summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAntonio Cunei <antonio.cunei@epfl.ch>2010-09-02 11:54:06 +0000
committerAntonio Cunei <antonio.cunei@epfl.ch>2010-09-02 11:54:06 +0000
commit918fb944b611ee08b5f5596c2fbc5123d2f09917 (patch)
treeb16a64b472f021b0f169ebf688b65f8492943691
parent13387444da947f6a9fa3770ec2acb227333da6cf (diff)
downloadscala-918fb944b611ee08b5f5596c2fbc5123d2f09917.tar.gz
scala-918fb944b611ee08b5f5596c2fbc5123d2f09917.tar.bz2
scala-918fb944b611ee08b5f5596c2fbc5123d2f09917.zip
Merged revisions 22108,22176-22177,22318,22589-...
Merged revisions 22108,22176-22177,22318,22589-22590,22595,22644,22657-22658,22723,22725, 22737-22738,22833-22835,22846,22858-22860,22872 via svnmerge from https://lampsvn.epfl.ch/svn-repos/scala/scala/trunk ........ r22108 | odersky | 2010-05-31 19:23:38 +0200 (Mon, 31 May 2010) | 1 line made hashset more robust for concurrent access to reduce eclipse race conditions. ........ r22176 | odersky | 2010-06-06 09:46:43 +0200 (Sun, 06 Jun 2010) | 2 lines Overwrote copyToArray for efficiency. ........ r22177 | odersky | 2010-06-06 09:47:21 +0200 (Sun, 06 Jun 2010) | 2 lines Fixed a typo in a use case ........ r22318 | odersky | 2010-06-16 17:36:08 +0200 (Wed, 16 Jun 2010) | 1 line Imporved printing of private[C] in TreePrinters. No review. ........ r22589 | odersky | 2010-07-19 15:55:09 +0200 (Mon, 19 Jul 2010) | 1 line new test files. ........ r22590 | odersky | 2010-07-19 15:56:03 +0200 (Mon, 19 Jul 2010) | 1 line Added `ask` method to compiler control to do fast trunaround computations on presentation compiler thread. ........ r22595 | odersky | 2010-07-19 17:19:45 +0200 (Mon, 19 Jul 2010) | 1 line added missing file. ........ r22644 | odersky | 2010-07-28 18:33:16 +0200 (Wed, 28 Jul 2010) | 1 line Fixes #3679. Review by milessabin. ........ r22657 | odersky | 2010-08-02 15:53:16 +0200 (Mon, 02 Aug 2010) | 1 line Revamped ScalaConversions. Fixes #3688. Also added JavaConverters object which allows for explicit asJava/asScala conversions in the scalaj style. Review by milessabin. ........ r22658 | odersky | 2010-08-02 15:53:58 +0200 (Mon, 02 Aug 2010) | 1 line Fixed some typoes/errors in doc comments. No review. ........ r22723 | odersky | 2010-08-10 17:47:15 +0200 (Tue, 10 Aug 2010) | 1 line Removed duplicate classes. No review. ........ r22725 | odersky | 2010-08-10 19:38:32 +0200 (Tue, 10 Aug 2010) | 1 line Added missing file for last checkin. ........ r22737 | odersky | 2010-08-12 11:02:46 +0200 (Thu, 12 Aug 2010) | 1 line Changes in docs and layout. No review. ........ r22738 | odersky | 2010-08-12 11:03:30 +0200 (Thu, 12 Aug 2010) | 1 line Fixed type soundness problem someone raised on hackers news. Test in override.scala. Review by moors. ........ r22833 | odersky | 2010-08-24 16:59:13 +0200 (Tue, 24 Aug 2010) | 1 line Fixes #3780. No review. ........ r22834 | odersky | 2010-08-24 16:59:54 +0200 (Tue, 24 Aug 2010) | 1 line new tests. No review. ........ r22835 | odersky | 2010-08-24 17:48:09 +0200 (Tue, 24 Aug 2010) | 1 line Closes #3776. No review. ........ r22846 | moors | 2010-08-26 18:16:54 +0200 (Thu, 26 Aug 2010) | 1 line this should fix our achy breaky build. no review ........ r22858 | odersky | 2010-08-30 17:56:13 +0200 (Mon, 30 Aug 2010) | 1 line added doc comment which makes things clearer when seen from Map or Set. ........ r22859 | odersky | 2010-08-30 17:59:05 +0200 (Mon, 30 Aug 2010) | 1 line removed author attribution, since no code from Stepan remains here. ........ r22860 | odersky | 2010-08-30 18:02:34 +0200 (Mon, 30 Aug 2010) | 1 line New wider interface of presentation compiler. Allows for partial responses and improves cancelling. See Response.scala for a usage example. ........ r22872 | odersky | 2010-08-31 17:37:55 +0200 (Tue, 31 Aug 2010) | 1 line Partial fix for #3774. The crash is gone but the program is rejected. A full fix will have to wait until a re-implementation of LUB/GLB along the lines of the DOT system. ........
-rw-r--r--src/compiler/scala/tools/nsc/Main.scala4
-rw-r--r--src/compiler/scala/tools/nsc/Phase.scala2
-rw-r--r--src/compiler/scala/tools/nsc/ast/TreePrinters.scala2
-rw-r--r--src/compiler/scala/tools/nsc/interactive/CompilerControl.scala35
-rw-r--r--src/compiler/scala/tools/nsc/interactive/ContextTrees.scala2
-rw-r--r--src/compiler/scala/tools/nsc/interactive/Global.scala75
-rw-r--r--src/compiler/scala/tools/nsc/interactive/REPL.scala12
-rw-r--r--src/compiler/scala/tools/nsc/interactive/Response.scala68
-rw-r--r--src/compiler/scala/tools/nsc/io/AbstractFile.scala6
-rw-r--r--src/compiler/scala/tools/nsc/symtab/Types.scala302
-rw-r--r--src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala2
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Analyzer.scala2
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Implicits.scala2
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/RefChecks.scala117
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Typers.scala2
-rw-r--r--src/compiler/scala/tools/nsc/util/HashSet.scala25
-rw-r--r--src/compiler/scala/tools/nsc/util/InterruptReq.scala28
-rw-r--r--src/compiler/scala/tools/nsc/util/WorkScheduler.scala30
-rw-r--r--src/library/scala/collection/JavaConversions.scala155
-rwxr-xr-xsrc/library/scala/collection/JavaConverters.scala456
-rw-r--r--src/library/scala/collection/TraversableOnce.scala7
-rw-r--r--src/library/scala/collection/generic/GenericTraversableTemplate.scala1
-rw-r--r--src/library/scala/collection/mutable/ArrayOps.scala8
-rw-r--r--src/library/scala/concurrent/SyncVar.scala2
-rwxr-xr-xsrc/library/scala/reflect/generic/UnPickler.scala2
-rwxr-xr-xsrc/library/scala/runtime/TraitSetter.java6
-rw-r--r--test/files/neg/override.check5
-rwxr-xr-xtest/files/neg/override.scala15
-rw-r--r--test/files/neg/t3774.check7
-rw-r--r--test/files/neg/t3774.scala5
-rw-r--r--test/files/neg/t3776.check4
-rw-r--r--test/files/neg/t3776.scala10
-rw-r--r--test/files/pos/t2133.scala18
-rwxr-xr-xtest/files/pos/t3174.scala14
-rwxr-xr-xtest/files/pos/t3174b.scala12
-rwxr-xr-xtest/files/pos/t3568.scala46
-rw-r--r--test/files/pos/t3688.scala9
-rw-r--r--test/files/run/t3763.scala3
-rwxr-xr-xtest/files/run/weakconform.scala4
-rwxr-xr-xtest/pending/run/t3609.scala11
40 files changed, 1218 insertions, 298 deletions
diff --git a/src/compiler/scala/tools/nsc/Main.scala b/src/compiler/scala/tools/nsc/Main.scala
index 948c5f6fb8..1e6699079d 100644
--- a/src/compiler/scala/tools/nsc/Main.scala
+++ b/src/compiler/scala/tools/nsc/Main.scala
@@ -8,8 +8,6 @@ package scala.tools.nsc
import java.io.File
import File.pathSeparator
-import scala.concurrent.SyncVar
-
import scala.tools.nsc.interactive.{ RefinedBuildManager, SimpleBuildManager }
import scala.tools.nsc.io.AbstractFile
import scala.tools.nsc.reporters.{Reporter, ConsoleReporter}
@@ -59,7 +57,7 @@ object Main extends AnyRef with EvalLoop {
import compiler.{ reporter => _, _ }
val sfs = command.files.map(getSourceFile(_))
- val reloaded = new SyncVar[Either[Unit, Throwable]]
+ val reloaded = new interactive.Response[Unit]
askReload(sfs, reloaded)
reloaded.get.right.toOption match {
case Some(ex) => reporter.cancelled = true // Causes exit code to be non-0
diff --git a/src/compiler/scala/tools/nsc/Phase.scala b/src/compiler/scala/tools/nsc/Phase.scala
index 882b96d84d..8cf93f6eea 100644
--- a/src/compiler/scala/tools/nsc/Phase.scala
+++ b/src/compiler/scala/tools/nsc/Phase.scala
@@ -24,7 +24,7 @@ abstract class Phase(val prev: Phase) {
def flagMask: Long = fmask
private var nx: Phase = this
- if (prev ne null) prev.nx = this
+ if ((prev ne null) && (prev ne NoPhase)) prev.nx = this
def next: Phase = nx
diff --git a/src/compiler/scala/tools/nsc/ast/TreePrinters.scala b/src/compiler/scala/tools/nsc/ast/TreePrinters.scala
index e1e7c90879..10b50db6d5 100644
--- a/src/compiler/scala/tools/nsc/ast/TreePrinters.scala
+++ b/src/compiler/scala/tools/nsc/ast/TreePrinters.scala
@@ -117,7 +117,7 @@ trait TreePrinters { trees: SymbolTable =>
def pw = tree.symbol.privateWithin
val args =
if (tree.symbol == NoSymbol) (mods.flags, mods.privateWithin)
- else if (pw == NoSymbol || pw == tree.symbol.owner) (tree.symbol.flags, "")
+ else if (pw == NoSymbol) (tree.symbol.flags, "")
else (tree.symbol.flags, pw.name)
printFlags(args._1, args._2.toString)
diff --git a/src/compiler/scala/tools/nsc/interactive/CompilerControl.scala b/src/compiler/scala/tools/nsc/interactive/CompilerControl.scala
index 26f7fb1115..b00da77b46 100644
--- a/src/compiler/scala/tools/nsc/interactive/CompilerControl.scala
+++ b/src/compiler/scala/tools/nsc/interactive/CompilerControl.scala
@@ -1,7 +1,6 @@
package scala.tools.nsc
package interactive
-import scala.concurrent.SyncVar
import scala.util.control.ControlThrowable
import scala.tools.nsc.io.AbstractFile
import scala.tools.nsc.util.{SourceFile, Position, WorkScheduler}
@@ -12,14 +11,6 @@ import scala.tools.nsc.ast._
*/
trait CompilerControl { self: Global =>
- /** Response {
- override def toString = "TypeMember("+sym+","+tpe+","+accessible+","+inherited+","+viaView+")"
- }{
- override def toString = "TypeMember("+sym+","+tpe+","+accessible+","+inherited+","+viaView+")"
- }wrapper to client
- */
- type Response[T] = SyncVar[Either[T, Throwable]]
-
abstract class WorkItem extends (() => Unit)
/** Info given for every member found by completion
@@ -30,8 +21,18 @@ trait CompilerControl { self: Global =>
val accessible: Boolean
}
- case class TypeMember(sym: Symbol, tpe: Type, accessible: Boolean, inherited: Boolean, viaView: Symbol) extends Member
- case class ScopeMember(sym: Symbol, tpe: Type, accessible: Boolean, viaImport: Tree) extends Member
+ case class TypeMember(
+ sym: Symbol,
+ tpe: Type,
+ accessible: Boolean,
+ inherited: Boolean,
+ viaView: Symbol) extends Member
+
+ case class ScopeMember(
+ sym: Symbol,
+ tpe: Type,
+ accessible: Boolean,
+ viaImport: Tree) extends Member
/** The scheduler by which client and compiler communicate
* Must be initialized before starting compilerRunner
@@ -82,7 +83,7 @@ trait CompilerControl { self: Global =>
override def toString = "reload "+sources
}
- /** Set sync var `result` to a fully attributed tree located at position `pos`
+ /** Set sync var `result` to the smallest fully attributed tree that encloses position `pos`.
*/
def askTypeAt(pos: Position, result: Response[Tree]) =
scheduler postWorkItem new WorkItem {
@@ -90,6 +91,8 @@ trait CompilerControl { self: Global =>
override def toString = "typeat "+pos.source+" "+pos.show
}
+ /** Set sync var `result` to the fully attributed & typechecked tree contained in `source`.
+ */
def askType(source: SourceFile, forceReload: Boolean, result: Response[Tree]) =
scheduler postWorkItem new WorkItem {
def apply() = self.getTypedTree(source, forceReload, result)
@@ -98,7 +101,6 @@ trait CompilerControl { self: Global =>
/** Set sync var `result' to list of members that are visible
* as members of the tree enclosing `pos`, possibly reachable by an implicit.
- * - if `selection` is false, as identifiers in the scope enclosing `pos`
*/
def askTypeCompletion(pos: Position, result: Response[List[Member]]) =
scheduler postWorkItem new WorkItem {
@@ -123,9 +125,6 @@ trait CompilerControl { self: Global =>
}
}
- /** Cancel currently pending high-priority jobs */
- def askCancel() = scheduler raise CancelActionReq
-
/** Cancel current compiler run and start a fresh one where everything will be re-typechecked
* (but not re-loaded).
*/
@@ -134,9 +133,11 @@ trait CompilerControl { self: Global =>
/** Tell the compile server to shutdown, and do not restart again */
def askShutdown() = scheduler raise ShutdownReq
+ /** Ask for a computation to be done quickly on the presentation compiler thread */
+ def ask[A](op: () => A): A = scheduler doQuickly op
+
// ---------------- Interpreted exceptions -------------------
- object CancelActionReq extends ControlThrowable
object FreshRunReq extends ControlThrowable
object ShutdownReq extends ControlThrowable
}
diff --git a/src/compiler/scala/tools/nsc/interactive/ContextTrees.scala b/src/compiler/scala/tools/nsc/interactive/ContextTrees.scala
index af50e4e468..af4052a2e2 100644
--- a/src/compiler/scala/tools/nsc/interactive/ContextTrees.scala
+++ b/src/compiler/scala/tools/nsc/interactive/ContextTrees.scala
@@ -17,7 +17,7 @@ trait ContextTrees { self: Global =>
* 3. The `pos` field of a context is the same as `context.tree.pos`, unless that
* position is transparent. In that case, `pos` equals the position of
* one of the solid descendants of `context.tree`.
- * 4. Children of a context have non-overlapping increasining positions.
+ * 4. Children of a context have non-overlapping increasing positions.
* 5. No context in the tree has a transparent position.
*/
class ContextTree(val pos: Position, val context: Context, val children: ArrayBuffer[ContextTree]) {
diff --git a/src/compiler/scala/tools/nsc/interactive/Global.scala b/src/compiler/scala/tools/nsc/interactive/Global.scala
index 2c174860e4..94322178b1 100644
--- a/src/compiler/scala/tools/nsc/interactive/Global.scala
+++ b/src/compiler/scala/tools/nsc/interactive/Global.scala
@@ -42,12 +42,17 @@ self =>
/** The currently active typer run */
private var currentTyperRun: TyperRun = _
- /** Is a background compiler run needed? */
+ /** Is a background compiler run needed?
+ * Note: outOfDate is true as long as there is a backgroud compile scheduled or going on.
+ */
private var outOfDate = false
/** Units compiled by a run with id >= minRunId are considered up-to-date */
private[interactive] var minRunId = 1
+ private val NoResponse: Response[_] = new Response[Any]
+ private var pendingResponse: Response[_] = NoResponse
+
/** Is a reload/background compiler currently running? */
private var acting = false
@@ -110,12 +115,19 @@ self =>
// ----------------- Polling ---------------------------------------
/** Called from runner thread and signalDone:
- * Poll for exceptions.
- * Poll for work reload/typedTreeAt/doFirst commands during background checking.
+ * Poll for interrupts and execute them immediately.
+ * Then, poll for exceptions and execute them.
+ * Then, poll for work reload/typedTreeAt/doFirst commands during background checking.
*/
def pollForWork() {
+ scheduler.pollInterrupt() match {
+ case Some(ir) =>
+ ir.execute(); pollForWork()
+ case _ =>
+ }
+ if (pendingResponse.isCancelled)
+ throw CancelException
scheduler.pollThrowable() match {
- case Some(ex @ CancelActionReq) => if (acting) throw ex
case Some(ex @ FreshRunReq) =>
currentTyperRun = newTyperRun
minRunId = currentRunId
@@ -131,9 +143,6 @@ self =>
if (debugIDE) println("picked up work item: "+action)
action()
if (debugIDE) println("done with work item: "+action)
- } catch {
- case CancelActionReq =>
- if (debugIDE) println("cancelled work item: "+action)
} finally {
if (debugIDE) println("quitting work item: "+action)
acting = false
@@ -220,10 +229,16 @@ self =>
private def backgroundCompile() {
if (debugIDE) inform("Starting new presentation compiler type checking pass")
reporter.reset
+
+ // remove any files in first that are no longer maintained by presentation compiler (i.e. closed)
firsts = firsts filter (s => unitOfFile contains (s.file))
+
val prefix = firsts map unitOf
+
val units = prefix ::: (unitOfFile.values.toList diff prefix) filter (!_.isUpToDate)
+
recompile(units)
+
if (debugIDE) inform("Everything is now up to date")
}
@@ -261,6 +276,8 @@ self =>
activeLocks = 0
currentTyperRun.typeCheck(unit)
unit.status = currentRunId
+ // todo: garbage collect any tyop-level symbols whose types are no longer valid for
+ // currentRunId
}
}
@@ -271,18 +288,24 @@ self =>
// ----------------- Implementations of client commands -----------------------
- def respond[T](result: Response[T])(op: => T): Unit =
+ def respond[T](result: Response[T])(op: => T): Unit = {
+ val prevResponse = pendingResponse
try {
- result set Left(op)
- return
+ pendingResponse = result
+ if (!result.isCancelled) result set op
} catch {
+ case CancelException =>
+ ;
case ex @ FreshRunReq =>
scheduler.postWorkItem(() => respond(result)(op))
throw ex
case ex =>
- result set Right(ex)
+ result raise ex
throw ex
+ } finally {
+ pendingResponse = prevResponse
}
+ }
/** Make sure a set of compilation units is loaded and parsed */
def reloadSources(sources: List[SourceFile]) {
@@ -298,8 +321,8 @@ self =>
/** Make sure a set of compilation units is loaded and parsed */
def reload(sources: List[SourceFile], result: Response[Unit]) {
respond(result)(reloadSources(sources))
- if (outOfDate) throw FreshRunReq
- else outOfDate = true
+ if (outOfDate) throw FreshRunReq // cancel background compile
+ else outOfDate = true // proceed normally and enable new background compile
}
/** A fully attributed tree located at position `pos` */
@@ -333,7 +356,7 @@ self =>
def stabilizedType(tree: Tree): Type = tree match {
case Ident(_) if tree.symbol.isStable => singleType(NoPrefix, tree.symbol)
- case Select(qual, _) if qual.tpe != null && tree.symbol.isStable => singleType(qual.tpe, tree.symbol)
+ case Select(qual, _) if qual.tpe != null && tree.symbol.isStable => singleType(qual.tpe, tree.symbol)
case Import(expr, selectors) =>
tree.symbol.info match {
case analyzer.ImportType(expr) => expr match {
@@ -399,11 +422,16 @@ self =>
def typeMembers(pos: Position): List[TypeMember] = {
var tree = typedTreeAt(pos)
+
+ // Let's say you have something like val x: List[Int] and ypu want to get completion after List
+ // Then the tree found at first is a TypeTree, ????
tree match {
- case tt : TypeTree => tree = tt.original
+ case tt : TypeTree if tt.original != null => tree = tt.original // ???
case _ =>
}
+ // if tree consists of just x. or x.fo where fo is not yet a full member name
+ // ignore the selection and look in just x.
tree match {
case Select(qual, name) if tree.tpe == ErrorType => tree = qual
case _ =>
@@ -419,6 +447,7 @@ self =>
val superAccess = tree.isInstanceOf[Super]
val scope = new Scope
val members = new LinkedHashMap[Symbol, TypeMember]
+
def addTypeMember(sym: Symbol, pre: Type, inherited: Boolean, viaView: Symbol) {
val symtpe = pre.memberType(sym)
if (scope.lookupAll(sym.name) forall (sym => !(members(sym).tpe matches symtpe))) {
@@ -431,22 +460,28 @@ self =>
viaView)
}
}
+
+ /** Create a fucntion application of a given view function to `tree` and typechecked it.
+ */
def viewApply(view: SearchResult): Tree = {
assert(view.tree != EmptyTree)
try {
- analyzer.newTyper(context.makeImplicit(false)).typed(Apply(view.tree, List(tree)) setPos tree.pos)
+ analyzer.newTyper(context.makeImplicit(reportAmbiguousErrors = false))
+ .typed(Apply(view.tree, List(tree)) setPos tree.pos)
} catch {
case ex: TypeError => EmptyTree
}
}
+
val pre = stabilizedType(tree)
val ownerTpe = if (tree.tpe != null) tree.tpe else pre
+
for (sym <- ownerTpe.decls)
addTypeMember(sym, pre, false, NoSymbol)
for (sym <- ownerTpe.members)
addTypeMember(sym, pre, true, NoSymbol)
val applicableViews: List[SearchResult] =
- new ImplicitSearch(tree, functionType(List(ownerTpe), AnyClass.tpe), true, context.makeImplicit(false))
+ new ImplicitSearch(tree, functionType(List(ownerTpe), AnyClass.tpe), isView = true, context.makeImplicit(reportAmbiguousErrors = false))
.allImplicits
for (view <- applicableViews) {
val vtree = viewApply(view)
@@ -499,7 +534,7 @@ self =>
tree
} else {
val unit = unitOf(pos)
- assert(unit.status >= JustParsed)
+ assert(unit.isParsed)
unit.targetPos = pos
try {
println("starting targeted type check")
@@ -515,7 +550,7 @@ self =>
}
def typedTree(unit: RichCompilationUnit): Tree = {
- assert(unit.status >= JustParsed)
+ assert(unit.isParsed)
unit.targetPos = NoPosition
typeCheck(unit)
unit.body
@@ -539,3 +574,5 @@ self =>
assert(globalPhase.id == 0)
}
+object CancelException extends Exception
+
diff --git a/src/compiler/scala/tools/nsc/interactive/REPL.scala b/src/compiler/scala/tools/nsc/interactive/REPL.scala
index 5589ddb9b1..775b979851 100644
--- a/src/compiler/scala/tools/nsc/interactive/REPL.scala
+++ b/src/compiler/scala/tools/nsc/interactive/REPL.scala
@@ -80,9 +80,9 @@ object REPL {
* complete file off1 off2?
*/
def run(comp: Global) {
- val reloadResult = new comp.Response[Unit]
- val typeatResult = new comp.Response[comp.Tree]
- val completeResult = new comp.Response[List[comp.Member]]
+ val reloadResult = new Response[Unit]
+ val typeatResult = new Response[comp.Tree]
+ val completeResult = new Response[List[comp.Member]]
def makePos(file: String, off1: String, off2: String) = {
val source = toSourceFile(file)
comp.rangePos(source, off1.toInt, off1.toInt, off2.toInt)
@@ -118,11 +118,11 @@ object REPL {
def toSourceFile(name: String) = new BatchSourceFile(new PlainFile(new java.io.File(name)))
- def show[T](svar: SyncVar[Either[T, Throwable]]) {
+ def show[T](svar: Response[T]) {
svar.get match {
case Left(result) => println("==> "+result)
- case Right(exc/*: Throwable ??*/) => exc.printStackTrace; println("ERROR: "+exc)
+ case Right(exc) => exc.printStackTrace; println("ERROR: "+exc)
}
- svar.unset()
+ svar.clear()
}
}
diff --git a/src/compiler/scala/tools/nsc/interactive/Response.scala b/src/compiler/scala/tools/nsc/interactive/Response.scala
new file mode 100644
index 0000000000..96e474a34a
--- /dev/null
+++ b/src/compiler/scala/tools/nsc/interactive/Response.scala
@@ -0,0 +1,68 @@
+package scala.tools.nsc
+package interactive
+
+import scala.concurrent.SyncVar
+
+/** Typical interaction, given a predicate <user-input>, a function <display>,
+ * and an exception handler <handle>:
+ *
+ * val TIMEOUT = 100 // (milliseconds) or something like that
+ * val r = new Response()
+ * while (!r.isComplete && !r.isCancelled) {
+ * if (<user-input>) r.cancel()
+ * else r.get(TIMEOUT) match {
+ * case Some(Left(data)) => <display>(data)
+ * case Some(Right(exc)) => <handle>(exc)
+ * case None =>
+ * }
+ * }
+ */
+class Response[T] {
+
+ private val data = new SyncVar[Either[T, Throwable]]
+ private var complete = false
+ private var cancelled = false
+
+ /** Set provisional data, more to come
+ */
+ def setProvisionally(x: T) =
+ data.set(Left(x))
+
+ /** Set final data, and mark resposne as complete.
+ */
+ def set(x: T) = data.synchronized {
+ data.set(Left(x))
+ complete = true
+ }
+
+ def raise(exc: Throwable) = data.synchronized {
+ data.set(Right(exc))
+ complete = true
+ }
+
+ /** Get data, wait as long as necessary
+ */
+ def get: Either[T, Throwable] = data.get
+
+ /** Optionally get data within `timeout` milliseconds.
+ */
+ def get(timeout: Long): Option[Either[T, Throwable]] = data.get(timeout)
+
+ /** Final data set was stored
+ */
+ def isComplete = data.synchronized { complete }
+
+ /** Cancel action computing this response
+ */
+ def cancel() = data.synchronized { cancelled = true }
+
+ /** A cancel request for this response has been issued
+ */
+ def isCancelled = data.synchronized { cancelled }
+
+ def clear() = data.synchronized {
+ data.unset()
+ complete = false
+ cancelled = false
+ }
+}
diff --git a/src/compiler/scala/tools/nsc/io/AbstractFile.scala b/src/compiler/scala/tools/nsc/io/AbstractFile.scala
index 5d4f7b8464..6f350233e2 100644
--- a/src/compiler/scala/tools/nsc/io/AbstractFile.scala
+++ b/src/compiler/scala/tools/nsc/io/AbstractFile.scala
@@ -107,9 +107,7 @@ abstract class AbstractFile extends AnyRef with Iterable[AbstractFile] {
def underlyingSource: Option[AbstractFile] = None
/** Does this abstract file denote an existing file? */
- def exists: Boolean =
- if (file ne null) file.exists
- else true
+ def exists: Boolean = (file eq null) || file.exists
/** Does this abstract file represent something which can contain classfiles? */
def isClassContainer = isDirectory || (sfile exists (Path isJarOrZip _))
@@ -132,7 +130,7 @@ abstract class AbstractFile extends AnyRef with Iterable[AbstractFile] {
/** Returns an output stream for writing the file */
def output: OutputStream
- /** Returns an unbuffered output stream for writing the file - defaults to out */
+ /** Returns a buffered output stream for writing the file - defaults to out */
def bufferedOutput: BufferedOutputStream = new BufferedOutputStream(output)
/** size of this file if it is a concrete file. */
diff --git a/src/compiler/scala/tools/nsc/symtab/Types.scala b/src/compiler/scala/tools/nsc/symtab/Types.scala
index 7aed4cd648..b3d2c56285 100644
--- a/src/compiler/scala/tools/nsc/symtab/Types.scala
+++ b/src/compiler/scala/tools/nsc/symtab/Types.scala
@@ -8,7 +8,7 @@ package scala.tools.nsc
package symtab
import scala.collection.immutable
-import scala.collection.mutable.{ListBuffer, WeakHashMap}
+import scala.collection.mutable.{ListBuffer, HashMap, WeakHashMap}
import ast.TreeGen
import util.{HashSet, Position, NoPosition}
import util.Statistics._
@@ -4864,7 +4864,15 @@ A type's typeSymbol should never be inspected directly.
isNumericValueType(tp1) && isNumericValueType(tp2) &&
isNumericSubClass(tp1.typeSymbol, tp2.typeSymbol)
- def lub(ts: List[Type]): Type = lub(ts, lubDepth(ts))
+ private val lubResults = new HashMap[(Int, List[Type]), Type]
+ private val glbResults = new HashMap[(Int, List[Type]), Type]
+
+ def lub(ts: List[Type]): Type = try {
+ lub(ts, lubDepth(ts))
+ } finally {
+ lubResults.clear()
+ glbResults.clear()
+ }
/** The least upper bound wrt &lt;:&lt; of a list of types */
def lub(ts: List[Type], depth: Int): Type = {
@@ -4879,72 +4887,83 @@ A type's typeSymbol should never be inspected directly.
MethodType(params, lub0(matchingRestypes(ts, params map (_.tpe))))
case ts @ TypeBounds(_, _) :: rest =>
TypeBounds(glb(ts map (_.bounds.lo), depth), lub(ts map (_.bounds.hi), depth))
- case ts0 =>
- val (ts, tparams) = stripExistentialsAndTypeVars(ts0)
- val bts: List[BaseTypeSeq] = ts map (_.baseTypeSeq)
- val lubBaseTypes: List[Type] = lubBaseTypeSeq(bts, depth)
- val lubParents = spanningTypes(lubBaseTypes)
- val lubOwner = commonOwner(ts)
- val lubBase = intersectionType(lubParents, lubOwner)
- val lubType =
- if (phase.erasedTypes || depth == 0) lubBase
- else {
- val lubRefined = refinedType(lubParents, lubOwner)
- val lubThisType = lubRefined.typeSymbol.thisType
- val narrowts = ts map (_.narrow)
- def lubsym(proto: Symbol): Symbol = {
- val prototp = lubThisType.memberInfo(proto)
- val syms = narrowts map (t =>
- t.nonPrivateMember(proto.name).suchThat(sym =>
- sym.tpe matches prototp.substThis(lubThisType.typeSymbol, t)))
- if (syms contains NoSymbol) NoSymbol
+ case ts =>
+ lubResults get (depth, ts) match {
+ case Some(lubType) =>
+ lubType
+ case None =>
+ lubResults((depth, ts)) = AnyClass.tpe
+ val res = if (depth < 0) AnyClass.tpe else lub1(ts)
+ lubResults((depth, ts)) = res
+ res
+ }
+ }
+ def lub1(ts0: List[Type]): Type = {
+ val (ts, tparams) = stripExistentialsAndTypeVars(ts0)
+ val bts: List[BaseTypeSeq] = ts map (_.baseTypeSeq)
+ val lubBaseTypes: List[Type] = lubBaseTypeSeq(bts, depth)
+ val lubParents = spanningTypes(lubBaseTypes)
+ val lubOwner = commonOwner(ts)
+ val lubBase = intersectionType(lubParents, lubOwner)
+ val lubType =
+ if (phase.erasedTypes || depth == 0) lubBase
+ else {
+ val lubRefined = refinedType(lubParents, lubOwner)
+ val lubThisType = lubRefined.typeSymbol.thisType
+ val narrowts = ts map (_.narrow)
+ def lubsym(proto: Symbol): Symbol = {
+ val prototp = lubThisType.memberInfo(proto)
+ val syms = narrowts map (t =>
+ t.nonPrivateMember(proto.name).suchThat(sym =>
+ sym.tpe matches prototp.substThis(lubThisType.typeSymbol, t)))
+ if (syms contains NoSymbol) NoSymbol
+ else {
+ val symtypes =
+ (narrowts, syms).zipped map ((t, sym) => t.memberInfo(sym).substThis(t.typeSymbol, lubThisType))
+ if (proto.isTerm) // possible problem: owner of info is still the old one, instead of new refinement class
+ proto.cloneSymbol(lubRefined.typeSymbol).setInfoOwnerAdjusted(lub(symtypes, decr(depth)))
+ else if (symtypes.tail forall (symtypes.head =:=))
+ proto.cloneSymbol(lubRefined.typeSymbol).setInfoOwnerAdjusted(symtypes.head)
else {
- val symtypes =
- (narrowts, syms).zipped map ((t, sym) => t.memberInfo(sym).substThis(t.typeSymbol, lubThisType))
- if (proto.isTerm) // possible problem: owner of info is still the old one, instead of new refinement class
- proto.cloneSymbol(lubRefined.typeSymbol).setInfoOwnerAdjusted(lub(symtypes, decr(depth)))
- else if (symtypes.tail forall (symtypes.head =:=))
- proto.cloneSymbol(lubRefined.typeSymbol).setInfoOwnerAdjusted(symtypes.head)
- else {
- def lubBounds(bnds: List[TypeBounds]): TypeBounds =
- TypeBounds(glb(bnds map (_.lo), decr(depth)), lub(bnds map (_.hi), decr(depth)))
- lubRefined.typeSymbol.newAbstractType(proto.pos, proto.name)
- .setInfoOwnerAdjusted(lubBounds(symtypes map (_.bounds)))
- }
+ def lubBounds(bnds: List[TypeBounds]): TypeBounds =
+ TypeBounds(glb(bnds map (_.lo), decr(depth)), lub(bnds map (_.hi), decr(depth)))
+ lubRefined.typeSymbol.newAbstractType(proto.pos, proto.name)
+ .setInfoOwnerAdjusted(lubBounds(symtypes map (_.bounds)))
}
}
- def refines(tp: Type, sym: Symbol): Boolean = {
- val syms = tp.nonPrivateMember(sym.name).alternatives;
- !syms.isEmpty && (syms forall (alt =>
- // todo alt != sym is strictly speaking not correct, but without it we lose
- // efficiency.
- alt != sym && !specializesSym(lubThisType, sym, tp, alt)))
- }
- for (sym <- lubBase.nonPrivateMembers) {
- // add a refinement symbol for all non-class members of lubBase
- // which are refined by every type in ts.
- if (!sym.isClass && !sym.isConstructor && (narrowts forall (t => refines(t, sym))))
- try {
- val lsym = lubsym(sym)
- if (lsym != NoSymbol) addMember(lubThisType, lubRefined, lubsym(sym))
- } catch {
- case ex: NoCommonType =>
- }
- }
- if (lubRefined.decls.isEmpty) lubBase
- else {
+ }
+ def refines(tp: Type, sym: Symbol): Boolean = {
+ val syms = tp.nonPrivateMember(sym.name).alternatives;
+ !syms.isEmpty && (syms forall (alt =>
+ // todo alt != sym is strictly speaking not correct, but without it we lose
+ // efficiency.
+ alt != sym && !specializesSym(lubThisType, sym, tp, alt)))
+ }
+ for (sym <- lubBase.nonPrivateMembers) {
+ // add a refinement symbol for all non-class members of lubBase
+ // which are refined by every type in ts.
+ if (!sym.isClass && !sym.isConstructor && (narrowts forall (t => refines(t, sym))))
+ try {
+ val lsym = lubsym(sym)
+ if (lsym != NoSymbol) addMember(lubThisType, lubRefined, lubsym(sym))
+ } catch {
+ case ex: NoCommonType =>
+ }
+ }
+ if (lubRefined.decls.isEmpty) lubBase
+ else {
// println("refined lub of "+ts+"/"+narrowts+" is "+lubRefined+", baseclasses = "+(ts map (_.baseTypeSeq) map (_.toList)))
- lubRefined
- }
+ lubRefined
}
- existentialAbstraction(tparams, lubType)
+ }
+ existentialAbstraction(tparams, lubType)
}
if (printLubs) {
println(indent + "lub of " + ts + " at depth "+depth)//debug
indent = indent + " "
assert(indent.length <= 100)
}
- val res = if (depth < 0) AnyClass.tpe else lub0(ts)
+ val res = lub0(ts)
if (printLubs) {
indent = indent.substring(0, indent.length() - 2)
println(indent + "lub of " + ts + " is " + res)//debug
@@ -4963,7 +4982,12 @@ A type's typeSymbol should never be inspected directly.
private var globalGlbDepth = 0
private final val globalGlbLimit = 2
- def glb(ts: List[Type]): Type = glb(ts, lubDepth(ts))
+ def glb(ts: List[Type]): Type = try {
+ glb(ts, lubDepth(ts))
+ } finally {
+ lubResults.clear()
+ glbResults.clear()
+ }
/** The greatest lower bound wrt &lt;:&lt; of a list of types */
private def glb(ts: List[Type], depth: Int): Type = {
@@ -4978,85 +5002,99 @@ A type's typeSymbol should never be inspected directly.
MethodType(params, glb0(matchingRestypes(ts, params map (_.tpe))))
case ts @ TypeBounds(_, _) :: rest =>
TypeBounds(lub(ts map (_.bounds.lo), depth), glb(ts map (_.bounds.hi), depth))
- case ts0 =>
- try {
- val (ts, tparams) = stripExistentialsAndTypeVars(ts0)
- val glbOwner = commonOwner(ts)
- def refinedToParents(t: Type): List[Type] = t match {
- case RefinedType(ps, _) => ps flatMap refinedToParents
- case _ => List(t)
- }
- def refinedToDecls(t: Type): List[Scope] = t match {
- case RefinedType(ps, decls) =>
- val dss = ps flatMap refinedToDecls
- if (decls.isEmpty) dss else decls :: dss
- case _ => List()
- }
- val ts1 = ts flatMap refinedToParents
- val glbBase = intersectionType(ts1, glbOwner)
- val glbType =
- if (phase.erasedTypes || depth == 0) glbBase
- else {
- val glbRefined = refinedType(ts1, glbOwner)
- val glbThisType = glbRefined.typeSymbol.thisType
- def glbsym(proto: Symbol): Symbol = {
- val prototp = glbThisType.memberInfo(proto)
- val syms = for (t <- ts;
- alt <- (t.nonPrivateMember(proto.name).alternatives);
- if glbThisType.memberInfo(alt) matches prototp
- ) yield alt
- val symtypes = syms map glbThisType.memberInfo
- assert(!symtypes.isEmpty)
- proto.cloneSymbol(glbRefined.typeSymbol).setInfoOwnerAdjusted(
- if (proto.isTerm) glb(symtypes, decr(depth))
- else {
- def isTypeBound(tp: Type) = tp match {
- case TypeBounds(_, _) => true
- case _ => false
- }
- def glbBounds(bnds: List[Type]): TypeBounds = {
- val lo = lub(bnds map (_.bounds.lo), decr(depth))
- val hi = glb(bnds map (_.bounds.hi), decr(depth))
- if (lo <:< hi) TypeBounds(lo, hi)
- else throw GlbFailure
+ case ts =>
+ glbResults get (depth, ts) match {
+ case Some(glbType) =>
+ glbType
+ case _ =>
+ glbResults((depth, ts)) = NothingClass.tpe
+ val res = if (depth < 0) NothingClass.tpe else glb1(ts)
+ glbResults((depth, ts)) = res
+ res
+ }
+ }
+ def glb1(ts0: List[Type]): Type = {
+ try {
+ val (ts, tparams) = stripExistentialsAndTypeVars(ts0)
+ val glbOwner = commonOwner(ts)
+ def refinedToParents(t: Type): List[Type] = t match {
+ case RefinedType(ps, _) => ps flatMap refinedToParents
+ case _ => List(t)
+ }
+ def refinedToDecls(t: Type): List[Scope] = t match {
+ case RefinedType(ps, decls) =>
+ val dss = ps flatMap refinedToDecls
+ if (decls.isEmpty) dss else decls :: dss
+ case _ => List()
+ }
+ val ts1 = ts flatMap refinedToParents
+ val glbBase = intersectionType(ts1, glbOwner)
+ val glbType =
+ if (phase.erasedTypes || depth == 0) glbBase
+ else {
+ val glbRefined = refinedType(ts1, glbOwner)
+ val glbThisType = glbRefined.typeSymbol.thisType
+ def glbsym(proto: Symbol): Symbol = {
+ val prototp = glbThisType.memberInfo(proto)
+ val syms = for (t <- ts;
+ alt <- (t.nonPrivateMember(proto.name).alternatives);
+ if glbThisType.memberInfo(alt) matches prototp
+ ) yield alt
+ val symtypes = syms map glbThisType.memberInfo
+ assert(!symtypes.isEmpty)
+ proto.cloneSymbol(glbRefined.typeSymbol).setInfoOwnerAdjusted(
+ if (proto.isTerm) glb(symtypes, decr(depth))
+ else {
+ def isTypeBound(tp: Type) = tp match {
+ case TypeBounds(_, _) => true
+ case _ => false
+ }
+ def glbBounds(bnds: List[Type]): TypeBounds = {
+ val lo = lub(bnds map (_.bounds.lo), decr(depth))
+ val hi = glb(bnds map (_.bounds.hi), decr(depth))
+ if (lo <:< hi) TypeBounds(lo, hi)
+ else throw GlbFailure
+ }
+ val symbounds = symtypes filter isTypeBound
+ var result: Type =
+ if (symbounds.isEmpty)
+ TypeBounds(NothingClass.tpe, AnyClass.tpe)
+ else glbBounds(symbounds)
+ for (t <- symtypes if !isTypeBound(t))
+ if (result.bounds containsType t) result = t
+ else throw GlbFailure
+ result
+ })
+ }
+ if (globalGlbDepth < globalGlbLimit)
+ try {
+ globalGlbDepth += 1
+ val dss = ts flatMap refinedToDecls
+ for (ds <- dss; val sym <- ds.iterator)
+ if (globalGlbDepth < globalGlbLimit && !(glbThisType specializes sym))
+ try {
+ addMember(glbThisType, glbRefined, glbsym(sym))
+ } catch {
+ case ex: NoCommonType =>
}
- val symbounds = symtypes filter isTypeBound
- var result: Type =
- if (symbounds.isEmpty)
- TypeBounds(NothingClass.tpe, AnyClass.tpe)
- else glbBounds(symbounds)
- for (t <- symtypes if !isTypeBound(t))
- if (result.bounds containsType t) result = t
- else throw GlbFailure
- result
- })
+ } finally {
+ globalGlbDepth -= 1
}
- if (globalGlbDepth < globalGlbLimit)
- try {
- globalGlbDepth += 1
- val dss = ts flatMap refinedToDecls
- for (ds <- dss; val sym <- ds.iterator)
- if (globalGlbDepth < globalGlbLimit && !(glbThisType specializes sym))
- try {
- addMember(glbThisType, glbRefined, glbsym(sym))
- } catch {
- case ex: NoCommonType =>
- }
- } finally {
- globalGlbDepth -= 1
- }
- if (glbRefined.decls.isEmpty) glbBase else glbRefined
- }
- existentialAbstraction(tparams, glbType)
- } catch {
- case GlbFailure =>
- if (ts forall (t => NullClass.tpe <:< t)) NullClass.tpe
- else NothingClass.tpe
- }
+ if (glbRefined.decls.isEmpty) glbBase else glbRefined
+ }
+ existentialAbstraction(tparams, glbType)
+ } catch {
+ case GlbFailure =>
+ if (ts forall (t => NullClass.tpe <:< t)) NullClass.tpe
+ else NothingClass.tpe
+ }
}
// if (settings.debug.value) { println(indent + "glb of " + ts + " at depth "+depth); indent = indent + " " } //DEBUG
- val res = if (depth < 0) NothingClass.tpe else glb0(ts)
+
+ val res = glb0(ts)
+
// if (settings.debug.value) { indent = indent.substring(0, indent.length() - 2); log(indent + "glb of " + ts + " is " + res) }//DEBUG
+
if (ts exists (_.isNotNull)) res.notNull else res
}
diff --git a/src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala b/src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala
index f78022bdaa..72868774e5 100644
--- a/src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala
+++ b/src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala
@@ -161,7 +161,7 @@ abstract class ExplicitOuter extends InfoTransform
// On the other hand, mixing in the trait into a separately compiled
// class needs to have a common naming scheme, independently of whether
// the field was accessed from an inner class or not. See #2946
- if (sym.owner.isTrait && (sym hasFlag LOCAL) && (sym.getter(sym.owner) == NoSymbol))
+ if (sym.owner.isTrait && (sym hasFlag LOCAL) && (sym.getter(sym.owner.toInterface) == NoSymbol))
sym.makeNotPrivate(sym.owner)
tp
}
diff --git a/src/compiler/scala/tools/nsc/typechecker/Analyzer.scala b/src/compiler/scala/tools/nsc/typechecker/Analyzer.scala
index 63e5a9fb25..80f833f03d 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Analyzer.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Analyzer.scala
@@ -74,7 +74,7 @@ trait Analyzer extends AnyRef
val runsRightAfter = Some("packageobjects")
def newPhase(_prev: Phase): StdPhase = new StdPhase(_prev) {
override def keepsTypeParams = false
- resetTyper()
+ resetTyper() // this does not in fact to the reset for each compilation run!
override def run {
val start = startTimer(typerNanos)
currentRun.units foreach applyPhase
diff --git a/src/compiler/scala/tools/nsc/typechecker/Implicits.scala b/src/compiler/scala/tools/nsc/typechecker/Implicits.scala
index 0056dcd917..63b971d2fd 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Implicits.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Implicits.scala
@@ -409,7 +409,7 @@ self: Analyzer =>
if (mt.isImplicit) 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)
+ matchesPtView(normalize(qtpe), ptarg, ptres, undet)
case Function1(arg1, res1) =>
matchesArgRes(arg1, res1, ptarg, ptres, undet)
case _ => false
diff --git a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala
index 74114b455e..c91bac3d7f 100644
--- a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala
@@ -80,6 +80,7 @@ abstract class RefChecks extends InfoTransform {
var localTyper: analyzer.Typer = typer;
var currentApplication: Tree = EmptyTree
var inPattern: Boolean = false
+ var checkedCombinations = Set[List[Type]]()
// only one overloaded alternative is allowed to define default arguments
private def checkDefaultsInOverloaded(clazz: Symbol) {
@@ -186,7 +187,7 @@ abstract class RefChecks extends InfoTransform {
* 4. Check that every member with an `override' modifier
* overrides some other member.
*/
- private def checkAllOverrides(clazz: Symbol) {
+ private def checkAllOverrides(clazz: Symbol, typesOnly: Boolean = false) {
case class MixinOverrideError(member: Symbol, msg: String)
@@ -299,56 +300,65 @@ abstract class RefChecks extends InfoTransform {
def intersectionIsEmpty(syms1: List[Symbol], syms2: List[Symbol]) =
!(syms1 exists (syms2 contains))
- if (member hasFlag PRIVATE) { // (1.1)
- overrideError("has weaker access privileges; it should not be private")
- }
- val mb = member.accessBoundary(member.owner)
- val ob = other.accessBoundary(member.owner)
- if (mb != RootClass && mb != NoSymbol && // todo: change
- (ob == RootClass || ob == NoSymbol || !ob.hasTransOwner(mb) ||
- (other hasFlag PROTECTED) && !(member hasFlag PROTECTED))) {
- overrideAccessError()
+ if (typesOnly) checkOverrideTypes()
+ else {
+ if (member hasFlag PRIVATE) { // (1.1)
+ overrideError("has weaker access privileges; it should not be private")
+ }
+ val mb = member.accessBoundary(member.owner)
+ val ob = other.accessBoundary(member.owner)
+ if (mb != RootClass && mb != NoSymbol && // todo: change
+ (ob == RootClass || ob == NoSymbol || !ob.hasTransOwner(mb) ||
+ (other hasFlag PROTECTED) && !(member hasFlag PROTECTED))) {
+ overrideAccessError()
+ }
+ else if (other.isClass || other.isModule) {
+ overrideError("cannot be used here - classes and objects cannot be overridden");
+ } else if (!other.isDeferred && (member.isClass || member.isModule)) {
+ overrideError("cannot be used here - classes and objects can only override abstract types");
+ } else if (other hasFlag FINAL) { // (1.2)
+ overrideError("cannot override final member");
+ } else if (!other.isDeferred && !(member hasFlag (OVERRIDE | ABSOVERRIDE | SYNTHETIC))) { // (1.3), SYNTHETIC because of DEVIRTUALIZE
+ overrideError("needs `override' modifier");
+ } else if ((other hasFlag ABSOVERRIDE) && other.isIncompleteIn(clazz) && !(member hasFlag ABSOVERRIDE)) {
+ overrideError("needs `abstract override' modifiers")
+ } else if ((member hasFlag (OVERRIDE | ABSOVERRIDE)) &&
+ (other hasFlag ACCESSOR) && other.accessed.isVariable && !other.accessed.hasFlag(LAZY)) {
+ overrideError("cannot override a mutable variable")
+ } else if ((member hasFlag (OVERRIDE | ABSOVERRIDE)) &&
+ !(member.owner.thisType.baseClasses exists (_ isSubClass other.owner)) &&
+ !member.isDeferred && !other.isDeferred &&
+ intersectionIsEmpty(member.allOverriddenSymbols, other.allOverriddenSymbols)) {
+ overrideError("cannot override a concrete member without a third member that's overridden by both "+
+ "(this rule is designed to prevent ``accidental overrides'')")
+ } else if (other.isStable && !member.isStable) { // (1.4)
+ overrideError("needs to be a stable, immutable value")
+ } else if (member.isValue && (member hasFlag LAZY) &&
+ other.isValue && !other.isSourceMethod && !other.isDeferred && !(other hasFlag LAZY)) {
+ overrideError("cannot override a concrete non-lazy value")
+ } else if (other.isValue && (other hasFlag LAZY) && !other.isSourceMethod && !other.isDeferred &&
+ member.isValue && !(member hasFlag LAZY)) {
+ overrideError("must be declared lazy to override a concrete lazy value")
+ } else {
+ checkOverrideTypes()
+ }
}
- else if (other.isClass || other.isModule) {
- overrideError("cannot be used here - classes and objects cannot be overridden");
- } else if (!other.isDeferred && (member.isClass || member.isModule)) {
- overrideError("cannot be used here - classes and objects can only override abstract types");
- } else if (other hasFlag FINAL) { // (1.2)
- overrideError("cannot override final member");
- } else if (!other.isDeferred && !(member hasFlag (OVERRIDE | ABSOVERRIDE | SYNTHETIC))) { // (1.3), SYNTHETIC because of DEVIRTUALIZE
- overrideError("needs `override' modifier");
- } else if ((other hasFlag ABSOVERRIDE) && other.isIncompleteIn(clazz) && !(member hasFlag ABSOVERRIDE)) {
- overrideError("needs `abstract override' modifiers")
- } else if ((member hasFlag (OVERRIDE | ABSOVERRIDE)) &&
- (other hasFlag ACCESSOR) && other.accessed.isVariable && !other.accessed.hasFlag(LAZY)) {
- overrideError("cannot override a mutable variable")
- } else if ((member hasFlag (OVERRIDE | ABSOVERRIDE)) &&
- !(member.owner.thisType.baseClasses exists (_ isSubClass other.owner)) &&
- !member.isDeferred && !other.isDeferred &&
- intersectionIsEmpty(member.allOverriddenSymbols, other.allOverriddenSymbols)) {
- overrideError("cannot override a concrete member without a third member that's overridden by both "+
- "(this rule is designed to prevent ``accidental overrides'')")
- } else if (other.isStable && !member.isStable) { // (1.4)
- overrideError("needs to be a stable, immutable value")
- } else if (member.isValue && (member hasFlag LAZY) &&
- other.isValue && !other.isSourceMethod && !other.isDeferred && !(other hasFlag LAZY)) {
- overrideError("cannot override a concrete non-lazy value")
- } else if (other.isValue && (other hasFlag LAZY) && !other.isSourceMethod && !other.isDeferred &&
- member.isValue && !(member hasFlag LAZY)) {
- overrideError("must be declared lazy to override a concrete lazy value")
- } else {
+
+ def checkOverrideTypes() {
if (other.isAliasType) {
- //if (!member.typeParams.isEmpty) // (1.5) @MAT
+ //if (!member.typeParams.isEmpty) (1.5) @MAT
// overrideError("may not be parameterized");
- //if (!other.typeParams.isEmpty) // (1.5) @MAT
+ //if (!other.typeParams.isEmpty) (1.5) @MAT
// overrideError("may not override parameterized type");
// @M: substSym
+
if (!(self.memberType(member).substSym(member.typeParams, other.typeParams) =:= self.memberType(other))) // (1.6)
overrideTypeError();
} else if (other.isAbstractType) {
//if (!member.typeParams.isEmpty) // (1.7) @MAT
// overrideError("may not be parameterized");
- var memberTp = self.memberType(member)
+
+ val memberTp = self.memberType(member)
val otherTp = self.memberInfo(other)
if (!(otherTp.bounds containsType memberTp)) { // (1.7.1)
overrideTypeError(); // todo: do an explaintypes with bounds here
@@ -369,7 +379,7 @@ abstract class RefChecks extends InfoTransform {
// this overlaps somewhat with validateVariance
if(member.isAliasType) {
val kindErrors = typer.infer.checkKindBounds(List(member), List(memberTp.normalize), self, member.owner)
-
+2
if(!kindErrors.isEmpty)
unit.error(member.pos,
"The kind of the right-hand side "+memberTp.normalize+" of "+member.keyString+" "+
@@ -381,10 +391,25 @@ abstract class RefChecks extends InfoTransform {
}
} else if (other.isTerm) {
other.cookJavaRawInfo() // #2454
-
- if (!overridesType(self.memberInfo(member), self.memberInfo(other))) { // 8
+ val memberTp = self.memberType(member)
+ val otherTp = self.memberType(other)
+ if (!overridesType(memberTp, otherTp)) { // 8
overrideTypeError()
- explainTypes(self.memberInfo(member), self.memberInfo(other))
+ explainTypes(memberTp, otherTp)
+ }
+
+ if (member.isStable && !otherTp.isVolatile) {
+ if (memberTp.isVolatile)
+ overrideError("has a volatile type; cannot override a member with non-volatile type")
+ else memberTp.normalize.resultType match {
+ case rt: RefinedType if !(rt =:= otherTp) && !(checkedCombinations contains rt.parents) =>
+ // might mask some inconsistencies -- check overrides
+ checkedCombinations += rt.parents
+ val tsym = rt.typeSymbol;
+ if (tsym.pos == NoPosition) tsym setPos member.pos
+ checkAllOverrides(tsym, typesOnly = true)
+ case _ =>
+ }
}
}
}
@@ -400,7 +425,7 @@ abstract class RefChecks extends InfoTransform {
printMixinOverrideErrors()
// Verifying a concrete class has nothing unimplemented.
- if (clazz.isClass && !clazz.isTrait && !(clazz hasFlag ABSTRACT)) {
+ if (clazz.isClass && !clazz.isTrait && !(clazz hasFlag ABSTRACT) && !typesOnly) {
val abstractErrors = new ListBuffer[String]
def abstractErrorMessage =
// a little formatting polish
diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
index d05754e080..69349e191b 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
@@ -2087,6 +2087,8 @@ trait Typers { self: Analyzer =>
EmptyTree
case _ =>
if (localTarget && !includesTargetPos(stat)) {
+ // skip typechecking of statements in a sequence where some other statement includes
+ // the targetposition
stat
} else {
val localTyper = if (inBlock || (stat.isDef && !stat.isInstanceOf[LabelDef])) this
diff --git a/src/compiler/scala/tools/nsc/util/HashSet.scala b/src/compiler/scala/tools/nsc/util/HashSet.scala
index aa6e19538c..8e0c2e2e59 100644
--- a/src/compiler/scala/tools/nsc/util/HashSet.scala
+++ b/src/compiler/scala/tools/nsc/util/HashSet.scala
@@ -11,19 +11,17 @@ class HashSet[T >: Null <: AnyRef](val label: String, initialCapacity: Int) exte
def this(label: String) = this(label, 16)
def this() = this(16)
- private var capacity = initialCapacity
private var used = 0
- private var table = new Array[AnyRef](capacity)
+ private var table = new Array[AnyRef](initialCapacity)
// System.err.println("Created: " + this)
def size: Int = used
def clear() {
- capacity = initialCapacity
used = 0
- table = new Array[AnyRef](capacity)
+ table = new Array[AnyRef](initialCapacity)
}
- private def index(x: Int): Int = math.abs(x % capacity)
+ private def index(x: Int): Int = math.abs(x % table.length)
def findEntryOrUpdate(x: T): T = {
var h = index(x.##)
@@ -37,7 +35,7 @@ class HashSet[T >: Null <: AnyRef](val label: String, initialCapacity: Int) exte
}
table(h) = x
used += 1
- if (used > (capacity >> 2)) growTable()
+ if (used > (table.length >> 2)) growTable()
x
}
@@ -61,14 +59,14 @@ class HashSet[T >: Null <: AnyRef](val label: String, initialCapacity: Int) exte
}
table(h) = x
used += 1
- if (used > (capacity >> 2)) growTable()
+ if (used > (table.length >> 2)) growTable()
}
def iterator = new Iterator[T] {
private var i = 0
def hasNext: Boolean = {
- while (i < capacity && (table(i) eq null)) i += 1
- i < capacity
+ while (i < table.length && (table(i) eq null)) i += 1
+ i < table.length
}
def next: T =
if (hasNext) { i += 1; table(i - 1).asInstanceOf[T] }
@@ -88,12 +86,11 @@ class HashSet[T >: Null <: AnyRef](val label: String, initialCapacity: Int) exte
private def growTable() {
val oldtable = table
val growthFactor =
- if (capacity <= initialCapacity) 8
- else if (capacity <= (initialCapacity * 8)) 4
+ if (table.length <= initialCapacity) 8
+ else if (table.length <= (initialCapacity * 8)) 4
else 2
- capacity *= growthFactor
- table = new Array[AnyRef](capacity)
+ table = new Array[AnyRef](table.length * growthFactor)
var i = 0
while (i < oldtable.length) {
val entry = oldtable(i)
@@ -101,5 +98,5 @@ class HashSet[T >: Null <: AnyRef](val label: String, initialCapacity: Int) exte
i += 1
}
}
- override def toString() = "HashSet %s(%d / %d)".format(label, used, capacity)
+ override def toString() = "HashSet %s(%d / %d)".format(label, used, table.length)
}
diff --git a/src/compiler/scala/tools/nsc/util/InterruptReq.scala b/src/compiler/scala/tools/nsc/util/InterruptReq.scala
new file mode 100644
index 0000000000..aa7804acbe
--- /dev/null
+++ b/src/compiler/scala/tools/nsc/util/InterruptReq.scala
@@ -0,0 +1,28 @@
+package scala.tools.nsc
+package util
+
+/** A class of work items to be used in interrupt requests.
+ */
+abstract class InterruptReq {
+ /** The result type of the operation
+ */
+ type R
+
+ /** The operation to be performed */
+ protected val todo: () => R
+
+ /** The result provided */
+ private var result: Option[R] = None
+
+ /** To be called from interrupted server to execute demanded task */
+ def execute(): Unit = synchronized {
+ result = Some(todo())
+ notify()
+ }
+
+ /** To be called from interrupting client to get result fo interrupt */
+ def getResult(): R = synchronized {
+ while (result.isEmpty) wait()
+ result.get
+ }
+}
diff --git a/src/compiler/scala/tools/nsc/util/WorkScheduler.scala b/src/compiler/scala/tools/nsc/util/WorkScheduler.scala
index e309b19b76..5f33ea4aaa 100644
--- a/src/compiler/scala/tools/nsc/util/WorkScheduler.scala
+++ b/src/compiler/scala/tools/nsc/util/WorkScheduler.scala
@@ -9,22 +9,21 @@ class WorkScheduler {
private var todo = new Queue[Action]
private var throwables = new Queue[Throwable]
+ private var interruptReqs = new Queue[InterruptReq]
- /** Called from server: block until todo list is nonempty */
+ /** Called from server: block until one of todo list, throwables or interruptReqs is nonempty */
def waitForMoreWork() = synchronized {
- while (todo.isEmpty) { wait() }
+ while (todo.isEmpty && throwables.isEmpty && interruptReqs.isEmpty) { wait() }
}
- /** called from Server: test whether todo list is nonempty */
+ /** called from Server: test whether one of todo list, throwables, or InterruptReqs is nonempty */
def moreWork(): Boolean = synchronized {
- todo.nonEmpty
+ todo.nonEmpty || throwables.nonEmpty || interruptReqs.nonEmpty
}
/** Called from server: get first action in todo list, and pop it off */
def nextWorkItem(): Option[Action] = synchronized {
- if (!todo.isEmpty) {
- Some(todo.dequeue())
- } else None
+ if (todo.isEmpty) None else Some(todo.dequeue())
}
/** Called from server: return optional exception posted by client
@@ -41,6 +40,22 @@ class WorkScheduler {
}
}
+ def pollInterrupt(): Option[InterruptReq] = synchronized {
+ if (interruptReqs.isEmpty) None else Some(interruptReqs.dequeue())
+ }
+
+ /** Called from client: have interrupt executed by server and return result */
+ def doQuickly[A](op: () => A): A = {
+ val ir = new InterruptReq {
+ type R = A
+ val todo = op
+ }
+ synchronized {
+ interruptReqs enqueue ir
+ }
+ ir.getResult()
+ }
+
/** Called from client: have action executed by server */
def postWorkItem(action: Action) = synchronized {
todo enqueue action
@@ -60,3 +75,4 @@ class WorkScheduler {
postWorkItem { () => }
}
}
+
diff --git a/src/library/scala/collection/JavaConversions.scala b/src/library/scala/collection/JavaConversions.scala
index 80fc28e234..bbd3976490 100644
--- a/src/library/scala/collection/JavaConversions.scala
+++ b/src/library/scala/collection/JavaConversions.scala
@@ -70,11 +70,14 @@ object JavaConversions {
* @param i The <code>Iterator</code> to be converted.
* @return A Java <code>Iterator</code> view of the argument.
*/
- implicit def asIterator[A](i : Iterator[A]): ju.Iterator[A] = i match {
+ implicit def asJavaIterator[A](i : Iterator[A]): ju.Iterator[A] = i match {
case JIteratorWrapper(wrapped) => wrapped
case _ => IteratorWrapper(i)
}
+ @deprecated("use asJavaIterator instead")
+ def asIterator[A](i : Iterator[A]): ju.Iterator[A] = asJavaIterator[A](i)
+
/**
* Implicitly converts a Scala <code>Iterator</code> to a Java <code>Enumeration</code>.
* The returned Java <code>Enumeration</code> is backed by the provided Scala
@@ -88,11 +91,14 @@ object JavaConversions {
* @param i The <code>Iterator</code> to be converted.
* @return A Java <code>Enumeration</code> view of the argument.
*/
- implicit def asEnumeration[A](i : Iterator[A]): ju.Enumeration[A] = i match {
+ implicit def asJavaEnumeration[A](i : Iterator[A]): ju.Enumeration[A] = i match {
case JEnumerationWrapper(wrapped) => wrapped
case _ => IteratorWrapper(i)
}
+ @deprecated("use asJavaEnmeration instead")
+ def asEnumeration[A](i : Iterator[A]): ju.Enumeration[A] = asJavaEnumeration[A](i)
+
/**
* Implicitly converts a Scala <code>Iterable</code> to a Java <code>Iterable</code>.
* The returned Java <code>Iterable</code> is backed by the provided Scala
@@ -106,11 +112,14 @@ object JavaConversions {
* @param i The <code>Iterable</code> to be converted.
* @return A Java <code>Iterable</code> view of the argument.
*/
- implicit def asIterable[A](i : Iterable[A]): jl.Iterable[A] = i match {
+ implicit def asJavaIterable[A](i : Iterable[A]): jl.Iterable[A] = i match {
case JIterableWrapper(wrapped) => wrapped
case _ => IterableWrapper(i)
}
+ @deprecated("use asJavaIterable instead")
+ def asIterable[A](i : Iterable[A]): jl.Iterable[A] = asJavaIterable[A](i)
+
/**
* Implicitly converts a Scala <code>Iterable</code> to an immutable Java
* <code>Collection</code>.
@@ -122,11 +131,14 @@ object JavaConversions {
* @param i The <code>SizedIterable</code> to be converted.
* @return A Java <code>Collection</code> view of the argument.
*/
- implicit def asCollection[A](i : Iterable[A]): ju.Collection[A] = i match {
+ implicit def asJavaCollection[A](i : Iterable[A]): ju.Collection[A] = i match {
case JCollectionWrapper(wrapped) => wrapped
case _ => new IterableWrapper(i)
}
+ @deprecated("use asJavaCollection instead")
+ def asCollection[A](i : Iterable[A]): ju.Collection[A] = asJavaCollection[A](i)
+
/**
* Implicitly converts a Scala mutable <code>Buffer</code> to a Java <code>List</code>.
* The returned Java <code>List</code> is backed by the provided Scala
@@ -140,11 +152,14 @@ object JavaConversions {
* @param b The <code>Buffer</code> to be converted.
* @return A Java <code>List</code> view of the argument.
*/
- implicit def asList[A](b : mutable.Buffer[A]): ju.List[A] = b match {
+ implicit def asJavaList[A](b : mutable.Buffer[A]): ju.List[A] = b match {
case JListWrapper(wrapped) => wrapped
case _ => new MutableBufferWrapper(b)
}
+ @deprecated("use asJavaList instead")
+ def asList[A](b : mutable.Buffer[A]): ju.List[A] = asJavaList[A](b)
+
/**
* Implicitly converts a Scala mutable <code>Seq</code> to a Java <code>List</code>.
* The returned Java <code>List</code> is backed by the provided Scala
@@ -158,11 +173,14 @@ object JavaConversions {
* @param b The <code>Seq</code> to be converted.
* @return A Java <code>List</code> view of the argument.
*/
- implicit def asList[A](b : mutable.Seq[A]): ju.List[A] = b match {
+ implicit def asJavaList[A](b : mutable.Seq[A]): ju.List[A] = b match {
case JListWrapper(wrapped) => wrapped
case _ => new MutableSeqWrapper(b)
}
+ @deprecated("use asJavaList instead")
+ def asList[A](b : mutable.Seq[A]): ju.List[A] = asJavaList[A](b)
+
/**
* Implicitly converts a Scala <code>Seq</code> to a Java <code>List</code>.
* The returned Java <code>List</code> is backed by the provided Scala
@@ -174,14 +192,16 @@ object JavaConversions {
* Java <code>List</code> will be returned.
*
* @param b The <code>Seq</code> to be converted.
- * @return A Java <code>List</co *
-de> view of the argument.
+ * @return A Java <code>List</code> view of the argument.
*/
- implicit def asList[A](b : Seq[A]): ju.List[A] = b match {
+ implicit def asJavaList[A](b : Seq[A]): ju.List[A] = b match {
case JListWrapper(wrapped) => wrapped
case _ => new SeqWrapper(b)
}
+ @deprecated("use asJavaList instead")
+ def asList[A](b : Seq[A]): ju.List[A] = asJavaList[A](b)
+
/**
* Implicitly converts a Scala mutable <code>Set</code> to a Java <code>Set</code>.
* The returned Java <code>Set</code> is backed by the provided Scala
@@ -195,11 +215,14 @@ de> view of the argument.
* @param s The <code>Set</code> to be converted.
* @return A Java <code>Set</code> view of the argument.
*/
- implicit def asSet[A](s : mutable.Set[A]): ju.Set[A] = s match {
+ implicit def asJavaSet[A](s : mutable.Set[A]): ju.Set[A] = s match {
case JSetWrapper(wrapped) => wrapped
case _ => new MutableSetWrapper(s)
}
+ @deprecated("use asJavaSet instead")
+ def asSet[A](s : mutable.Set[A]): ju.Set[A] = asJavaSet[A](s)
+
/**
* Implicitly converts a Scala <code>Set</code> to a Java <code>Set</code>.
* The returned Java <code>Set</code> is backed by the provided Scala
@@ -213,11 +236,14 @@ de> view of the argument.
* @param s The <code>Set</code> to be converted.
* @return A Java <code>Set</code> view of the argument.
*/
- implicit def asSet[A](s: Set[A]): ju.Set[A] = s match {
+ implicit def asJavaSet[A](s: Set[A]): ju.Set[A] = s match {
case JSetWrapper(wrapped) => wrapped
case _ => new SetWrapper(s)
}
+ @deprecated("use asJavaSet instead")
+ def asSet[A](s : Set[A]): ju.Set[A] = asJavaSet[A](s)
+
/**
* Implicitly converts a Scala mutable <code>Map</code> to a Java <code>Map</code>.
* The returned Java <code>Map</code> is backed by the provided Scala
@@ -231,12 +257,15 @@ de> view of the argument.
* @param m The <code>Map</code> to be converted.
* @return A Java <code>Map</code> view of the argument.
*/
- implicit def asMap[A, B](m : mutable.Map[A, B]): ju.Map[A, B] = m match {
+ implicit def asJavaMap[A, B](m : mutable.Map[A, B]): ju.Map[A, B] = m match {
//case JConcurrentMapWrapper(wrapped) => wrapped
case JMapWrapper(wrapped) => wrapped
case _ => new MutableMapWrapper(m)
}
+ @deprecated("use asJavaMap instead")
+ def asMap[A, B](m : mutable.Map[A, B]): ju.Map[A, B] = asJavaMap[A, B](m)
+
/**
* Implicitly converts a Scala mutable <code>Map</code> to a Java <code>Dictionary</code>.
* The returned Java <code>Dictionary</code> is backed by the provided Scala
@@ -250,24 +279,14 @@ de> view of the argument.
* @param m The <code>Map</code> to be converted.
* @return A Java <code>Dictionary</code> view of the argument.
*/
- implicit def asDictionary[A, B](m : mutable.Map[A, B]): ju.Dictionary[A, B] = m match {
+ implicit def asJavaDictionary[A, B](m : mutable.Map[A, B]): ju.Dictionary[A, B] = m match {
//case JConcurrentMapWrapper(wrapped) => wrapped
case JDictionaryWrapper(wrapped) => wrapped
case _ => new DictionaryWrapper(m)
}
- /**
- * Implicitly converts a Java <code>Properties</code> to a Scala mutable <code>Map[String, String]</code>.
- * The returned Scala <code>Map[String, String]</code> is backed by the provided Java
- * <code>Properties</code> and any side-effects of using it via the Scala interface will
- * be visible via the Java interface and vice versa.
- *
- * @param m The <code>Properties</code> to be converted.
- * @return A Scala mutable <code>Map[String, String]</code> view of the argument.
- */
- implicit def asMap(p: ju.Properties): mutable.Map[String, String] = p match {
- case _ => new JPropertiesWrapper(p)
- }
+ @deprecated("use asJavaDictionary instead")
+ def asDictionary[A, B](m : mutable.Map[A, B]): ju.Dictionary[A, B] = asJavaDictionary[A, B](m)
/**
* Implicitly converts a Scala <code>Map</code> to a Java <code>Map</code>.
@@ -282,12 +301,15 @@ de> view of the argument.
* @param m The <code>Map</code> to be converted.
* @return A Java <code>Map</code> view of the argument.
*/
- implicit def asMap[A, B](m : Map[A, B]): ju.Map[A, B] = m match {
+ implicit def asJavaMap[A, B](m : Map[A, B]): ju.Map[A, B] = m match {
//case JConcurrentMapWrapper(wrapped) => wrapped
case JMapWrapper(wrapped) => wrapped
case _ => new MapWrapper(m)
}
+ @deprecated("use asJavaMap instead")
+ def asMap[A, B](m : Map[A, B]): ju.Map[A, B] = asJavaMap[A, B](m)
+
/**
* Implicitly converts a Scala mutable `ConcurrentMap` to a Java `ConcurrentMap`.
* The returned Java `ConcurrentMap` is backed by the provided Scala `ConcurrentMap`
@@ -297,12 +319,18 @@ de> view of the argument.
* If the Scala <code>ConcurrentMap</code> was previously obtained from an implicit or
* explicit call of <code>asConcurrentMap(java.util.concurrect.ConcurrentMap)</code> then the original
* Java <code>ConcurrentMap</code> will be returned.
+ *
+ * @param m The <code>ConcurrentMap</code> to be converted.
+ * @return A Java <code>ConcurrentMap</code> view of the argument.
*/
- implicit def asConcurrentMap[A, B](m: mutable.ConcurrentMap[A, B]): juc.ConcurrentMap[A, B] = m match {
+ implicit def asJavaConcurrentMap[A, B](m: mutable.ConcurrentMap[A, B]): juc.ConcurrentMap[A, B] = m match {
case JConcurrentMapWrapper(wrapped) => wrapped
case _ => new ConcurrentMapWrapper(m)
}
+ @deprecated("use asJavaConcurrentMap instead")
+ def asConcurrentMap[A, B](m: mutable.ConcurrentMap[A, B]): juc.ConcurrentMap[A, B] = asJavaConcurrentMap[A, B](m)
+
// Java => Scala
/**
@@ -318,11 +346,14 @@ de> view of the argument.
* @param i The <code>Iterator</code> to be converted.
* @return A Scala <code>Iterator</code> view of the argument.
*/
- implicit def asIterator[A](i : ju.Iterator[A]): Iterator[A] = i match {
+ implicit def asScalaIterator[A](i : ju.Iterator[A]): Iterator[A] = i match {
case IteratorWrapper(wrapped) => wrapped
case _ => JIteratorWrapper(i)
}
+ @deprecated("use asScalaIterator instead")
+ def asIterator[A](i : ju.Iterator[A]): Iterator[A] = asScalaIterator[A](i)
+
/**
* Implicitly converts a Java <code>Enumeration</code> to a Scala <code>Iterator</code>.
* The returned Scala <code>Iterator</code> is backed by the provided Java
@@ -336,11 +367,14 @@ de> view of the argument.
* @param i The <code>Enumeration</code> to be converted.
* @return A Scala <code>Iterator</code> view of the argument.
*/
- implicit def asIterator[A](i : ju.Enumeration[A]): Iterator[A] = i match {
+ implicit def enumerationAsScalaIterator[A](i : ju.Enumeration[A]): Iterator[A] = i match {
case IteratorWrapper(wrapped) => wrapped
case _ => JEnumerationWrapper(i)
}
+ @deprecated("use enumerationAsScalaIterator instead")
+ def asIterator[A](i : ju.Enumeration[A]): Iterator[A] = enumerationAsScalaIterator[A](i)
+
/**
* Implicitly converts a Java <code>Iterable</code> to a Scala <code>Iterable</code>.
* The returned Scala <code>Iterable</code> is backed by the provided Java
@@ -354,11 +388,14 @@ de> view of the argument.
* @param i The <code>Iterable</code> to be converted.
* @return A Scala <code>Iterable</code> view of the argument.
*/
- implicit def asIterable[A](i : jl.Iterable[A]): Iterable[A] = i match {
+ implicit def asScalaIterable[A](i : jl.Iterable[A]): Iterable[A] = i match {
case IterableWrapper(wrapped) => wrapped
case _ => JIterableWrapper(i)
}
+ @deprecated("use asScalaIterable instead")
+ def asIterable[A](i : jl.Iterable[A]): Iterable[A] = asScalaIterable[A](i)
+
/**
* Implicitly converts a Java <code>Collection</code> to an Scala <code>Iterable</code>.
* <p>
@@ -369,11 +406,14 @@ de> view of the argument.
* @param i The <code>Collection</code> to be converted.
* @return A Scala <code>SizedIterable</code> view of the argument.
*/
- implicit def asIterable[A](i : ju.Collection[A]): Iterable[A] = i match {
+ implicit def asScalaIterable[A](i : ju.Collection[A]): Iterable[A] = i match {
case IterableWrapper(wrapped) => wrapped
case _ => JCollectionWrapper(i)
}
+ @deprecated("use asScalaIterable instead")
+ def asIterable[A](i : ju.Collection[A]): Iterable[A] = asScalaIterable[A](i)
+
/**
* Implicitly converts a Java <code>List</code> to a Scala mutable <code>Buffer</code>.
* The returned Scala <code>Buffer</code> is backed by the provided Java
@@ -387,11 +427,14 @@ de> view of the argument.
* @param l The <code>List</code> to be converted.
* @return A Scala mutable <code>Buffer</code> view of the argument.
*/
- implicit def asBuffer[A](l : ju.List[A]): mutable.Buffer[A] = l match {
+ implicit def asScalaBuffer[A](l : ju.List[A]): mutable.Buffer[A] = l match {
case MutableBufferWrapper(wrapped) => wrapped
case _ =>new JListWrapper(l)
}
+ @deprecated("use asScalaBuffer instead")
+ def asBuffer[A](l : ju.List[A]): mutable.Buffer[A] = asScalaBuffer[A](l)
+
/**
* Implicitly converts a Java <code>Set</code> to a Scala mutable <code>Set</code>.
* The returned Scala <code>Set</code> is backed by the provided Java
@@ -405,11 +448,14 @@ de> view of the argument.
* @param s The <code>Set</code> to be converted.
* @return A Scala mutable <code>Set</code> view of the argument.
*/
- implicit def asSet[A](s : ju.Set[A]): mutable.Set[A] = s match {
+ implicit def asScalaSet[A](s : ju.Set[A]): mutable.Set[A] = s match {
case MutableSetWrapper(wrapped) => wrapped
case _ =>new JSetWrapper(s)
}
+ @deprecated("use asScalaSet instead")
+ def asSet[A](s : ju.Set[A]): mutable.Set[A] = asScalaSet[A](s)
+
/**
* Implicitly converts a Java <code>Map</code> to a Scala mutable <code>Map</code>.
* The returned Scala <code>Map</code> is backed by the provided Java
@@ -423,12 +469,15 @@ de> view of the argument.
* @param m The <code>Map</code> to be converted.
* @return A Scala mutable <code>Map</code> view of the argument.
*/
- implicit def asMap[A, B](m : ju.Map[A, B]): mutable.Map[A, B] = m match {
+ implicit def asScalaMap[A, B](m : ju.Map[A, B]): mutable.Map[A, B] = m match {
//case ConcurrentMapWrapper(wrapped) => wrapped
case MutableMapWrapper(wrapped) => wrapped
case _ => new JMapWrapper(m)
}
+ @deprecated("use asScalaMap instead")
+ def asMap[A, B](m : ju.Map[A, B]): mutable.Map[A, B] = asScalaMap[A, B](m)
+
/**
* Implicitly converts a Java <code>ConcurrentMap</code> to a Scala mutable <code>ConcurrentMap</code>.
* The returned Scala <code>ConcurrentMap</code> is backed by the provided Java
@@ -442,11 +491,14 @@ de> view of the argument.
* @param m The <code>ConcurrentMap</code> to be converted.
* @return A Scala mutable <code>ConcurrrentMap</code> view of the argument.
*/
- implicit def asConcurrentMap[A, B](m: juc.ConcurrentMap[A, B]): mutable.ConcurrentMap[A, B] = m match {
+ implicit def asScalaConcurrentMap[A, B](m: juc.ConcurrentMap[A, B]): mutable.ConcurrentMap[A, B] = m match {
case cmw: ConcurrentMapWrapper[a, b] => cmw.underlying
case _ => new JConcurrentMapWrapper(m)
}
+ @deprecated("use asScalaConcurrentMap instead")
+ def asConcurrentMap[A, B](m: juc.ConcurrentMap[A, B]): mutable.ConcurrentMap[A, B] = asScalaConcurrentMap[A, B](m)
+
/**
* Implicitly converts a Java <code>Dictionary</code> to a Scala mutable <code>Map[String, String]</code>.
* The returned Scala <code>Map[String, String]</code> is backed by the provided Java
@@ -456,12 +508,31 @@ de> view of the argument.
* @param m The <code>Dictionary</code> to be converted.
* @return A Scala mutable <code>Map[String, String]</code> view of the argument.
*/
- implicit def asMap[A, B](p: ju.Dictionary[A, B]): mutable.Map[A, B] = p match {
+ implicit def dictionaryAsScalaMap[A, B](p: ju.Dictionary[A, B]): mutable.Map[A, B] = p match {
case DictionaryWrapper(wrapped) => wrapped
case _ => new JDictionaryWrapper(p)
}
- // Private implementations ...
+ @deprecated("use dictionaryAsScalaMap instead")
+ def asMap[A, B](p: ju.Dictionary[A, B]): mutable.Map[A, B] = dictionaryAsScalaMap[A, B](p)
+
+ /**
+ * Implicitly converts a Java <code>Properties</code> to a Scala mutable <code>Map[String, String]</code>.
+ * The returned Scala <code>Map[String, String]</code> is backed by the provided Java
+ * <code>Properties</code> and any side-effects of using it via the Scala interface will
+ * be visible via the Java interface and vice versa.
+ *
+ * @param m The <code>Properties</code> to be converted.
+ * @return A Scala mutable <code>Map[String, String]</code> view of the argument.
+ */
+ implicit def asScalaMap(p: ju.Properties): mutable.Map[String, String] = p match {
+ case _ => new JPropertiesWrapper(p)
+ }
+
+ @deprecated("use asScalaMap instead")
+ def asMap(p: ju.Properties): mutable.Map[String, String] = asScalaMap(p)
+
+ // Private implementations (shared by JavaConverters) ...
case class IteratorWrapper[A](underlying : Iterator[A]) extends ju.Iterator[A] with ju.Enumeration[A] {
def hasNext = underlying.hasNext
@@ -471,6 +542,10 @@ de> view of the argument.
def remove = throw new UnsupportedOperationException
}
+ class ToIteratorWrapper[A](underlying : Iterator[A]) {
+ def asJava = new IteratorWrapper(underlying)
+ }
+
case class JIteratorWrapper[A](underlying : ju.Iterator[A]) extends Iterator[A] {
def hasNext = underlying.hasNext
def next = underlying.next
@@ -751,8 +826,8 @@ de> view of the argument.
extends ju.Dictionary[A, B] {
def size: Int = underlying.size
def isEmpty: Boolean = underlying.isEmpty
- def keys: ju.Enumeration[A] = asEnumeration(underlying.keysIterator)
- def elements: ju.Enumeration[B] = asEnumeration(underlying.valuesIterator)
+ def keys: ju.Enumeration[A] = asJavaEnumeration(underlying.keysIterator)
+ def elements: ju.Enumeration[B] = asJavaEnumeration(underlying.valuesIterator)
def get(key: AnyRef) = try {
underlying.get(key.asInstanceOf[A]) match {
case None => null.asInstanceOf[B]
@@ -800,7 +875,7 @@ de> view of the argument.
if (r != null) Some(r) else None
}
- def iterator = asIterator(underlying.keys) map (k => (k, underlying get k))
+ def iterator = enumerationAsScalaIterator(underlying.keys) map (k => (k, underlying get k))
override def clear() = underlying.clear()
}
diff --git a/src/library/scala/collection/JavaConverters.scala b/src/library/scala/collection/JavaConverters.scala
new file mode 100755
index 0000000000..cb4c56fd59
--- /dev/null
+++ b/src/library/scala/collection/JavaConverters.scala
@@ -0,0 +1,456 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2006-2010, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | http://www.scala-lang.org/ **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+
+
+package scala.collection
+
+/** <p>
+ * A collection of decorators that allow to convert between
+ * Scala and Java collections using `asScala` and `asJava` methods.
+ * </p>
+ * <p>
+ * The following conversions are supported via `asJava`, `asScala`
+ * </p>
+ * <ul>
+ * <li><code>scala.collection.Iterable</code> <=> <code>java.lang.Iterable</code></li>
+ * <li><code>scala.collection.Iterator</code> <=> <code>java.util.Iterator</code></li>
+ * <li><code>scala.collection.mutable.Buffer</code> <=> <code>java.util.List</code></li>
+ * <li><code>scala.collection.mutable.Set</code> <=> <code>java.util.Set</code></li>
+ * <li><code>scala.collection.mutable.Map</code> <=> <code>java.util.Map</code></li>
+ * <li><code>scala.collection.mutable.ConcurrentMap</code> <=> <code>java.util.concurrent.ConcurrentMap</code></li>
+ * </ul>
+ * <p>
+ * In all cases, converting from a source type to a target type and back
+ * again will return the original source object, e.g.
+ * </p>
+ * <pre>
+ * <b>import</b> scala.collection.JavaConverters._
+ *
+ * <b>val</b> sl = <b>new</b> scala.collection.mutable.ListBuffer[Int]
+ * <b>val</b> jl : java.util.List[Int] = sl.asJava
+ * <b>val</b> sl2 : scala.collection.mutable.Buffer[Int] = jl.asScala
+ * assert(sl eq sl2)g</pre>
+ * <p>
+ * <p>
+ * The following conversions also are supported, but the
+ * direction Scala to Java is done my a more specifically named method:
+ * `asJavaCollection`, `asJavaEnumeration`, `asJavaDictionary`.
+ * </p>
+ * <ul>
+ * <li><code>scala.collection.Iterable</code> <=> <code>java.util.Collection</code></li>
+ * <li><code>scala.collection.Iterator</code> <=> <code>java.util.Enumeration</code></li>
+ * <li><code>scala.collection.mutable.Map</code> <=> <code>java.util.Dictionary</code></li>
+ * </ul>
+ * In addition, the following one way conversions are provided via `asJava`:
+ * </p>
+ * <ul>
+ * <li><code>scala.collection.Seq => <code>java.util.List }</code></li>
+ * <li><code>scala.collection.mutable.Seq => <code>java.util.List</code></li>
+ * <li><code>scala.collection.Set</code> => <code>java.util.Set</code></li>
+ * <li><code>scala.collection.Map</code> => <code>java.util.Map</code></li>
+ * </ul>
+ *
+ * @author Martin Odersky
+ * @since 2.8.1
+ */
+object JavaConverters {
+ import java.{ lang => jl, util => ju }
+ import java.util.{ concurrent => juc }
+ import JavaConversions._
+
+ // Conversion decorator classes
+
+ /** Generic class containing the `asJava` converter method */
+ class AsJava[C](op: => C) {
+ /** Converts a Scala collection to the corresponding Java collection */
+ def asJava: C = op
+ }
+
+ /** Generic class containing the `asScala` converter method */
+ class AsScala[C](op: => C) {
+ /** Converts a Java collection to the corresponding Scala collection */
+ def asScala: C = op
+ }
+
+ /** Generic class containing the `asJavaCollection` converter method */
+ class AsJavaCollection[A](i: Iterable[A]) {
+ /** Converts a Scala `Iterable` to a Java `Collection` */
+ def asJavaCollection: ju.Collection[A] = JavaConversions.asJavaCollection(i)
+ }
+
+ /** Generic class containing the `asJavaEnumeration` converter method */
+ class AsJavaEnumeration[A](i: Iterator[A]) {
+ /** Converts a Scala `Iterator` to a Java `Enumeration` */
+ def asJavaEnumeration: ju.Enumeration[A] = JavaConversions.asJavaEnumeration(i)
+ }
+
+ /** Generic class containing the `asJavaDictionary` converter method */
+ class AsJavaDictionary[A, B](m : mutable.Map[A, B]) {
+ /** Converts a Scala `Map` to a Java `Dictionary` */
+ def asJavaDictionary: ju.Dictionary[A, B] = JavaConversions.asJavaDictionary(m)
+ }
+
+ // Scala => Java
+
+ /**
+ * Adds an `asJava` method that implicitly converts a Scala <code>Iterator</code> to a Java <code>Iterator</code>.
+ * The returned Java <code>Iterator</code> is backed by the provided Scala
+ * <code>Iterator</code> and any side-effects of using it via the Java interface will
+ * be visible via the Scala interface and vice versa.
+ * <p>
+ * If the Scala <code>Iterator</code> was previously obtained from an implicit or
+ * explicit call of <code>asIterator(java.util.Iterator)</code> then the original
+ * Java <code>Iterator</code> will be returned by the `asJava` method.
+ *
+ * @param i The <code>Iterator</code> to be converted.
+ * @return An object with an `asJava` method that returns a Java <code>Iterator</code> view of the argument.
+ */
+ implicit def asJavaIteratorConverter[A](i : Iterator[A]): AsJava[ju.Iterator[A]] =
+ new AsJava(asJavaIterator(i))
+
+ /**
+ * Adds an `asJavaEnumeration` method that implicitly converts a Scala <code>Iterator</code> to a Java <code>Enumeration</code>.
+ * The returned Java <code>Enumeration</code> is backed by the provided Scala
+ * <code>Iterator</code> and any side-effects of using it via the Java interface will
+ * be visible via the Scala interface and vice versa.
+ * <p>
+ * If the Scala <code>Iterator</code> was previously obtained from an implicit or
+ * explicit call of <code>asIterator(java.util.Enumeration)</code> then the
+ * original Java <code>Enumeration</code> will be returned.
+ *
+ * @param i The <code>Iterator</code> to be converted.
+ * @return An object with an `asJavaEnumeration` method that returns a Java <code>Enumeration</code> view of the argument.
+ */
+ implicit def asJavaEnumerationConverter[A](i : Iterator[A]): AsJavaEnumeration[A] =
+ new AsJavaEnumeration(i)
+
+ /**
+ * Adds an `asJava` method that implicitly converts a Scala <code>Iterable</code> to a Java <code>Iterable</code>.
+ * The returned Java <code>Iterable</code> is backed by the provided Scala
+ * <code>Iterable</code> and any side-effects of using it via the Java interface will
+ * be visible via the Scala interface and vice versa.
+ * <p>
+ * If the Scala <code>Iterable</code> was previously obtained from an implicit or
+ * explicit call of <code>asIterable(java.lang.Iterable)</code> then the original
+ * Java <code>Iterable</code> will be returned.
+ *
+ * @param i The <code>Iterable</code> to be converted.
+ * @return An object with an `asJavaCollection` method that returns a Java <code>Iterable</code> view of the argument.
+ */
+ implicit def asJavaIterableConverter[A](i : Iterable[A]): AsJava[jl.Iterable[A]] =
+ new AsJava(asJavaIterable(i))
+
+ /**
+ * Adds an `asJavaCollection` method that implicitly converts a Scala <code>Iterable</code> to an immutable Java
+ * <code>Collection</code>.
+ * <p>
+ * If the Scala <code>Iterable</code> was previously obtained from an implicit or
+ * explicit call of <code>asSizedIterable(java.util.Collection)</code> then the original
+ * Java <code>Collection</code> will be returned.
+ *
+ * @param i The <code>SizedIterable</code> to be converted.
+ * @return An object with an `asJava` method that returns a Java <code>Collection</code> view of the argument.
+ */
+ implicit def asJavaCollectionConverter[A](i : Iterable[A]): AsJavaCollection[A] =
+ new AsJavaCollection(i)
+
+ /**
+ * Adds an `asJava` method that implicitly converts a Scala mutable <code>Buffer</code> to a Java <code>List</code>.
+ * The returned Java <code>List</code> is backed by the provided Scala
+ * <code>Buffer</code> and any side-effects of using it via the Java interface will
+ * be visible via the Scala interface and vice versa.
+ * <p>
+ * If the Scala <code>Buffer</code> was previously obtained from an implicit or
+ * explicit call of <code>asBuffer(java.util.List)</code> then the original
+ * Java <code>List</code> will be returned.
+ *
+ * @param b The <code>Buffer</code> to be converted.
+ * @return An object with an `asJava` method that returns a Java <code>List</code> view of the argument.
+ */
+ implicit def asJavaListConverter[A](b : mutable.Buffer[A]): AsJava[ju.List[A]] =
+ new AsJava(asJavaList(b))
+
+ /**
+ * Adds an `asJava` method that implicitly converts a Scala mutable <code>Seq</code> to a Java <code>List</code>.
+ * The returned Java <code>List</code> is backed by the provided Scala
+ * <code>Seq</code> and any side-effects of using it via the Java interface will
+ * be visible via the Scala interface and vice versa.
+ * <p>
+ * If the Scala <code>Seq</code> was previously obtained from an implicit or
+ * explicit call of <code>asSeq(java.util.List)</code> then the original
+ * Java <code>List</code> will be returned.
+ *
+ * @param b The <code>Seq</code> to be converted.
+ * @return An object with an `asJava` method that returns a Java <code>List</code> view of the argument.
+ */
+ implicit def asJavaListConverter[A](b : mutable.Seq[A]): AsJava[ju.List[A]] =
+ new AsJava(asJavaList(b))
+
+ /**
+ * Adds an `asJava` method that implicitly converts a Scala <code>Seq</code> to a Java <code>List</code>.
+ * The returned Java <code>List</code> is backed by the provided Scala
+ * <code>Seq</code> and any side-effects of using it via the Java interface will
+ * be visible via the Scala interface and vice versa.
+ * <p>
+ * If the Scala <code>Seq</code> was previously obtained from an implicit or
+ * explicit call of <code>asSeq(java.util.List)</code> then the original
+ * Java <code>List</code> will be returned.
+ *
+ * @param b The <code>Seq</code> to be converted.
+ * @return An object with an `asJava` method that returns a Java <code>List</code> view of the argument.
+ */
+ implicit def asJavaListConverter[A](b : Seq[A]): AsJava[ju.List[A]] =
+ new AsJava(asJavaList(b))
+
+ /**
+ * Adds an `asJava` method that implicitly converts a Scala mutable <code>Set</code> to a Java <code>Set</code>.
+ * The returned Java <code>Set</code> is backed by the provided Scala
+ * <code>Set</code> and any side-effects of using it via the Java interface will
+ * be visible via the Scala interface and vice versa.
+ * <p>
+ * If the Scala <code>Set</code> was previously obtained from an implicit or
+ * explicit call of <code>asSet(java.util.Set)</code> then the original
+ * Java <code>Set</code> will be returned.
+ *
+ * @param s The <code>Set</code> to be converted.
+ * @return An object with an `asJava` method that returns a Java <code>Set</code> view of the argument.
+ */
+ implicit def asJavaSetConverter[A](s : mutable.Set[A]): AsJava[ju.Set[A]] =
+ new AsJava(asJavaSet(s))
+
+ /**
+ * Adds an `asJava` method that implicitly converts a Scala <code>Set</code> to a Java <code>Set</code>.
+ * The returned Java <code>Set</code> is backed by the provided Scala
+ * <code>Set</code> and any side-effects of using it via the Java interface will
+ * be visible via the Scala interface and vice versa.
+ * <p>
+ * If the Scala <code>Set</code> was previously obtained from an implicit or
+ * explicit call of <code>asSet(java.util.Set)</code> then the original
+ * Java <code>Set</code> will be returned.
+ *
+ * @param s The <code>Set</code> to be converted.
+ * @return An object with an `asJava` method that returns a Java <code>Set</code> view of the argument.
+ */
+ implicit def asJavaSetConverter[A](s : Set[A]): AsJava[ju.Set[A]] =
+ new AsJava(asJavaSet(s))
+
+ /**
+ * Adds an `asJava` method that implicitly converts a Scala mutable <code>Map</code> to a Java <code>Map</code>.
+ * The returned Java <code>Map</code> is backed by the provided Scala
+ * <code>Map</code> and any side-effects of using it via the Java interface will
+ * be visible via the Scala interface and vice versa.
+ * <p>
+ * If the Scala <code>Map</code> was previously obtained from an implicit or
+ * explicit call of <code>asMap(java.util.Map)</code> then the original
+ * Java <code>Map</code> will be returned.
+ *
+ * @param m The <code>Map</code> to be converted.
+ * @return An object with an `asJava` method that returns a Java <code>Map</code> view of the argument.
+ */
+ implicit def asJavaMapConverter[A, B](m : mutable.Map[A, B]): AsJava[ju.Map[A, B]] =
+ new AsJava(asJavaMap(m))
+
+ /**
+ * Adds an `asJavaDictionary` method that implicitly converts a Scala mutable <code>Map</code> to a Java <code>Dictionary</code>.
+ * The returned Java <code>Dictionary</code> is backed by the provided Scala
+ * <code>Dictionary</code> and any side-effects of using it via the Java interface will
+ * be visible via the Scala interface and vice versa.
+ * <p>
+ * If the Scala <code>Dictionary</code> was previously obtained from an implicit or
+ * explicit call of <code>asMap(java.util.Dictionary)</code> then the original
+ * Java <code>Dictionary</code> will be returned.
+ *
+ * @param m The <code>Map</code> to be converted.
+ * @return An object with an `asJavaDictionary` method that returns a Java <code>Dictionary</code> view of the argument.
+ */
+ implicit def asJavaDictionaryConverter[A, B](m : mutable.Map[A, B]): AsJavaDictionary[A, B] =
+ new AsJavaDictionary(m)
+
+ /**
+ * Adds an `asJava` method that implicitly converts a Scala <code>Map</code> to a Java <code>Map</code>.
+ * The returned Java <code>Map</code> is backed by the provided Scala
+ * <code>Map</code> and any side-effects of using it via the Java interface will
+ * be visible via the Scala interface and vice versa.
+ * <p>
+ * If the Scala <code>Map</code> was previously obtained from an implicit or
+ * explicit call of <code>asMap(java.util.Map)</code> then the original
+ * Java <code>Map</code> will be returned.
+ *
+ * @param m The <code>Map</code> to be converted.
+ * @return An object with an `asJava` method that returns a Java <code>Map</code> view of the argument.
+ */
+ implicit def asJavaMapConverter[A, B](m : Map[A, B]): AsJava[ju.Map[A, B]] =
+ new AsJava(asJavaMap(m))
+
+ /**
+ * Adds an `asJava` method that implicitly converts a Scala mutable `ConcurrentMap` to a Java `ConcurrentMap`.
+ * The returned Java `ConcurrentMap` is backed by the provided Scala `ConcurrentMap`
+ * and any side-effects of using it via the Java interface will be visible
+ * via the Scala interface and vice versa.
+ * <p>
+ * If the Scala <code>ConcurrentMap</code> was previously obtained from an implicit or
+ * explicit call of <code>asConcurrentMap(java.util.concurrect.ConcurrentMap)</code> then the original
+ * Java <code>ConcurrentMap</code> will be returned.
+ *
+ * @param m The <code>ConcurrentMap</code> to be converted.
+ * @return An object with an `asJava` method that returns a Java <code>ConcurrentMap</code> view of the argument.
+ */
+ implicit def asJavaConcurrentMapConverter[A, B](m: mutable.ConcurrentMap[A, B]): AsJava[juc.ConcurrentMap[A, B]] =
+ new AsJava(asJavaConcurrentMap(m))
+
+ /**
+ * Adds an `asScala` method that implicitly converts a Java <code>Iterator</code> to a Scala <code>Iterator</code>.
+ * The returned Scala <code>Iterator</code> is backed by the provided Java
+ * <code>Iterator</code> and any side-effects of using it via the Scala interface will
+ * be visible via the Java interface and vice versa.
+ * <p>
+ * If the Java <code>Iterator</code> was previously obtained from an implicit or
+ * explicit call of <code>asIterator(scala.collection.Iterator)</code> then the original
+ * Scala <code>Iterator</code> will be returned.
+ *
+ * @param i The <code>Iterator</code> to be converted.
+ * @return An object with an `asScala` method that returns a Scala <code>Iterator</code> view of the argument.
+ */
+ implicit def asScalaIteratorConverter[A](i : ju.Iterator[A]): AsScala[Iterator[A]] =
+ new AsScala(asScalaIterator(i))
+
+ /**
+ * Adds an `asScala` method that implicitly converts a Java <code>Enumeration</code> to a Scala <code>Iterator</code>.
+ * The returned Scala <code>Iterator</code> is backed by the provided Java
+ * <code>Enumeration</code> and any side-effects of using it via the Scala interface will
+ * be visible via the Java interface and vice versa.
+ * <p>
+ * If the Java <code>Enumeration</code> was previously obtained from an implicit or
+ * explicit call of <code>asEnumeration(scala.collection.Iterator)</code> then the
+ * original Scala <code>Iterator</code> will be returned.
+ *
+ * @param i The <code>Enumeration</code> to be converted.
+ * @return An object with an `asScala` method that returns a Scala <code>Iterator</code> view of the argument.
+ */
+ implicit def enumerationAsScalaIteratorConverter[A](i : ju.Enumeration[A]): AsScala[Iterator[A]] =
+ new AsScala(enumerationAsScalaIterator(i))
+
+ /**
+ * Adds an `asScala` method that implicitly converts a Java <code>Iterable</code> to a Scala <code>Iterable</code>.
+ * The returned Scala <code>Iterable</code> is backed by the provided Java
+ * <code>Iterable</code> and any side-effects of using it via the Scala interface will
+ * be visible via the Java interface and vice versa.
+ * <p>
+ * If the Java <code>Iterable</code> was previously obtained from an implicit or
+ * explicit call of <code>asIterable(scala.collection.Iterable)</code> then the original
+ * Scala <code>Iterable</code> will be returned.
+ *
+ * @param i The <code>Iterable</code> to be converted.
+ * @return An object with an `asScala` method that returns a Scala <code>Iterable</code> view of the argument.
+ */
+ implicit def asScalaIterableConverter[A](i : jl.Iterable[A]): AsScala[Iterable[A]] =
+ new AsScala(asScalaIterable(i))
+
+ /**
+ * Adds an `asScala` method that implicitly converts a Java <code>Collection</code> to an Scala <code>Iterable</code>.
+ * <p>
+ * If the Java <code>Collection</code> was previously obtained from an implicit or
+ * explicit call of <code>asCollection(scala.collection.SizedIterable)</code> then
+ * the original Scala <code>SizedIterable</code> will be returned.
+ *
+ * @param i The <code>Collection</code> to be converted.
+ * @return An object with an `asScala` method that returns a Scala <code>SizedIterable</code> view of the argument.
+ */
+ implicit def asScalaIterableConverter[A](i : ju.Collection[A]): AsScala[Iterable[A]] =
+ new AsScala(asScalaIterable(i))
+
+ /**
+ * Adds an `asScala` method that implicitly converts a Java <code>List</code> to a Scala mutable <code>Buffer</code>.
+ * The returned Scala <code>Buffer</code> is backed by the provided Java
+ * <code>List</code> and any side-effects of using it via the Scala interface will
+ * be visible via the Java interface and vice versa.
+ * <p>
+ * If the Java <code>List</code> was previously obtained from an implicit or
+ * explicit call of <code>asList(scala.collection.mutable.Buffer)</code> then the original
+ * Scala <code>Buffer</code> will be returned.
+ *
+ * @param l The <code>List</code> to be converted.
+ * @return An object with an `asScala` method that returns a Scala mutable <code>Buffer</code> view of the argument.
+ */
+ implicit def asScalaBufferConverter[A](l : ju.List[A]): AsScala[mutable.Buffer[A]] =
+ new AsScala(asScalaBuffer(l))
+
+ /**
+ * Adds an `asScala` method that implicitly converts a Java <code>Set</code> to a Scala mutable <code>Set</code>.
+ * The returned Scala <code>Set</code> is backed by the provided Java
+ * <code>Set</code> and any side-effects of using it via the Scala interface will
+ * be visible via the Java interface and vice versa.
+ * <p>
+ * If the Java <code>Set</code> was previously obtained from an implicit or
+ * explicit call of <code>asSet(scala.collection.mutable.Set)</code> then the original
+ * ScalaThe reported problems have to do with dependent method types, which is currently an experimental feature in Scala and is still under development. We emphasize that these problems are related to type-inference and, as stated in the paper, it is possible to run and type-check the programs with additional annotations. <code>Set</code> will be returned.
+ *
+ * @param s The <code>Set</code> to be converted.
+ * @return An object with an `asScala` method that returns a Scala mutable <code>Set</code> view of the argument.
+ */
+ implicit def asScalaSetConverter[A](s : ju.Set[A]): AsScala[mutable.Set[A]] =
+ new AsScala(asScalaSet(s))
+
+ /**
+ * Adds an `asScala` method that implicitly converts a Java <code>Map</code> to a Scala mutable <code>Map</code>.
+ * The returned Scala <code>Map</code> is backed by the provided Java
+ * <code>Map</code> and any side-effects of using it via the Scala interface will
+ * be visible via the Java interface and vice versa.
+ * <p>
+ * If the Java <code>Map</code> was previously obtained from an implicit or
+ * explicit call of <code>asMap(scala.collection.mutable.Map)</code> then the original
+ * Scala <code>Map</code> will be returned.
+ *
+ * @param m The <code>Map</code> to be converted.
+ * @return An object with an `asScala` method that returns a Scala mutable <code>Map</code> view of the argument.
+ */
+ implicit def asScalaMapConverter[A, B](m : ju.Map[A, B]): AsScala[mutable.Map[A, B]] =
+ new AsScala(asScalaMap(m))
+
+ /**
+ * Adds an `asScala` method that implicitly converts a Java <code>ConcurrentMap</code> to a Scala mutable <code>ConcurrentMap</code>.
+ * The returned Scala <code>ConcurrentMap</code> is backed by the provided Java
+ * <code>ConcurrentMap</code> and any side-effects of using it via the Scala interface will
+ * be visible via the Java interface and vice versa.
+ * <p>
+ * If the Java <code>ConcurrentMap</code> was previously obtained from an implicit or
+ * explicit call of <code>asConcurrentMap(scala.collection.mutable.ConcurrentMap)</code> then the original
+ * Scala <code>ConcurrentMap</code> will be returned.
+ *
+ * @param m The <code>ConcurrentMap</code> to be converted.
+ * @return An object with an `asScala` method that returns a Scala mutable <code>ConcurrrentMap</code> view of the argument.
+ */
+ implicit def asScalaConcurrentMapConverter[A, B](m: juc.ConcurrentMap[A, B]): AsScala[mutable.ConcurrentMap[A, B]] =
+ new AsScala(asScalaConcurrentMap(m))
+
+ /**
+ * Adds an `asScala` method that implicitly converts a Java <code>Dictionary</code> to a Scala mutable <code>Map[String, String]</code>.
+ * The returned Scala <code>Map[String, String]</code> is backed by the provided Java
+ * <code>Dictionary</code> and any side-effects of using it via the Scala interface will
+ * be visible via the Java interface and vice versa.
+ *
+ * @param m The <code>Dictionary</code> to be converted.
+ * @return An object with an `asScala` method that returns a Scala mutable <code>Map[String, String]</code> view of the argument.
+ */
+ implicit def dictionaryAsScalaMapConverter[A, B](p: ju.Dictionary[A, B]): AsScala[mutable.Map[A, B]] =
+ new AsScala(dictionaryAsScalaMap(p))
+
+ /**
+ * Adds an `asScala` method that implicitly converts a Java <code>Properties</code> to a Scala mutable <code>Map[String, String]</code>.
+ * The returned Scala <code>Map[String, String]</code> is backed by the provided Java
+ * <code>Properties</code> and any side-effects of using it via the Scala interface will
+ * be visible via the Java interface and vice versa.
+ *
+ * @param m The <code>Properties</code> to be converted.
+ * @return An object with an `asScala` method that returns a Scala mutable <code>Map[String, String]</code> view of the argument.
+ */
+ implicit def asScalaMapConverter(p: ju.Properties): AsScala[mutable.Map[String, String]] =
+ new AsScala(asScalaMap(p))
+
+}
diff --git a/src/library/scala/collection/TraversableOnce.scala b/src/library/scala/collection/TraversableOnce.scala
index b6c0ce146e..6656b05083 100644
--- a/src/library/scala/collection/TraversableOnce.scala
+++ b/src/library/scala/collection/TraversableOnce.scala
@@ -277,7 +277,7 @@ trait TraversableOnce[+A] {
* @tparam B the result type of the `+` operator.
* @return the sum of all elements of this $coll with respect to the `+` operator in `num`.
*
- * @usecase def sum: Int
+ * @usecase def sum: A
*
* @return the sum of all elements in this $coll of numbers of type `Int`.
* Instead of `Int`, any other type `T` with an implicit `Numeric[T]` implementation
@@ -294,7 +294,7 @@ trait TraversableOnce[+A] {
* @tparam B the result type of the `*` operator.
* @return the product of all elements of this $coll with respect to the `*` operator in `num`.
*
- * @usecase def product: Int
+ * @usecase def product: A
*
* @return the product of all elements in this $coll of numbers of type `Int`.
* Instead of `Int`, any other type `T` with an implicit `Numeric[T]` implementation
@@ -442,6 +442,9 @@ trait TraversableOnce[+A] {
* is undefined.
* $willNotTerminateInf
* @return a map containing all elements of this $coll.
+ * @usecase def toMap: Map[K, V]
+ * @return a map of type `immutable.Map[K, V]`
+ * containing all key/value pairs of type `(K, V)` of this $coll.
*/
def toMap[T, U](implicit ev: A <:< (T, U)): immutable.Map[T, U] = {
val b = immutable.Map.newBuilder[T, U]
diff --git a/src/library/scala/collection/generic/GenericTraversableTemplate.scala b/src/library/scala/collection/generic/GenericTraversableTemplate.scala
index 54f4a07c10..5f009b6742 100644
--- a/src/library/scala/collection/generic/GenericTraversableTemplate.scala
+++ b/src/library/scala/collection/generic/GenericTraversableTemplate.scala
@@ -51,6 +51,7 @@ trait GenericTraversableTemplate[+A, +CC[X] <: Traversable[X]] extends HasNewBui
def isEmpty: Boolean
/** The factory companion object that builds instances of class $Coll.
+ * (or its `Iterable` superclass where class $Coll is not a `Seq`.)
*/
def companion: GenericCompanion[CC]
diff --git a/src/library/scala/collection/mutable/ArrayOps.scala b/src/library/scala/collection/mutable/ArrayOps.scala
index d7072c0661..00e8697b53 100644
--- a/src/library/scala/collection/mutable/ArrayOps.scala
+++ b/src/library/scala/collection/mutable/ArrayOps.scala
@@ -10,6 +10,7 @@
package scala.collection
package mutable
+import compat.Platform.arraycopy
import scala.reflect.ClassManifest
@@ -38,6 +39,13 @@ abstract class ArrayOps[T] extends ArrayLike[T, Array[T]] {
ClassManifest.fromClass(
repr.getClass.getComponentType.getComponentType.asInstanceOf[Predef.Class[U]]))
+ override def copyToArray[U >: T](xs: Array[U], start: Int, len: Int) {
+ var l = len
+ if (repr.length < l) l = repr.length
+ if (xs.length - start < l) l = xs.length - start max 0
+ Array.copy(repr, 0, xs, start, l)
+ }
+
override def toArray[U >: T : ClassManifest]: Array[U] =
if (implicitly[ClassManifest[U]].erasure eq repr.getClass.getComponentType)
repr.asInstanceOf[Array[U]]
diff --git a/src/library/scala/concurrent/SyncVar.scala b/src/library/scala/concurrent/SyncVar.scala
index 46dc415e1f..dce770ce43 100644
--- a/src/library/scala/concurrent/SyncVar.scala
+++ b/src/library/scala/concurrent/SyncVar.scala
@@ -13,7 +13,7 @@ package scala.concurrent
/** The class <code>SyncVar</code> ...
*
- * @author Martin Odersky, Stepan Koltsov
+ * @author Martin Odersky
* @version 1.0, 10/03/2003
*/
class SyncVar[A] {
diff --git a/src/library/scala/reflect/generic/UnPickler.scala b/src/library/scala/reflect/generic/UnPickler.scala
index ee021446bc..54ac1acc3d 100755
--- a/src/library/scala/reflect/generic/UnPickler.scala
+++ b/src/library/scala/reflect/generic/UnPickler.scala
@@ -42,7 +42,7 @@ abstract class UnPickler {
}
}
- /** To ne implemented in subclasses. Like `unpickle` but without the catch-all error handling.
+ /** To be implemented in subclasses. Like `unpickle` but without the catch-all error handling.
*/
def scan(bytes: Array[Byte], offset: Int, classRoot: Symbol, moduleRoot: Symbol, filename: String)
diff --git a/src/library/scala/runtime/TraitSetter.java b/src/library/scala/runtime/TraitSetter.java
new file mode 100755
index 0000000000..d9907c0ac0
--- /dev/null
+++ b/src/library/scala/runtime/TraitSetter.java
@@ -0,0 +1,6 @@
+package scala.runtime;
+
+/** A marker annotation to tag a setter of a mutable variable in a trait
+ */
+public @interface TraitSetter {
+} \ No newline at end of file
diff --git a/test/files/neg/override.check b/test/files/neg/override.check
new file mode 100644
index 0000000000..0336fb2b11
--- /dev/null
+++ b/test/files/neg/override.check
@@ -0,0 +1,5 @@
+override.scala:9: error: overriding type T in trait A with bounds >: Int <: Int;
+ type T in trait B with bounds >: String <: String has incompatible type
+ lazy val x : A with B = x
+ ^
+one error found
diff --git a/test/files/neg/override.scala b/test/files/neg/override.scala
new file mode 100755
index 0000000000..764b06603a
--- /dev/null
+++ b/test/files/neg/override.scala
@@ -0,0 +1,15 @@
+trait X {
+ trait A { type T >: Int <: Int }
+ val x : A
+ var n : x.T = 3
+}
+
+trait Y extends X {
+ trait B { type T >: String <: String }
+ lazy val x : A with B = x
+ n = "foo"
+}
+
+object Test extends Application {
+ new Y {}
+}
diff --git a/test/files/neg/t3774.check b/test/files/neg/t3774.check
new file mode 100644
index 0000000000..d73166bff9
--- /dev/null
+++ b/test/files/neg/t3774.check
@@ -0,0 +1,7 @@
+t3774.scala:4: error: overloaded method value ++ with alternatives:
+ [B1 >: List[Int]](xs: scala.collection.TraversableOnce[((Int, Int), B1)])scala.collection.immutable.Map[(Int, Int),B1] <and>
+ [B >: ((Int, Int), List[Int]),That](that: scala.collection.TraversableOnce[B])(implicit bf: scala.collection.generic.CanBuildFrom[scala.collection.immutable.Map[(Int, Int),List[Int]],B,That])That
+ cannot be applied to (scala.collection.immutable.IndexedSeq[((Int, Int), scala.collection.immutable.Range.Inclusive)])
+ Map[(Int,Int),List[Int]]() ++ (for(x <- 0 to 1 ; y <- 0 to 1) yield {(x,y)-> (0 to 1)})
+ ^
+one error found
diff --git a/test/files/neg/t3774.scala b/test/files/neg/t3774.scala
new file mode 100644
index 0000000000..2869925b01
--- /dev/null
+++ b/test/files/neg/t3774.scala
@@ -0,0 +1,5 @@
+// This used to hang the lub process. Now it rejects the file. This is still not correct,
+// but we can solve this only after a redesign of lub a la dot.
+object Hang {
+ Map[(Int,Int),List[Int]]() ++ (for(x <- 0 to 1 ; y <- 0 to 1) yield {(x,y)-> (0 to 1)})
+}
diff --git a/test/files/neg/t3776.check b/test/files/neg/t3776.check
new file mode 100644
index 0000000000..e8798df6f3
--- /dev/null
+++ b/test/files/neg/t3776.check
@@ -0,0 +1,4 @@
+t3776.scala:8: error: value someOperation is not a member of _$1
+ def parsedAs[T](v: T) = MyParser.parse(pattern, a).get someOperation v
+ ^
+one error found
diff --git a/test/files/neg/t3776.scala b/test/files/neg/t3776.scala
new file mode 100644
index 0000000000..6e368165aa
--- /dev/null
+++ b/test/files/neg/t3776.scala
@@ -0,0 +1,10 @@
+import util.parsing.combinator.{PackratParsers, RegexParsers}
+
+object MyParser extends RegexParsers with PackratParsers {
+}
+
+object Test {
+ class ParsedAs(a: String) (implicit pattern: MyParser.Parser[_]) {
+ def parsedAs[T](v: T) = MyParser.parse(pattern, a).get someOperation v
+ }
+}
diff --git a/test/files/pos/t2133.scala b/test/files/pos/t2133.scala
new file mode 100644
index 0000000000..c74d0a4bbf
--- /dev/null
+++ b/test/files/pos/t2133.scala
@@ -0,0 +1,18 @@
+trait Foo {
+ object bar {
+ private[this] def fn() = 5
+ }
+}
+
+trait Foo2 {
+ object bip {
+ def fn() = 10
+ }
+}
+
+class Bob extends AnyRef with Foo with Foo2 {
+ import bip._
+ import bar._
+
+ def go() = fn()
+}
diff --git a/test/files/pos/t3174.scala b/test/files/pos/t3174.scala
new file mode 100755
index 0000000000..c3d90a4946
--- /dev/null
+++ b/test/files/pos/t3174.scala
@@ -0,0 +1,14 @@
+object test {
+ def method() {
+ class Foo extends AnyRef {
+ object Color {
+ object Blue
+ }
+
+ class Board {
+ val grid = Color.Blue
+ }
+ }
+ new Foo
+ }
+ }
diff --git a/test/files/pos/t3174b.scala b/test/files/pos/t3174b.scala
new file mode 100755
index 0000000000..4df1bfe837
--- /dev/null
+++ b/test/files/pos/t3174b.scala
@@ -0,0 +1,12 @@
+trait Foo[X] { def foo : Map[String,Foo[X]] }
+
+object Test {
+ def f[T]() : Foo[T] = {
+ class Anon extends Foo[T] {
+ var foo: Map[String, Foo[T]] = Map[String,Foo[T]]()
+ //def foo = Map[String,Foo[T]]()
+ //def foo_=(x: Map[String,Foo[T]]) {}
+ }
+ new Anon
+ }
+}
diff --git a/test/files/pos/t3568.scala b/test/files/pos/t3568.scala
new file mode 100755
index 0000000000..c8e3fcc4be
--- /dev/null
+++ b/test/files/pos/t3568.scala
@@ -0,0 +1,46 @@
+import scala.annotation._
+import scala.annotation.unchecked._
+import scala.collection._
+
+
+package object buffer {
+ val broken = new ArrayVec2() // commenting out this line causes the file to compile.
+
+ val works = Class.forName("buffer.ArrayVec2").newInstance().asInstanceOf[ArrayVec2]
+}
+
+package buffer {
+ object Main {
+ // ArrayVec2 can be compiled, instantiated and used.
+ def main(args: Array[String]) { println(works) }
+ }
+
+ trait ElemType { type Element; type Component <: ElemType }
+ trait Float1 extends ElemType { type Element = Float; type Component = Float1}
+ class Vec2 extends ElemType { type Element = Vec2; type Component = Float1 }
+
+ abstract class BaseSeq[T <: ElemType, E]
+ extends IndexedSeq[E] with IndexedSeqOptimized[E, IndexedSeq[E]] {
+ def length = 1
+ def apply(i: Int) :E
+ }
+
+ abstract class GenericSeq[T <: ElemType] extends BaseSeq[T, T#Element]
+ trait DataArray[T <: ElemType] extends BaseSeq[T, T#Element]
+ trait DataView[T <: ElemType] extends BaseSeq[T, T#Element]
+ abstract class BaseFloat1 extends BaseSeq[Float1, Float]
+
+ class ArrayFloat1 extends BaseFloat1 with DataArray[Float1] {
+ def apply(i: Int) :Float = 0f
+ }
+
+ class ViewFloat1 extends BaseFloat1 with DataView[Float1] {
+ def apply(i: Int) :Float = 0f
+ }
+
+ class ArrayVec2(val backingSeq: ArrayFloat1)
+ extends GenericSeq[Vec2] with DataArray[Vec2] {
+ def this() = this(new ArrayFloat1)
+ def apply(i: Int) :Vec2 = null
+ }
+}
diff --git a/test/files/pos/t3688.scala b/test/files/pos/t3688.scala
new file mode 100644
index 0000000000..0ac1cfe514
--- /dev/null
+++ b/test/files/pos/t3688.scala
@@ -0,0 +1,9 @@
+import collection.mutable
+import collection.JavaConversions._
+import java.{util => ju}
+
+object Test {
+
+ implicitly[mutable.Map[Int, String] => ju.Dictionary[Int, String]]
+
+}
diff --git a/test/files/run/t3763.scala b/test/files/run/t3763.scala
new file mode 100644
index 0000000000..c8462b7437
--- /dev/null
+++ b/test/files/run/t3763.scala
@@ -0,0 +1,3 @@
+object Test extends Application {
+ val x = Array(Array(1), List(1))
+}
diff --git a/test/files/run/weakconform.scala b/test/files/run/weakconform.scala
new file mode 100755
index 0000000000..1ea81c9f64
--- /dev/null
+++ b/test/files/run/weakconform.scala
@@ -0,0 +1,4 @@
+object Test extends Application {
+ val x: Float = 10/3
+ assert(x == 3.0)
+}
diff --git a/test/pending/run/t3609.scala b/test/pending/run/t3609.scala
new file mode 100755
index 0000000000..262948137d
--- /dev/null
+++ b/test/pending/run/t3609.scala
@@ -0,0 +1,11 @@
+object Test extends Application {
+ class A
+ class B extends A
+ def foo(x: A, y: B) = print(1)
+ val foo = new {
+ //def apply(x: B, y: A) = print(3)
+ def apply = (x: B, z: B) => print(4)
+ }
+
+ foo(new B, new B)
+}