summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2012-04-05 17:17:39 -0700
committerMartin Odersky <odersky@gmail.com>2012-04-05 17:17:39 -0700
commit115f5467e3f3ff07abbba2b23c40c2ff0d7ddd1b (patch)
tree15265c311900918c79c5eda8d54c58fc145ef4a8
parent7f79ef0e30f088b41b14763f44338c240acf1a63 (diff)
parent754b4a85e4093f25cc10f092fefdb34215097c94 (diff)
downloadscala-115f5467e3f3ff07abbba2b23c40c2ff0d7ddd1b.tar.gz
scala-115f5467e3f3ff07abbba2b23c40c2ff0d7ddd1b.tar.bz2
scala-115f5467e3f3ff07abbba2b23c40c2ff0d7ddd1b.zip
Merge branch 'master' into topic/reflect
-rw-r--r--build.xml25
-rw-r--r--src/build/maven/scala-library-pom.xml29
-rw-r--r--src/compiler/scala/reflect/internal/SymbolTable.scala5
-rw-r--r--src/compiler/scala/reflect/internal/Symbols.scala7
-rw-r--r--src/compiler/scala/reflect/internal/Types.scala10
-rw-r--r--src/compiler/scala/reflect/internal/util/TraceSymbolActivity.scala168
-rw-r--r--src/compiler/scala/tools/nsc/Global.scala3
-rw-r--r--src/compiler/scala/tools/nsc/interactive/tests/InteractiveTest.scala1
-rw-r--r--src/compiler/scala/tools/nsc/interactive/tests/core/AskCommand.scala4
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Infer.scala3
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Namers.scala5
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/RefChecks.scala15
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Typers.scala11
-rw-r--r--src/continuations/plugin/scala/tools/selectivecps/CPSUtils.scala2
-rw-r--r--src/continuations/plugin/scala/tools/selectivecps/SelectiveANFTransform.scala26
-rw-r--r--src/library/scala/Option.scala12
-rw-r--r--src/library/scala/collection/JavaConversions.scala2
-rwxr-xr-xsrc/library/scala/collection/JavaConverters.scala2
-rw-r--r--src/library/scala/collection/convert/DecorateAsJava.scala20
-rw-r--r--src/library/scala/collection/convert/DecorateAsScala.scala21
-rw-r--r--src/library/scala/collection/convert/WrapAsJava.scala31
-rw-r--r--src/library/scala/collection/convert/WrapAsScala.scala25
-rw-r--r--src/library/scala/collection/convert/Wrappers.scala51
-rw-r--r--src/library/scala/collection/mutable/HashTable.scala2
-rw-r--r--src/library/scala/concurrent/ConcurrentPackageObject.scala57
-rw-r--r--src/library/scala/concurrent/ExecutionContext.scala7
-rw-r--r--src/library/scala/concurrent/Future.scala106
-rw-r--r--src/library/scala/concurrent/Promise.scala17
-rw-r--r--src/library/scala/concurrent/impl/ExecutionContextImpl.scala43
-rw-r--r--src/library/scala/concurrent/impl/Future.scala39
-rw-r--r--src/library/scala/concurrent/impl/Promise.scala48
-rw-r--r--src/library/scala/math/BigDecimal.scala15
-rw-r--r--src/library/scala/math/BigInt.scala38
-rw-r--r--src/library/scala/util/Try.scala53
-rw-r--r--test/disabled/continuations-neg/infer0.check (renamed from test/files/continuations-neg/infer0.check)0
-rw-r--r--test/disabled/continuations-neg/infer0.scala (renamed from test/files/continuations-neg/infer0.scala)8
-rw-r--r--test/files/continuations-run/shift-pct.check25
-rw-r--r--test/files/continuations-run/shift-pct.scala30
-rw-r--r--test/files/continuations-run/z1673.check0
-rw-r--r--test/files/continuations-run/z1673.scala31
-rw-r--r--test/files/jvm/scala-concurrent-tck.scala80
-rw-r--r--test/files/neg/variances.check19
-rw-r--r--test/files/neg/variances.scala29
-rw-r--r--test/files/pos/t3272.scala8
-rw-r--r--test/files/pos/t4910.scala6
-rw-r--r--test/files/presentation/memory-leaks.check14
-rw-r--r--test/files/presentation/memory-leaks/MemoryLeaksTest.scala125
-rw-r--r--test/files/run/concurrent-map-conversions.scala36
-rw-r--r--test/files/run/is-valid-num.scala77
-rw-r--r--test/files/run/numbereq.scala35
-rw-r--r--test/files/run/option-fold.check5
-rw-r--r--test/files/run/option-fold.scala19
-rw-r--r--test/files/run/reflect-overload.scala16
53 files changed, 1216 insertions, 250 deletions
diff --git a/build.xml b/build.xml
index 56c9bccf57..6f3e4a8d19 100644
--- a/build.xml
+++ b/build.xml
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
-<project name="sabbus" default="build">
+<project name="sabbus" default="build" xmlns:artifact="urn:maven-artifact-ant">
<description>
SuperSabbus for Scala core, builds the scala library and compiler. It can also package it as a simple distribution, tests it for stable bootstrapping and against the Scala test suite.
</description>
@@ -238,6 +238,21 @@ INITIALISATION
</touch>
</target>
+ <!-- Add our maven ant tasks -->
+ <target name="init.maven.tasks" depends="init.jars.check" unless="init.maven.tasks.finished">
+ <path id="maven-ant-tasks.classpath" path="${lib.dir}/ant/maven-ant-tasks-2.1.1.jar" />
+ <typedef resource="org/apache/maven/artifact/ant/antlib.xml" uri="urn:maven-artifact-ant" classpathref="maven-ant-tasks.classpath" />
+
+ <property name="init.maven.tasks.finished" value="true" />
+ </target>
+
+ <!-- Resolve maven dependencies -->
+ <target name="init.maven.jars" depends="init.maven.tasks">
+ <artifact:dependencies pathId="dependency.classpath" filesetId="dependency.fileset">
+ <dependency groupId="org.skife.com.typesafe.config" artifactId="typesafe-config" version="0.3.0"/>
+ </artifact:dependencies>
+ </target>
+
<!-- Determines OSGi string + maven extension. -->
<target name="init.hasbuildnum">
<condition property="version.hasbuildnum">
@@ -296,7 +311,7 @@ INITIALISATION
<target name="init.version.done" depends="init.version.release, init.version.snapshot"/>
- <target name="init" depends="init.jars, init.version.done">
+ <target name="init" depends="init.jars, init.maven.jars, init.version.done">
<!-- scalac.args.optimise is selectively overridden in certain antcall tasks. -->
<property name="scalac.args.optimise" value=""/>
<!-- scalac.args.quickonly are added to quick.* targets but not others (particularly, locker.)
@@ -337,6 +352,7 @@ INITIALISATION
</fileset>
<pathelement location="${ant.jar}"/>
<path refid="lib.extra"/>
+ <path refid="dependency.classpath"/>
</path>
<!-- And print-out what we are building -->
@@ -1002,6 +1018,11 @@ PACKED QUICK BUILD (PACK)
<target name="pack.lib" depends="pack.pre-lib" unless="pack.lib.available">
<mkdir dir="${build-pack.dir}/lib"/>
+ <!-- First copy maven dependencies -->
+ <copy todir="${build-pack.dir}/lib">
+ <fileset refid="dependency.fileset" />
+ <mapper type="flatten" />
+ </copy>
<jar destfile="${build-pack.dir}/lib/scala-library.jar">
<fileset dir="${build-quick.dir}/classes/library">
<exclude name="scala/dbc/**"/>
diff --git a/src/build/maven/scala-library-pom.xml b/src/build/maven/scala-library-pom.xml
index 673c3dfada..c3f8a4531c 100644
--- a/src/build/maven/scala-library-pom.xml
+++ b/src/build/maven/scala-library-pom.xml
@@ -30,17 +30,24 @@
<system>JIRA</system>
<url>https://issues.scala-lang.org/</url>
</issueManagement>
- <distributionManagement>
- <repository>
- <id>scala-tools.org</id>
- <url>@RELEASE_REPOSITORY@</url>
- </repository>
- <snapshotRepository>
- <id>scala-tools.org</id>
- <url>@SNAPSHOT_REPOSITORY@</url>
- <uniqueVersion>false</uniqueVersion>
- </snapshotRepository>
- </distributionManagement>
+ <dependencies>
+ <dependency>
+ <groupId>org.skife.com.typesafe.config</groupId>
+ <artifactId>typesafe-config</artifactId>
+ <version>0.3.0</version>
+ </dependency>
+ </dependencies>
+ <distributionManagement>
+ <repository>
+ <id>scala-tools.org</id>
+ <url>@RELEASE_REPOSITORY@</url>
+ </repository>
+ <snapshotRepository>
+ <id>scala-tools.org</id>
+ <url>@SNAPSHOT_REPOSITORY@</url>
+ <uniqueVersion>false</uniqueVersion>
+ </snapshotRepository>
+ </distributionManagement>
<developers>
<developer>
<id>lamp</id>
diff --git a/src/compiler/scala/reflect/internal/SymbolTable.scala b/src/compiler/scala/reflect/internal/SymbolTable.scala
index bb11ca634a..256c1a6ced 100644
--- a/src/compiler/scala/reflect/internal/SymbolTable.scala
+++ b/src/compiler/scala/reflect/internal/SymbolTable.scala
@@ -62,6 +62,11 @@ abstract class SymbolTable extends api.Universe
result
}
+ final val traceSymbolActivity = sys.props contains "scalac.debug.syms"
+ object traceSymbols extends {
+ val global: SymbolTable.this.type = SymbolTable.this
+ } with util.TraceSymbolActivity
+
/** Are we compiling for Java SE? */
// def forJVM: Boolean
diff --git a/src/compiler/scala/reflect/internal/Symbols.scala b/src/compiler/scala/reflect/internal/Symbols.scala
index 4842d47e4d..63d030531d 100644
--- a/src/compiler/scala/reflect/internal/Symbols.scala
+++ b/src/compiler/scala/reflect/internal/Symbols.scala
@@ -3,7 +3,6 @@
* @author Martin Odersky
*/
-
package scala.reflect
package internal
@@ -166,9 +165,11 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
private var rawpos = initPos
val id = nextId() // identity displayed when -uniqid
-
private[this] var _validTo: Period = NoPeriod
+ if (traceSymbolActivity)
+ traceSymbols.recordNewSymbol(this)
+
def validTo = _validTo
def validTo_=(x: Period) { _validTo = x}
@@ -863,6 +864,8 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
else originalOwner(this) = rawowner
}
assert(!inReflexiveMirror, "owner_= is not thread-safe; cannot be run in reflexive code")
+ if (traceSymbolActivity)
+ traceSymbols.recordNewSymbolOwner(this, owner)
_rawowner = owner
}
diff --git a/src/compiler/scala/reflect/internal/Types.scala b/src/compiler/scala/reflect/internal/Types.scala
index 5afa5343ed..786b680ff8 100644
--- a/src/compiler/scala/reflect/internal/Types.scala
+++ b/src/compiler/scala/reflect/internal/Types.scala
@@ -5059,6 +5059,8 @@ trait Types extends api.Types { self: SymbolTable =>
case (_, tv @ TypeVar(_,_)) => tv.registerTypeSelection(tr2.sym, tr1)
case _ => false
})
+ case _: SingleType =>
+ return isSameType2(tp2, tp1) // put singleton type on the left, caught below
case _ =>
}
case tt1: ThisType =>
@@ -5071,6 +5073,8 @@ trait Types extends api.Types { self: SymbolTable =>
tp2 match {
case st2: SingleType =>
if (equalSymsAndPrefixes(st1.sym, st1.pre, st2.sym, st2.pre)) return true
+ case TypeRef(pre2, sym2, Nil) =>
+ if (sym2.isModuleClass && equalSymsAndPrefixes(st1.sym, st1.pre, sym2.sourceModule, pre2)) return true
case _ =>
}
case ct1: ConstantType =>
@@ -5481,7 +5485,7 @@ trait Types extends api.Types { self: SymbolTable =>
* - handle typerefs, refined types, notnull and singleton types.
*/
def fourthTry = tp1 match {
- case tr1 @ TypeRef(_, sym1, _) =>
+ case tr1 @ TypeRef(pre1, sym1, _) =>
sym1 match {
case NothingClass => true
case NullClass =>
@@ -5495,8 +5499,8 @@ trait Types extends api.Types { self: SymbolTable =>
if (isRaw(sym1, tr1.args))
isSubType(rawToExistential(tp1), tp2, depth)
else if (sym1.isModuleClass) tp2 match {
- case SingleType(_, sym2) => sym1 == sym2
- case _ => false
+ case SingleType(pre2, sym2) => equalSymsAndPrefixes(sym1.sourceModule, pre1, sym2, pre2)
+ case _ => false
}
else if (sym1.isRefinementClass)
isSubType(sym1.info, tp2, depth)
diff --git a/src/compiler/scala/reflect/internal/util/TraceSymbolActivity.scala b/src/compiler/scala/reflect/internal/util/TraceSymbolActivity.scala
new file mode 100644
index 0000000000..eb384f9a85
--- /dev/null
+++ b/src/compiler/scala/reflect/internal/util/TraceSymbolActivity.scala
@@ -0,0 +1,168 @@
+package scala.reflect.internal
+package util
+
+import scala.collection.{ mutable, immutable }
+
+trait TraceSymbolActivity {
+ val global: SymbolTable
+ import global._
+
+ if (traceSymbolActivity)
+ scala.sys addShutdownHook showAllSymbols()
+
+ private type Set[T] = scala.collection.immutable.Set[T]
+ private val Set = scala.collection.immutable.Set
+
+ val allSymbols = mutable.Map[Int, Symbol]()
+ val allChildren = mutable.Map[Int, List[Int]]() withDefaultValue Nil
+ val prevOwners = mutable.Map[Int, List[(Int, Phase)]]() withDefaultValue Nil
+ val symsCaused = mutable.Map[Int, Int]() withDefaultValue 0
+ val allTrees = mutable.Set[Tree]()
+
+ def recordSymbolsInTree(tree: Tree) {
+ allTrees += tree
+ }
+
+ def recordNewSymbol(sym: Symbol) {
+ if (sym.id > 1) {
+ allSymbols(sym.id) = sym
+ allChildren(sym.owner.id) ::= sym.id
+ }
+ }
+ def recordNewSymbolOwner(sym: Symbol, newOwner: Symbol) {
+ val sid = sym.id
+ val oid = sym.owner.id
+ val nid = newOwner.id
+
+ prevOwners(sid) ::= (oid -> phase)
+ allChildren(oid) = allChildren(oid) filterNot (_ == sid)
+ allChildren(nid) ::= sid
+ }
+
+ /** TODO.
+ */
+ private def reachableDirectlyFromSymbol(sym: Symbol): List[Symbol] = (
+ List(sym.owner, sym.alias, sym.thisSym)
+ ++ sym.children
+ ++ sym.info.parents.map(_.typeSymbol)
+ ++ sym.typeParams
+ ++ sym.paramss.flatten
+ )
+ private def reachable[T](inputs: Traversable[T], mkSymbol: T => Symbol): Set[Symbol] = {
+ def loop(seen: Set[Symbol], remaining: List[Symbol]): Set[Symbol] = {
+ remaining match {
+ case Nil => seen
+ case head :: rest =>
+ if ((head eq null) || (head eq NoSymbol) || seen(head)) loop(seen, rest)
+ else loop(seen + head, rest ++ reachableDirectlyFromSymbol(head).filterNot(seen))
+ }
+ }
+ loop(immutable.Set(), inputs.toList map mkSymbol filterNot (_ eq null) distinct)
+ }
+ private def treeList(t: Tree) = {
+ val buf = mutable.ListBuffer[Tree]()
+ t foreach (buf += _)
+ buf.toList
+ }
+
+ private def reachableFromSymbol(root: Symbol): Set[Symbol] =
+ reachable[Symbol](List(root, root.info.typeSymbol), x => x)
+
+ private def reachableFromTree(tree: Tree): Set[Symbol] =
+ reachable[Tree](treeList(tree), _.symbol)
+
+ private def signature(id: Int) = runBeforeErasure(allSymbols(id).defString)
+
+ private def dashes(s: Any): String = ("" + s) map (_ => '-')
+ private def show(s1: Any, ss: Any*) {
+ println("%-12s".format(s1) +: ss mkString " ")
+ }
+ private def showHeader(s1: Any, ss: Any*) {
+ show(s1, ss: _*)
+ show(dashes(s1), ss map dashes: _*)
+ }
+ private def showSym(sym: Symbol) {
+ def prefix = (" " * (sym.ownerChain.length - 1)) + sym.id
+ try println("%s#%s %s".format(prefix, sym.accurateKindString, sym.name.decode))
+ catch {
+ case x => println(prefix + " failed: " + x)
+ }
+ allChildren(sym.id).sorted foreach showIdAndRemove
+ }
+ private def showIdAndRemove(id: Int) {
+ allSymbols remove id foreach showSym
+ }
+ private def symbolStr(id: Int): String = {
+ if (id == 1) "NoSymbol" else {
+ val sym = allSymbols(id)
+ sym.accurateKindString + " " + sym.name.decode
+ }
+ }
+ private def ownerStr(id: Int): String = {
+ val sym = allSymbols(id)
+ sym.name.decode + "#" + sym.id
+ }
+
+ private def freq[T, U](xs: collection.Traversable[T])(fn: T => U): List[(U, Int)] = {
+ val ys = xs groupBy fn mapValues (_.size)
+ ys.toList sortBy (-_._2)
+ }
+
+ private def showMapFreq[T](xs: collection.Map[T, Traversable[_]])(showFn: T => String) {
+ xs.mapValues(_.size).toList.sortBy(-_._2) take 100 foreach { case (k, size) =>
+ show(size, showFn(k))
+ }
+ println("\n")
+ }
+ private def showFreq[T, U](xs: Traversable[T])(groupFn: T => U, showFn: U => String = (x: U) => "" + x) = {
+ showMapFreq(xs.toList groupBy groupFn)(showFn)
+ }
+ private lazy val findErasurePhase: Phase = {
+ var ph = phase
+ while (ph != NoPhase && ph.name != "erasure") {
+ ph = ph.prev
+ }
+ ph
+ }
+ private def runBeforeErasure[T](body: => T): T = atPhase(findErasurePhase)(body)
+
+ def showAllSymbols() {
+ if (!traceSymbolActivity) return
+ allSymbols(1) = NoSymbol
+
+ println("" + allSymbols.size + " symbols created.")
+ println("")
+
+ showHeader("descendants", "symbol")
+ showFreq(allSymbols.values flatMap (_.ownerChain drop 1))(_.id, symbolStr)
+
+ showHeader("children", "symbol")
+ showMapFreq(allChildren)(symbolStr)
+
+ if (prevOwners.nonEmpty) {
+ showHeader("prev owners", "symbol")
+ showMapFreq(prevOwners) { k =>
+ val owners = (((allSymbols(k).owner.id, NoPhase)) :: prevOwners(k)) map {
+ case (oid, NoPhase) => "-> owned by " + ownerStr(oid)
+ case (oid, ph) => "-> owned by %s (until %s)".format(ownerStr(oid), ph)
+ }
+ signature(k) :: owners mkString "\n "
+ }
+ }
+
+ val nameFreq = allSymbols.values.toList groupBy (_.name)
+ showHeader("frequency", "%-15s".format("name"), "owners")
+ showMapFreq(nameFreq) { name =>
+ "%-15s %s".format(name.decode, {
+ val owners = freq(nameFreq(name))(_.owner)
+
+ "%4s owners (%s)".format(
+ owners.size,
+ owners.take(3).map({ case (k, v) => v + "/" + k }).mkString(", ") + ", ..."
+ )
+ })
+ }
+
+ allSymbols.keys.toList.sorted foreach showIdAndRemove
+ }
+}
diff --git a/src/compiler/scala/tools/nsc/Global.scala b/src/compiler/scala/tools/nsc/Global.scala
index 9ccd0c28db..6a30dc2a0f 100644
--- a/src/compiler/scala/tools/nsc/Global.scala
+++ b/src/compiler/scala/tools/nsc/Global.scala
@@ -1356,6 +1356,9 @@ class Global(var currentSettings: Settings, var reporter: Reporter) extends Symb
inform(unitTimingsFormatted)
}
+ if (traceSymbolActivity)
+ units map (_.body) foreach (traceSymbols recordSymbolsInTree _)
+
// In case no phase was specified for -Xshow-class/object, show it now for sure.
if (opt.noShow)
showMembers()
diff --git a/src/compiler/scala/tools/nsc/interactive/tests/InteractiveTest.scala b/src/compiler/scala/tools/nsc/interactive/tests/InteractiveTest.scala
index 7be115e777..9dc2a8de10 100644
--- a/src/compiler/scala/tools/nsc/interactive/tests/InteractiveTest.scala
+++ b/src/compiler/scala/tools/nsc/interactive/tests/InteractiveTest.scala
@@ -55,6 +55,7 @@ abstract class InteractiveTest
with AskShutdown
with AskReload
with AskLoadedTyped
+ with AskType
with PresentationCompilerInstance
with CoreTestDefs
with InteractiveTestSettings { self =>
diff --git a/src/compiler/scala/tools/nsc/interactive/tests/core/AskCommand.scala b/src/compiler/scala/tools/nsc/interactive/tests/core/AskCommand.scala
index 35d6723818..657ef23eed 100644
--- a/src/compiler/scala/tools/nsc/interactive/tests/core/AskCommand.scala
+++ b/src/compiler/scala/tools/nsc/interactive/tests/core/AskCommand.scala
@@ -101,13 +101,13 @@ trait AskTypeAt extends AskCommand {
trait AskType extends AskCommand {
import compiler.Tree
- private[tests] def askType(source: SourceFile, forceReload: Boolean)(implicit reporter: Reporter): Response[Tree] = {
+ protected def askType(source: SourceFile, forceReload: Boolean)(implicit reporter: Reporter): Response[Tree] = {
ask {
compiler.askType(source, forceReload, _)
}
}
- private[tests] def askType(sources: Seq[SourceFile], forceReload: Boolean)(implicit reporter: Reporter): Seq[Response[Tree]] = {
+ protected def askType(sources: Seq[SourceFile], forceReload: Boolean)(implicit reporter: Reporter): Seq[Response[Tree]] = {
for(source <- sources) yield
askType(source, forceReload)
}
diff --git a/src/compiler/scala/tools/nsc/typechecker/Infer.scala b/src/compiler/scala/tools/nsc/typechecker/Infer.scala
index a1ca4904f4..dba31f7bca 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Infer.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Infer.scala
@@ -484,8 +484,7 @@ trait Infer {
else Some(
if (targ.typeSymbol == RepeatedParamClass) targ.baseType(SeqClass)
else if (targ.typeSymbol == JavaRepeatedParamClass) targ.baseType(ArrayClass)
- // this infers Foo.type instead of "object Foo" (see also widenIfNecessary)
- else if (targ.typeSymbol.isModuleClass || ((opt.experimental || opt.virtPatmat) && tvar.constr.avoidWiden)) targ
+ else if ((opt.experimental || opt.virtPatmat) && tvar.constr.avoidWiden) targ
else targ.widen
)
))
diff --git a/src/compiler/scala/tools/nsc/typechecker/Namers.scala b/src/compiler/scala/tools/nsc/typechecker/Namers.scala
index 8604366bf2..1b505d1e5d 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Namers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Namers.scala
@@ -793,10 +793,7 @@ trait Namers extends MethodSynthesis {
val tpe1 = dropRepeatedParamType(tpe.deconst)
val tpe2 = tpe1.widen
- // This infers Foo.type instead of "object Foo"
- // See Infer#adjustTypeArgs for the polymorphic case.
- if (tpe.typeSymbolDirect.isModuleClass) tpe1
- else if (sym.isVariable || sym.isMethod && !sym.hasAccessorFlag)
+ if (sym.isVariable || sym.isMethod && !sym.hasAccessorFlag)
if (tpe2 <:< pt) tpe2 else tpe1
else if (isHidden(tpe)) tpe2
// In an attempt to make pattern matches involving method local vals
diff --git a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala
index 045614e773..54b711cebc 100644
--- a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala
@@ -951,17 +951,20 @@ abstract class RefChecks extends InfoTransform with reflect.internal.transform.R
override def traverse(tree: Tree) {
tree match {
- case ClassDef(_, _, _, _) |
- TypeDef(_, _, _, _) =>
+ case ClassDef(_, _, _, _) | TypeDef(_, _, _, _) =>
validateVariance(tree.symbol)
super.traverse(tree)
// ModuleDefs need not be considered because they have been eliminated already
case ValDef(_, _, _, _) =>
- validateVariance(tree.symbol)
+ if (!tree.symbol.hasLocalFlag)
+ validateVariance(tree.symbol)
case DefDef(_, _, tparams, vparamss, _, _) =>
- validateVariance(tree.symbol)
- traverseTrees(tparams)
- traverseTreess(vparamss)
+ // No variance check for object-private/protected methods/values.
+ if (!tree.symbol.hasLocalFlag) {
+ validateVariance(tree.symbol)
+ traverseTrees(tparams)
+ traverseTreess(vparamss)
+ }
case Template(_, _, _) =>
super.traverse(tree)
case _ =>
diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
index 2aff00f6a5..36c81b09cd 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
@@ -2089,7 +2089,10 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
for (Apply(_, xs) <- cdef.pat ; x <- xs dropRight 1 ; if treeInfo isStar x)
StarPositionInPatternError(x)
- val pat1 = typedPattern(cdef.pat, pattpe)
+ // withoutAnnotations - see continuations-run/z1673.scala
+ // This adjustment is awfully specific to continuations, but AFAICS the
+ // whole AnnotationChecker framework is.
+ val pat1 = typedPattern(cdef.pat, pattpe.withoutAnnotations)
// When case classes have more than two parameter lists, the pattern ends
// up typed as a method. We only pattern match on the first parameter
// list, so substitute the final result type of the method, i.e. the type
@@ -2199,7 +2202,7 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
vparams map {p => if(p.tpt.tpe == null) typedType(p.tpt).tpe else p.tpt.tpe}
}
- def mkParams(methodSym: Symbol, formals: List[Type] = deriveFormals) = {
+ def mkParams(methodSym: Symbol, formals: List[Type]/* = deriveFormals*/) = {
selOverride match {
case None if targs.isEmpty => MissingParameterTypeAnonMatchError(tree, pt); (Nil, EmptyTree)
case None =>
@@ -2225,7 +2228,7 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
// rig the show so we can get started typing the method body -- later we'll correct the infos...
anonClass setInfo ClassInfoType(List(ObjectClass.tpe, pt, SerializableClass.tpe), newScope, anonClass)
val methodSym = anonClass.newMethod(nme.apply, tree.pos, FINAL)
- val (paramSyms, selector) = mkParams(methodSym)
+ val (paramSyms, selector) = mkParams(methodSym, deriveFormals)
if (selector eq EmptyTree) EmptyTree
else {
@@ -2289,7 +2292,7 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
def isDefinedAtMethod = {
val methodSym = anonClass.newMethod(nme.isDefinedAt, tree.pos, FINAL)
- val (paramSyms, selector) = mkParams(methodSym)
+ val (paramSyms, selector) = mkParams(methodSym, deriveFormals)
if (selector eq EmptyTree) EmptyTree
else {
val methodBodyTyper = newTyper(context.makeNewScope(context.tree, methodSym)) // should use the DefDef for the context's tree, but it doesn't exist yet (we need the typer we're creating to create it)
diff --git a/src/continuations/plugin/scala/tools/selectivecps/CPSUtils.scala b/src/continuations/plugin/scala/tools/selectivecps/CPSUtils.scala
index 075009ce5e..67ea6e15f0 100644
--- a/src/continuations/plugin/scala/tools/selectivecps/CPSUtils.scala
+++ b/src/continuations/plugin/scala/tools/selectivecps/CPSUtils.scala
@@ -24,6 +24,7 @@ trait CPSUtils {
val shift = newTermName("shift")
val shiftR = newTermName("shiftR")
val shiftSuffix = newTermName("$shift")
+ val shiftUnit0 = newTermName("shiftUnit0")
val shiftUnit = newTermName("shiftUnit")
val shiftUnitR = newTermName("shiftUnitR")
}
@@ -38,6 +39,7 @@ trait CPSUtils {
lazy val ModCPS = definitions.getRequiredModule("scala.util.continuations")
lazy val MethShiftUnit = definitions.getMember(ModCPS, cpsNames.shiftUnit)
+ lazy val MethShiftUnit0 = definitions.getMember(ModCPS, cpsNames.shiftUnit0)
lazy val MethShiftUnitR = definitions.getMember(ModCPS, cpsNames.shiftUnitR)
lazy val MethShift = definitions.getMember(ModCPS, cpsNames.shift)
lazy val MethShiftR = definitions.getMember(ModCPS, cpsNames.shiftR)
diff --git a/src/continuations/plugin/scala/tools/selectivecps/SelectiveANFTransform.scala b/src/continuations/plugin/scala/tools/selectivecps/SelectiveANFTransform.scala
index 1189cc2e38..a6737573ea 100644
--- a/src/continuations/plugin/scala/tools/selectivecps/SelectiveANFTransform.scala
+++ b/src/continuations/plugin/scala/tools/selectivecps/SelectiveANFTransform.scala
@@ -310,15 +310,23 @@ abstract class SelectiveANFTransform extends PluginComponent with Transform with
try {
val Some((a, b)) = cpsR
-
- val res = localTyper.typed(atPos(tree.pos) {
- Apply(TypeApply(gen.mkAttributedRef(MethShiftUnit),
- List(TypeTree(plainTpe), TypeTree(a), TypeTree(b))),
- List(expr))
- })
- return (stms, res)
-
- } catch {
+ /** Since shiftUnit is bounded [A,B,C>:B] this may not typecheck
+ * if C is overly specific. So if !(B <:< C), call shiftUnit0
+ * instead, which takes only two type arguments.
+ */
+ val conforms = a <:< b
+ val call = localTyper.typedPos(tree.pos)(
+ Apply(
+ TypeApply(
+ gen.mkAttributedRef( if (conforms) MethShiftUnit else MethShiftUnit0 ),
+ List(TypeTree(plainTpe), TypeTree(a)) ++ ( if (conforms) List(TypeTree(b)) else Nil )
+ ),
+ List(expr)
+ )
+ )
+ return ((stms, call))
+ }
+ catch {
case ex:TypeError =>
unit.error(ex.pos, "cannot cps-transform expression " + tree + ": " + ex.msg)
}
diff --git a/src/library/scala/Option.scala b/src/library/scala/Option.scala
index 6db4904b93..2d87ccb261 100644
--- a/src/library/scala/Option.scala
+++ b/src/library/scala/Option.scala
@@ -130,6 +130,18 @@ sealed abstract class Option[+A] extends Product with Serializable {
@inline final def map[B](f: A => B): Option[B] =
if (isEmpty) None else Some(f(this.get))
+ /** Returns the result of applying $f to this $option's
+ * value if the $option is nonempty. Otherwise, evaluates
+ * expression $ifEmpty.
+ *
+ * @note This is equivalent to `$option map f getOrElse ifEmpty`.
+ *
+ * @param ifEmpty the expression to evaluate if empty.
+ * @param f the function to apply if nonempty.
+ */
+ @inline final def fold[B](ifEmpty: => B)(f: A => B): B =
+ if (isEmpty) ifEmpty else f(this.get)
+
/** Returns the result of applying $f to this $option's value if
* this $option is nonempty.
* Returns $none if this $option is empty.
diff --git a/src/library/scala/collection/JavaConversions.scala b/src/library/scala/collection/JavaConversions.scala
index 75ab3f28f5..a978a9a783 100644
--- a/src/library/scala/collection/JavaConversions.scala
+++ b/src/library/scala/collection/JavaConversions.scala
@@ -127,3 +127,5 @@ object JavaConversions extends WrapAsScala with WrapAsJava {
@deprecated("use propertiesAsScalaMap instead", "2.9.0")
def asScalaMap(p: ju.Properties): mutable.Map[String, String] = propertiesAsScalaMap(p)
}
+
+
diff --git a/src/library/scala/collection/JavaConverters.scala b/src/library/scala/collection/JavaConverters.scala
index 13f1f19f81..f8a9466caf 100755
--- a/src/library/scala/collection/JavaConverters.scala
+++ b/src/library/scala/collection/JavaConverters.scala
@@ -100,4 +100,4 @@ object JavaConverters extends DecorateAsJava with DecorateAsScala {
@deprecated("Use propertiesAsScalaMapConverter instead", "2.9.0")
def asScalaMapConverter(p: ju.Properties): AsScala[mutable.Map[String, String]] = propertiesAsScalaMapConverter(p)
-} \ No newline at end of file
+}
diff --git a/src/library/scala/collection/convert/DecorateAsJava.scala b/src/library/scala/collection/convert/DecorateAsJava.scala
index 76837d937c..e05bfc41cd 100644
--- a/src/library/scala/collection/convert/DecorateAsJava.scala
+++ b/src/library/scala/collection/convert/DecorateAsJava.scala
@@ -291,6 +291,26 @@ trait DecorateAsJava {
* @return An object with an `asJava` method that returns a Java
* `ConcurrentMap` view of the argument.
*/
+ @deprecated("Use `concurrent.Map` instead of `ConcurrentMap`.", "2.10.0")
implicit def asJavaConcurrentMapConverter[A, B](m: mutable.ConcurrentMap[A, B]): AsJava[juc.ConcurrentMap[A, B]] =
new AsJava(asJavaConcurrentMap(m))
+
+ /**
+ * Adds an `asJava` method that implicitly converts a Scala mutable
+ * `concurrent.Map` to a Java `ConcurrentMap`.
+ *
+ * The returned Java `ConcurrentMap` is backed by the provided Scala
+ * `concurrent.Map` and any side-effects of using it via the Java interface
+ * will be visible via the Scala interface and vice versa.
+ *
+ * If the Scala `concurrent.Map` was previously obtained from an implicit or
+ * explicit call of `asConcurrentMap(java.util.concurrect.ConcurrentMap)`
+ * then the original Java `ConcurrentMap` will be returned.
+ *
+ * @param m The Scala `concurrent.Map` to be converted.
+ * @return An object with an `asJava` method that returns a Java
+ * `ConcurrentMap` view of the argument.
+ */
+ implicit def asJavaConcurrentMapConverter[A, B](m: concurrent.Map[A, B]): AsJava[juc.ConcurrentMap[A, B]] =
+ new AsJava(asJavaConcurrentMap(m))
}
diff --git a/src/library/scala/collection/convert/DecorateAsScala.scala b/src/library/scala/collection/convert/DecorateAsScala.scala
index bb14228e67..722f0b9af9 100644
--- a/src/library/scala/collection/convert/DecorateAsScala.scala
+++ b/src/library/scala/collection/convert/DecorateAsScala.scala
@@ -156,10 +156,29 @@ trait DecorateAsScala {
* @return An object with an `asScala` method that returns a Scala mutable
* `ConcurrentMap` view of the argument.
*/
- implicit def asScalaConcurrentMapConverter[A, B](m: juc.ConcurrentMap[A, B]): AsScala[mutable.ConcurrentMap[A, B]] =
+ @deprecated("Use `mapAsScalaConcurrentMapConverter` instead, and use `concurrent.Map` instead of `ConcurrentMap`.", "2.10.0")
+ 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 `ConcurrentMap`
+ * to a Scala mutable `concurrent.Map`. The returned Scala `concurrent.Map` is
+ * backed by the provided Java `ConcurrentMap` and any side-effects of using
+ * it via the Scala interface will be visible via the Java interface and
+ * vice versa.
+ *
+ * If the Java `ConcurrentMap` was previously obtained from an implicit or
+ * explicit call of `mapAsScalaConcurrentMap(scala.collection.mutable.ConcurrentMap)`
+ * then the original Scala `concurrent.Map` will be returned.
+ *
+ * @param m The `ConcurrentMap` to be converted.
+ * @return An object with an `asScala` method that returns a Scala mutable
+ * `concurrent.Map` view of the argument.
+ */
+ implicit def mapAsScalaConcurrentMapConverter[A, B](m: juc.ConcurrentMap[A, B]): AsScala[concurrent.Map[A, B]] =
+ new AsScala(mapAsScalaConcurrentMap(m))
+
+ /**
* Adds an `asScala` method that implicitly converts a Java `Dictionary`
* to a Scala mutable `Map[String, String]`. The returned Scala
* `Map[String, String]` is backed by the provided Java `Dictionary` and
diff --git a/src/library/scala/collection/convert/WrapAsJava.scala b/src/library/scala/collection/convert/WrapAsJava.scala
index 6274518d1a..cdec72b9fe 100644
--- a/src/library/scala/collection/convert/WrapAsJava.scala
+++ b/src/library/scala/collection/convert/WrapAsJava.scala
@@ -241,16 +241,45 @@ trait WrapAsJava {
* will be visible via the Scala interface and vice versa.
*
* If the Scala `ConcurrentMap` was previously obtained from an implicit or
- * explicit call of `asConcurrentMap(java.util.concurrect.ConcurrentMap)`
+ * explicit call of `asScalaConcurrentMap(java.util.concurrect.ConcurrentMap)`
* then the original Java ConcurrentMap will be returned.
*
* @param m The `ConcurrentMap` to be converted.
* @return A Java `ConcurrentMap` view of the argument.
*/
+ @deprecated("Use `concurrent.Map` instead of `ConcurrentMap`.", "2.10.0")
implicit def asJavaConcurrentMap[A, B](m: mutable.ConcurrentMap[A, B]): juc.ConcurrentMap[A, B] = m match {
+ case JConcurrentMapDeprecatedWrapper(wrapped) => wrapped
+ case _ => new ConcurrentMapDeprecatedWrapper(m)
+ }
+
+ /**
+ * Implicitly converts a Scala mutable `concurrent.Map` to a Java
+ * `ConcurrentMap`.
+ *
+ * The returned Java `ConcurrentMap` is backed by the provided Scala
+ * `concurrent.Map` and any side-effects of using it via the Java interface
+ * will be visible via the Scala interface and vice versa.
+ *
+ * If the Scala `concurrent.Map` was previously obtained from an implicit or
+ * explicit call of `mapAsScalaConcurrentMap(java.util.concurrect.ConcurrentMap)`
+ * then the original Java ConcurrentMap will be returned.
+ *
+ * @param m The Scala `concurrent.Map` to be converted.
+ * @return A Java `ConcurrentMap` view of the argument.
+ */
+ implicit def asJavaConcurrentMap[A, B](m: concurrent.Map[A, B]): juc.ConcurrentMap[A, B] = m match {
case JConcurrentMapWrapper(wrapped) => wrapped
case _ => new ConcurrentMapWrapper(m)
}
}
object WrapAsJava extends WrapAsJava { }
+
+
+
+
+
+
+
+
diff --git a/src/library/scala/collection/convert/WrapAsScala.scala b/src/library/scala/collection/convert/WrapAsScala.scala
index 02b58f55a4..56e13b2105 100644
--- a/src/library/scala/collection/convert/WrapAsScala.scala
+++ b/src/library/scala/collection/convert/WrapAsScala.scala
@@ -154,9 +154,28 @@ trait WrapAsScala {
* @param m The ConcurrentMap to be converted.
* @return A Scala mutable ConcurrentMap view of the argument.
*/
- 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 `mapAsScalaConcurrentMap` instead, and use `concurrent.Map` instead of `ConcurrentMap`.", "2.10.0")
+ def asScalaConcurrentMap[A, B](m: juc.ConcurrentMap[A, B]): mutable.ConcurrentMap[A, B] = m match {
+ case cmw: ConcurrentMapDeprecatedWrapper[a, b] => cmw.underlying
+ case _ => new JConcurrentMapDeprecatedWrapper(m)
+ }
+
+ /**
+ * Implicitly converts a Java ConcurrentMap to a Scala mutable ConcurrentMap.
+ * The returned Scala ConcurrentMap is backed by the provided Java
+ * ConcurrentMap and any side-effects of using it via the Scala interface will
+ * be visible via the Java interface and vice versa.
+ *
+ * If the Java ConcurrentMap was previously obtained from an implicit or
+ * explicit call of `asConcurrentMap(scala.collection.mutable.ConcurrentMap)`
+ * then the original Scala ConcurrentMap will be returned.
+ *
+ * @param m The ConcurrentMap to be converted.
+ * @return A Scala mutable ConcurrentMap view of the argument.
+ */
+ implicit def mapAsScalaConcurrentMap[A, B](m: juc.ConcurrentMap[A, B]): concurrent.Map[A, B] = m match {
+ case cmw: ConcurrentMapWrapper[a, b] => cmw.underlying
+ case _ => new JConcurrentMapWrapper(m)
}
/**
diff --git a/src/library/scala/collection/convert/Wrappers.scala b/src/library/scala/collection/convert/Wrappers.scala
index 8136e462cb..b1b48b760f 100644
--- a/src/library/scala/collection/convert/Wrappers.scala
+++ b/src/library/scala/collection/convert/Wrappers.scala
@@ -268,7 +268,7 @@ private[collection] trait Wrappers {
override def empty = JMapWrapper(new ju.HashMap[A, B])
}
- class ConcurrentMapWrapper[A, B](override val underlying: mutable.ConcurrentMap[A, B]) extends MutableMapWrapper[A, B](underlying) with juc.ConcurrentMap[A, B] {
+ class ConcurrentMapDeprecatedWrapper[A, B](override val underlying: mutable.ConcurrentMap[A, B]) extends MutableMapWrapper[A, B](underlying) with juc.ConcurrentMap[A, B] {
def putIfAbsent(k: A, v: B) = underlying.putIfAbsent(k, v) match {
case Some(v) => v
@@ -290,7 +290,54 @@ private[collection] trait Wrappers {
def replace(k: A, oldval: B, newval: B) = underlying.replace(k, oldval, newval)
}
- case class JConcurrentMapWrapper[A, B](val underlying: juc.ConcurrentMap[A, B]) extends mutable.AbstractMap[A, B] with JMapWrapperLike[A, B, JConcurrentMapWrapper[A, B]] with mutable.ConcurrentMap[A, B] {
+ class ConcurrentMapWrapper[A, B](override val underlying: concurrent.Map[A, B]) extends MutableMapWrapper[A, B](underlying) with juc.ConcurrentMap[A, B] {
+
+ def putIfAbsent(k: A, v: B) = underlying.putIfAbsent(k, v) match {
+ case Some(v) => v
+ case None => null.asInstanceOf[B]
+ }
+
+ def remove(k: AnyRef, v: AnyRef) = try {
+ underlying.remove(k.asInstanceOf[A], v.asInstanceOf[B])
+ } catch {
+ case ex: ClassCastException =>
+ false
+ }
+
+ def replace(k: A, v: B): B = underlying.replace(k, v) match {
+ case Some(v) => v
+ case None => null.asInstanceOf[B]
+ }
+
+ def replace(k: A, oldval: B, newval: B) = underlying.replace(k, oldval, newval)
+ }
+
+ case class JConcurrentMapDeprecatedWrapper[A, B](val underlying: juc.ConcurrentMap[A, B]) extends mutable.AbstractMap[A, B] with JMapWrapperLike[A, B, JConcurrentMapDeprecatedWrapper[A, B]] with mutable.ConcurrentMap[A, B] {
+ override def get(k: A) = {
+ val v = underlying get k
+ if (v != null) Some(v)
+ else None
+ }
+
+ override def empty = new JConcurrentMapDeprecatedWrapper(new juc.ConcurrentHashMap[A, B])
+
+ def putIfAbsent(k: A, v: B): Option[B] = {
+ val r = underlying.putIfAbsent(k, v)
+ if (r != null) Some(r) else None
+ }
+
+ def remove(k: A, v: B): Boolean = underlying.remove(k, v)
+
+ def replace(k: A, v: B): Option[B] = {
+ val prev = underlying.replace(k, v)
+ if (prev != null) Some(prev) else None
+ }
+
+ def replace(k: A, oldvalue: B, newvalue: B): Boolean =
+ underlying.replace(k, oldvalue, newvalue)
+ }
+
+ case class JConcurrentMapWrapper[A, B](val underlying: juc.ConcurrentMap[A, B]) extends mutable.AbstractMap[A, B] with JMapWrapperLike[A, B, JConcurrentMapWrapper[A, B]] with concurrent.Map[A, B] {
override def get(k: A) = {
val v = underlying get k
if (v != null) Some(v)
diff --git a/src/library/scala/collection/mutable/HashTable.scala b/src/library/scala/collection/mutable/HashTable.scala
index cc0aed6963..06b7d40bfc 100644
--- a/src/library/scala/collection/mutable/HashTable.scala
+++ b/src/library/scala/collection/mutable/HashTable.scala
@@ -366,7 +366,7 @@ private[collection] object HashTable {
private[collection] final def newThreshold(_loadFactor: Int, size: Int) = ((size.toLong * _loadFactor) / loadFactorDenum).toInt
- private[collection] final def sizeForThreshold(_loadFactor: Int, thr: Int) = thr * loadFactorDenum / _loadFactor
+ private[collection] final def sizeForThreshold(_loadFactor: Int, thr: Int) = ((thr.toLong * loadFactorDenum) / _loadFactor).toInt
private[collection] final def capacity(expectedSize: Int) = if (expectedSize == 0) 1 else powerOfTwo(expectedSize)
diff --git a/src/library/scala/concurrent/ConcurrentPackageObject.scala b/src/library/scala/concurrent/ConcurrentPackageObject.scala
index ba98757906..0f882540f2 100644
--- a/src/library/scala/concurrent/ConcurrentPackageObject.scala
+++ b/src/library/scala/concurrent/ConcurrentPackageObject.scala
@@ -8,11 +8,8 @@
package scala.concurrent
-
-
-import java.util.concurrent.{ Executors, ExecutorService }
-import scala.concurrent.forkjoin.ForkJoinPool
-import scala.util.{ Try, Success, Failure }
+import java.util.concurrent.{ Executors, ExecutorService, ThreadFactory }
+import scala.concurrent.forkjoin.{ ForkJoinPool, ForkJoinWorkerThread }
import scala.concurrent.util.Duration
import ConcurrentPackageObject._
@@ -24,14 +21,9 @@ abstract class ConcurrentPackageObject {
/** A global execution environment for executing lightweight tasks.
*/
lazy val executionContext =
- new impl.ExecutionContextImpl(getExecutorService)
-
- private[concurrent] def getExecutorService: AnyRef =
- if (scala.util.Properties.isJavaAtLeast("1.6")) {
- val vendor = scala.util.Properties.javaVmVendor
- if ((vendor contains "Oracle") || (vendor contains "Sun") || (vendor contains "Apple")) new ForkJoinPool
- else Executors.newCachedThreadPool()
- } else Executors.newCachedThreadPool()
+ new impl.ExecutionContextImpl()
+
+ private val currentExecutionContext = new ThreadLocal[ExecutionContext]
val handledFutureException: PartialFunction[Throwable, Throwable] = {
case t: Throwable if isFutureThrowable(t) => t
@@ -45,23 +37,23 @@ abstract class ConcurrentPackageObject {
case _ => true
}
- private[concurrent] def resolve[T](source: Try[T]): Try[T] = source match {
- case Failure(t: scala.runtime.NonLocalReturnControl[_]) => Success(t.value.asInstanceOf[T])
- case Failure(t: scala.util.control.ControlThrowable) => Failure(new ExecutionException("Boxed ControlThrowable", t))
- case Failure(t: InterruptedException) => Failure(new ExecutionException("Boxed InterruptedException", t))
- case Failure(e: Error) => Failure(new ExecutionException("Boxed Error", e))
+ private[concurrent] def resolve[T](source: Either[Throwable, T]): Either[Throwable, T] = source match {
+ case Left(t: scala.runtime.NonLocalReturnControl[_]) => Right(t.value.asInstanceOf[T])
+ case Left(t: scala.util.control.ControlThrowable) => Left(new ExecutionException("Boxed ControlThrowable", t))
+ case Left(t: InterruptedException) => Left(new ExecutionException("Boxed InterruptedException", t))
+ case Left(e: Error) => Left(new ExecutionException("Boxed Error", e))
case _ => source
}
private[concurrent] def resolver[T] =
- resolverFunction.asInstanceOf[PartialFunction[Throwable, Try[T]]]
+ resolverFunction.asInstanceOf[PartialFunction[Throwable, Either[Throwable, T]]]
/* concurrency constructs */
- def future[T](body: =>T)(implicit execCtx: ExecutionContext = executionContext): Future[T] =
+ def future[T](body: =>T)(implicit execctx: ExecutionContext = executionContext): Future[T] =
Future[T](body)
- def promise[T]()(implicit execCtx: ExecutionContext = executionContext): Promise[T] =
+ def promise[T]()(implicit execctx: ExecutionContext = executionContext): Promise[T] =
Promise[T]()
/** Wraps a block of code into an awaitable object. */
@@ -82,8 +74,8 @@ abstract class ConcurrentPackageObject {
* - InterruptedException - in the case that a wait within the blockable object was interrupted
* - TimeoutException - in the case that the blockable object timed out
*/
- def blocking[T](body: =>T)(implicit execCtx: ExecutionContext): T =
- executionContext.blocking(body)
+ def blocking[T](body: =>T): T =
+ blocking(body2awaitable(body), Duration.fromNanos(0))
/** Blocks on an awaitable object.
*
@@ -94,8 +86,11 @@ abstract class ConcurrentPackageObject {
* - InterruptedException - in the case that a wait within the blockable object was interrupted
* - TimeoutException - in the case that the blockable object timed out
*/
- def blocking[T](awaitable: Awaitable[T], atMost: Duration)(implicit execCtx: ExecutionContext = executionContext): T =
- executionContext.blocking(awaitable, atMost)
+ def blocking[T](awaitable: Awaitable[T], atMost: Duration): T =
+ currentExecutionContext.get match {
+ case null => Await.result(awaitable, atMost)
+ case ec => ec.internalBlockingCall(awaitable, atMost)
+ }
@inline implicit final def int2durationops(x: Int): DurationOps = new DurationOps(x)
}
@@ -106,11 +101,11 @@ private[concurrent] object ConcurrentPackageObject {
// compiling a subset of sources; it seems that the wildcard is not
// properly handled, and you get messages like "type _$1 defined twice".
// This is consistent with other package object breakdowns.
- private val resolverFunction: PartialFunction[Throwable, Try[_]] = {
- case t: scala.runtime.NonLocalReturnControl[_] => Success(t.value)
- case t: scala.util.control.ControlThrowable => Failure(new ExecutionException("Boxed ControlThrowable", t))
- case t: InterruptedException => Failure(new ExecutionException("Boxed InterruptedException", t))
- case e: Error => Failure(new ExecutionException("Boxed Error", e))
- case t => Failure(t)
+ private val resolverFunction: PartialFunction[Throwable, Either[Throwable, _]] = {
+ case t: scala.runtime.NonLocalReturnControl[_] => Right(t.value)
+ case t: scala.util.control.ControlThrowable => Left(new ExecutionException("Boxed ControlThrowable", t))
+ case t: InterruptedException => Left(new ExecutionException("Boxed InterruptedException", t))
+ case e: Error => Left(new ExecutionException("Boxed Error", e))
+ case t => Left(t)
}
}
diff --git a/src/library/scala/concurrent/ExecutionContext.scala b/src/library/scala/concurrent/ExecutionContext.scala
index a206a2d4ea..16d9a1f980 100644
--- a/src/library/scala/concurrent/ExecutionContext.scala
+++ b/src/library/scala/concurrent/ExecutionContext.scala
@@ -13,7 +13,6 @@ package scala.concurrent
import java.util.concurrent.atomic.{ AtomicInteger }
import java.util.concurrent.{ Executors, Future => JFuture, Callable }
import scala.concurrent.util.Duration
-import scala.util.{ Try, Success, Failure }
import scala.concurrent.forkjoin.{ ForkJoinPool, RecursiveTask => FJTask, RecursiveAction, ForkJoinWorkerThread }
import scala.collection.generic.CanBuildFrom
import collection._
@@ -26,10 +25,8 @@ trait ExecutionContext {
def execute[U](body: () => U): Unit
- def blocking[T](body: =>T): T
-
- def blocking[T](awaitable: Awaitable[T], atMost: Duration): T
-
+ def internalBlockingCall[T](awaitable: Awaitable[T], atMost: Duration): T
+
def reportFailure(t: Throwable): Unit
/* implementations follow */
diff --git a/src/library/scala/concurrent/Future.scala b/src/library/scala/concurrent/Future.scala
index d73801aa90..5f703ac23b 100644
--- a/src/library/scala/concurrent/Future.scala
+++ b/src/library/scala/concurrent/Future.scala
@@ -17,7 +17,6 @@ import java.util.{ LinkedList => JLinkedList }
import java.{ lang => jl }
import java.util.concurrent.atomic.{ AtomicReferenceFieldUpdater, AtomicInteger, AtomicBoolean }
-import scala.util.{ Try, Success, Failure }
import scala.concurrent.util.Duration
import scala.Option
@@ -97,8 +96,8 @@ self =>
* $multipleCallbacks
*/
def onSuccess[U](pf: PartialFunction[T, U]): this.type = onComplete {
- case Failure(t) => // do nothing
- case Success(v) => if (pf isDefinedAt v) pf(v) else { /*do nothing*/ }
+ case Left(t) => // do nothing
+ case Right(v) => if (pf isDefinedAt v) pf(v) else { /*do nothing*/ }
}
/** When this future is completed with a failure (i.e. with a throwable),
@@ -114,8 +113,8 @@ self =>
* $multipleCallbacks
*/
def onFailure[U](callback: PartialFunction[Throwable, U]): this.type = onComplete {
- case Failure(t) => if (isFutureThrowable(t) && callback.isDefinedAt(t)) callback(t) else { /*do nothing*/ }
- case Success(v) => // do nothing
+ case Left(t) => if (isFutureThrowable(t) && callback.isDefinedAt(t)) callback(t) else { /*do nothing*/ }
+ case Right(v) => // do nothing
}
/** When this future is completed, either through an exception, a timeout, or a value,
@@ -126,7 +125,7 @@ self =>
*
* $multipleCallbacks
*/
- def onComplete[U](func: Try[T] => U): this.type
+ def onComplete[U](func: Either[Throwable, T] => U): this.type
/* Miscellaneous */
@@ -151,7 +150,7 @@ self =>
* if it contains a valid result, or `Some(Failure(error))` if it contains
* an exception.
*/
- def value: Option[Try[T]]
+ def value: Option[Either[Throwable, T]]
/* Projections */
@@ -175,8 +174,8 @@ self =>
val p = newPromise[Throwable]
onComplete {
- case Failure(t) => p success t
- case Success(v) => p failure noSuchElem(v)
+ case Left(t) => p success t
+ case Right(v) => p failure noSuchElem(v)
}
p.future
@@ -190,8 +189,8 @@ self =>
* Will not be called if the future fails.
*/
def foreach[U](f: T => U): Unit = onComplete {
- case Success(r) => f(r)
- case Failure(_) => // do nothing
+ case Right(r) => f(r)
+ case Left(_) => // do nothing
}
/** Creates a new future by applying a function to the successful result of
@@ -204,8 +203,8 @@ self =>
val p = newPromise[S]
onComplete {
- case Failure(t) => p failure t
- case Success(v) =>
+ case Left(t) => p failure t
+ case Right(v) =>
try p success f(v)
catch {
case t => p complete resolver(t)
@@ -226,12 +225,12 @@ self =>
val p = newPromise[S]
onComplete {
- case Failure(t) => p failure t
- case Success(v) =>
+ case Left(t) => p failure t
+ case Right(v) =>
try {
f(v) onComplete {
- case Failure(t) => p failure t
- case Success(v) => p success v
+ case Left(t) => p failure t
+ case Right(v) => p success v
}
} catch {
case t: Throwable => p complete resolver(t)
@@ -261,8 +260,8 @@ self =>
val p = newPromise[T]
onComplete {
- case Failure(t) => p failure t
- case Success(v) =>
+ case Left(t) => p failure t
+ case Right(v) =>
try {
if (pred(v)) p success v
else p failure new NoSuchElementException("Future.filter predicate is not satisfied by: " + v)
@@ -274,6 +273,18 @@ self =>
p.future
}
+ /** Used by for-comprehensions.
+ */
+ final def withFilter(p: T => Boolean): Future[T] = filter(p)
+ // final def withFilter(p: T => Boolean) = new FutureWithFilter[T](this, p)
+
+ // final class FutureWithFilter[+S](self: Future[S], p: S => Boolean) {
+ // def foreach(f: S => Unit): Unit = self filter p foreach f
+ // def map[R](f: S => R) = self filter p map f
+ // def flatMap[R](f: S => Future[R]) = self filter p flatMap f
+ // def withFilter(q: S => Boolean): FutureWithFilter[S] = new FutureWithFilter[S](self, x => p(x) && q(x))
+ // }
+
/** Creates a new future by mapping the value of the current future if the given partial function is defined at that value.
*
* If the current future contains a value for which the partial function is defined, the new future will also hold that value.
@@ -298,8 +309,8 @@ self =>
val p = newPromise[S]
onComplete {
- case Failure(t) => p failure t
- case Success(v) =>
+ case Left(t) => p failure t
+ case Right(v) =>
try {
if (pf.isDefinedAt(v)) p success pf(v)
else p failure new NoSuchElementException("Future.collect partial function is not defined at: " + v)
@@ -327,7 +338,7 @@ self =>
val p = newPromise[U]
onComplete {
- case Failure(t) if pf isDefinedAt t =>
+ case Left(t) if pf isDefinedAt t =>
try { p success pf(t) }
catch { case t: Throwable => p complete resolver(t) }
case otherwise => p complete otherwise
@@ -353,7 +364,7 @@ self =>
val p = newPromise[U]
onComplete {
- case Failure(t) if pf isDefinedAt t =>
+ case Left(t) if pf isDefinedAt t =>
try {
p completeWith pf(t)
} catch {
@@ -377,8 +388,8 @@ self =>
val p = newPromise[(T, U)]
this onComplete {
- case Failure(t) => p failure t
- case Success(r) => that onSuccess {
+ case Left(t) => p failure t
+ case Right(r) => that onSuccess {
case r2 => p success ((r, r2))
}
}
@@ -408,16 +419,35 @@ self =>
val p = newPromise[U]
onComplete {
- case Failure(t) => that onComplete {
- case Failure(_) => p failure t
- case Success(v) => p success v
+ case Left(t) => that onComplete {
+ case Left(_) => p failure t
+ case Right(v) => p success v
}
- case Success(v) => p success v
+ case Right(v) => p success v
}
p.future
}
-
+
+ /** Creates a new `Future[S]` which is completed with this `Future`'s result if
+ * that conforms to `S`'s erased type or a `ClassCastException` otherwise.
+ */
+ def mapTo[S](implicit m: Manifest[S]): Future[S] = {
+ val p = newPromise[S]
+
+ onComplete {
+ case l: Left[Throwable, _] => p complete l.asInstanceOf[Either[Throwable, S]]
+ case Right(t) =>
+ p complete (try {
+ Right(impl.Future.boxedType(m.erasure).cast(t).asInstanceOf[S])
+ } catch {
+ case e: ClassCastException => Left(e)
+ })
+ }
+
+ p.future
+ }
+
/** Applies the side-effecting function to the result of this future, and returns
* a new future with the result of this future.
*
@@ -441,7 +471,7 @@ self =>
* }
* }}}
*/
- def andThen[U](pf: PartialFunction[Try[T], U]): Future[T] = {
+ def andThen[U](pf: PartialFunction[Either[Throwable, T], U]): Future[T] = {
val p = newPromise[T]
onComplete {
@@ -469,9 +499,9 @@ self =>
def either[U >: T](that: Future[U]): Future[U] = {
val p = self.newPromise[U]
- val completePromise: PartialFunction[Try[U], _] = {
- case Failure(t) => p tryFailure t
- case Success(v) => p trySuccess v
+ val completePromise: PartialFunction[Either[Throwable, U], _] = {
+ case Left(t) => p tryFailure t
+ case Right(v) => p trySuccess v
}
self onComplete completePromise
@@ -510,7 +540,7 @@ object Future {
def firstCompletedOf[T](futures: Traversable[Future[T]])(implicit executor: ExecutionContext): Future[T] = {
val p = Promise[T]()
- val completeFirst: Try[T] => Unit = p tryComplete _
+ val completeFirst: Either[Throwable, T] => Unit = p tryComplete _
futures.foreach(_ onComplete completeFirst)
p.future
@@ -523,14 +553,14 @@ object Future {
else {
val result = Promise[Option[T]]()
val ref = new AtomicInteger(futures.size)
- val search: Try[T] => Unit = v => try {
+ val search: Either[Throwable, T] => Unit = v => try {
v match {
- case Success(r) => if (predicate(r)) result tryComplete Success(Some(r))
+ case Right(r) => if (predicate(r)) result tryComplete Right(Some(r))
case _ =>
}
} finally {
if (ref.decrementAndGet == 0)
- result tryComplete Success(None)
+ result tryComplete Right(None)
}
futures.foreach(_ onComplete search)
diff --git a/src/library/scala/concurrent/Promise.scala b/src/library/scala/concurrent/Promise.scala
index 61e21606e6..8f2bce5d1a 100644
--- a/src/library/scala/concurrent/Promise.scala
+++ b/src/library/scala/concurrent/Promise.scala
@@ -8,11 +8,6 @@
package scala.concurrent
-import scala.util.{ Try, Success, Failure }
-
-
-
-
/** Promise is an object which can be completed with a value or failed
* with an exception.
*
@@ -40,7 +35,7 @@ trait Promise[T] {
*
* $promiseCompletion
*/
- def complete(result:Try[T]): this.type = if (tryComplete(result)) this else throwCompleted
+ def complete(result: Either[Throwable, T]): this.type = if (tryComplete(result)) this else throwCompleted
/** Tries to complete the promise with either a value or the exception.
*
@@ -48,7 +43,7 @@ trait Promise[T] {
*
* @return If the promise has already been completed returns `false`, or `true` otherwise.
*/
- def tryComplete(result: Try[T]): Boolean
+ def tryComplete(result: Either[Throwable, T]): Boolean
/** Completes this promise with the specified future, once that future is completed.
*
@@ -75,7 +70,7 @@ trait Promise[T] {
*
* @return If the promise has already been completed returns `false`, or `true` otherwise.
*/
- def trySuccess(value: T): Boolean = tryComplete(Success(value))
+ def trySuccess(value: T): Boolean = tryComplete(Right(value))
/** Completes the promise with an exception.
*
@@ -93,7 +88,7 @@ trait Promise[T] {
*
* @return If the promise has already been completed returns `false`, or `true` otherwise.
*/
- def tryFailure(t: Throwable): Boolean = tryComplete(Failure(t))
+ def tryFailure(t: Throwable): Boolean = tryComplete(Left(t))
/** Wraps a `Throwable` in an `ExecutionException` if necessary. TODO replace with `resolver` from scala.concurrent
*
@@ -118,11 +113,11 @@ object Promise {
/** Creates an already completed Promise with the specified exception
*/
- def failed[T](exception: Throwable)(implicit executor: ExecutionContext): Promise[T] = new impl.Promise.KeptPromise[T](Failure(exception))
+ def failed[T](exception: Throwable)(implicit executor: ExecutionContext): Promise[T] = new impl.Promise.KeptPromise[T](Left(exception))
/** Creates an already completed Promise with the specified result
*/
- def successful[T](result: T)(implicit executor: ExecutionContext): Promise[T] = new impl.Promise.KeptPromise[T](Success(result))
+ def successful[T](result: T)(implicit executor: ExecutionContext): Promise[T] = new impl.Promise.KeptPromise[T](Right(result))
}
diff --git a/src/library/scala/concurrent/impl/ExecutionContextImpl.scala b/src/library/scala/concurrent/impl/ExecutionContextImpl.scala
index 5dc440f42b..9a94bfca4f 100644
--- a/src/library/scala/concurrent/impl/ExecutionContextImpl.scala
+++ b/src/library/scala/concurrent/impl/ExecutionContextImpl.scala
@@ -10,16 +10,49 @@ package scala.concurrent.impl
-import java.util.concurrent.{Callable, ExecutorService}
+import java.util.concurrent.{Callable, ExecutorService, Executors, ThreadFactory}
import scala.concurrent.forkjoin._
import scala.concurrent.{ExecutionContext, resolver, Awaitable, body2awaitable}
-import scala.util.{ Try, Success, Failure }
import scala.concurrent.util.{ Duration }
-private[scala] class ExecutionContextImpl(val executorService: AnyRef) extends ExecutionContext {
+private[scala] class ExecutionContextImpl() extends ExecutionContext {
import ExecutionContextImpl._
+
+ val executorService: AnyRef = getExecutorService
+
+ // to ensure that the current execution context thread local is properly set
+ private def executorsThreadFactory = new ThreadFactory {
+ def newThread(r: Runnable) = new Thread(new Runnable {
+ override def run() {
+ currentExecutionContext.set(ExecutionContextImpl.this)
+ r.run()
+ }
+ })
+ }
+
+ // to ensure that the current execution context thread local is properly set
+ private def forkJoinPoolThreadFactory = new ForkJoinPool.ForkJoinWorkerThreadFactory {
+ def newThread(fjp: ForkJoinPool) = new ForkJoinWorkerThread(fjp) {
+ override def onStart() {
+ currentExecutionContext.set(ExecutionContextImpl.this)
+ }
+ }
+ }
+
+ private def getExecutorService: AnyRef =
+ if (scala.util.Properties.isJavaAtLeast("1.6")) {
+ val vendor = scala.util.Properties.javaVmVendor
+ if ((vendor contains "Oracle") || (vendor contains "Sun") || (vendor contains "Apple"))
+ new ForkJoinPool(
+ Runtime.getRuntime.availableProcessors(),
+ forkJoinPoolThreadFactory,
+ null,
+ false)
+ else
+ Executors.newCachedThreadPool(executorsThreadFactory)
+ } else Executors.newCachedThreadPool(executorsThreadFactory)
def execute(runnable: Runnable): Unit = executorService match {
case fj: ForkJoinPool =>
@@ -37,9 +70,7 @@ private[scala] class ExecutionContextImpl(val executorService: AnyRef) extends E
def run() = body()
})
- def blocking[T](body: =>T): T = blocking(body2awaitable(body), Duration.fromNanos(0))
-
- def blocking[T](awaitable: Awaitable[T], atMost: Duration): T = {
+ def internalBlockingCall[T](awaitable: Awaitable[T], atMost: Duration): T = {
Future.releaseStack(this)
awaitable.result(atMost)(scala.concurrent.Await.canAwaitEvidence)
diff --git a/src/library/scala/concurrent/impl/Future.scala b/src/library/scala/concurrent/impl/Future.scala
index 6833b2467f..615ab061a5 100644
--- a/src/library/scala/concurrent/impl/Future.scala
+++ b/src/library/scala/concurrent/impl/Future.scala
@@ -11,11 +11,8 @@ package scala.concurrent.impl
import scala.concurrent.{Awaitable, ExecutionContext}
-import scala.util.{ Try, Success, Failure }
import scala.collection.mutable.Stack
-
-
private[concurrent] trait Future[+T] extends scala.concurrent.Future[T] with Awaitable[T] {
implicit def executor: ExecutionContext
@@ -36,39 +33,9 @@ private[concurrent] trait Future[+T] extends scala.concurrent.Future[T] with Awa
* if it contains a valid result, or Some(Left(error)) if it contains
* an exception.
*/
- def value: Option[Try[T]]
-
- def onComplete[U](func: Try[T] => U): this.type
-
- /** Creates a new Future[A] which is completed with this Future's result if
- * that conforms to A's erased type or a ClassCastException otherwise.
- */
- final def mapTo[T](implicit m: Manifest[T]) = {
- val p = new Promise.DefaultPromise[T]
-
- onComplete {
- case f @ Failure(t) => p complete f.asInstanceOf[Try[T]]
- case Success(v) =>
- p complete (try {
- Success(Future.boxedType(m.erasure).cast(v).asInstanceOf[T])
- } catch {
- case e: ClassCastException => Failure(e)
- })
- }
+ def value: Option[Either[Throwable, T]]
- p.future
- }
-
- /** Used by for-comprehensions.
- */
- final def withFilter(p: T => Boolean) = new FutureWithFilter[T](this, p)
-
- final class FutureWithFilter[+A](self: Future[A], p: A => Boolean) {
- def foreach(f: A => Unit): Unit = self filter p foreach f
- def map[B](f: A => B) = self filter p map f
- def flatMap[B](f: A => Future[B]) = self filter p flatMap f
- def withFilter(q: A => Boolean): FutureWithFilter[A] = new FutureWithFilter[A](self, x ⇒ p(x) && q(x))
- }
+ def onComplete[U](func: Either[Throwable, T] => U): this.type
}
@@ -97,7 +64,7 @@ object Future {
def run = {
promise complete {
try {
- Success(body)
+ Right(body)
} catch {
case e => scala.concurrent.resolver(e)
}
diff --git a/src/library/scala/concurrent/impl/Promise.scala b/src/library/scala/concurrent/impl/Promise.scala
index c79b0d02cc..f7e073cb78 100644
--- a/src/library/scala/concurrent/impl/Promise.scala
+++ b/src/library/scala/concurrent/impl/Promise.scala
@@ -15,7 +15,6 @@ import java.util.concurrent.atomic.AtomicReferenceFieldUpdater
import scala.concurrent.{Awaitable, ExecutionContext, resolve, resolver, blocking, CanAwait, TimeoutException}
//import scala.util.continuations._
import scala.concurrent.util.Duration
-import scala.util.Try
import scala.util
import scala.annotation.tailrec
//import scala.concurrent.NonDeterministic
@@ -84,18 +83,18 @@ object Promise {
*
* [adriaan] it's unsound to make FState covariant (tryComplete won't type check)
*/
- sealed trait FState[T] { def value: Option[Try[T]] }
+ sealed trait FState[T] { def value: Option[Either[Throwable, T]] }
- case class Pending[T](listeners: List[Try[T] => Any] = Nil) extends FState[T] {
- def value: Option[Try[T]] = None
+ case class Pending[T](listeners: List[Either[Throwable, T] => Any] = Nil) extends FState[T] {
+ def value: Option[Either[Throwable, T]] = None
}
- case class Success[T](value: Option[util.Success[T]] = None) extends FState[T] {
- def result: T = value.get.get
+ case class Success[T](value: Option[Either[Throwable, T]] = None) extends FState[T] {
+ def result: T = value.get.right.get
}
- case class Failure[T](value: Option[util.Failure[T]] = None) extends FState[T] {
- def exception: Throwable = value.get.exception
+ case class Failure[T](value: Option[Either[Throwable, T]] = None) extends FState[T] {
+ def exception: Throwable = value.get.left.get
}
private val emptyPendingValue = Pending[Nothing](Nil)
@@ -127,7 +126,7 @@ object Promise {
value.isDefined
}
- executor.blocking(concurrent.body2awaitable(awaitUnsafe(dur2long(atMost))), atMost)
+ blocking(concurrent.body2awaitable(awaitUnsafe(dur2long(atMost))), atMost)
}
def ready(atMost: Duration)(implicit permit: CanAwait): this.type =
@@ -136,11 +135,11 @@ object Promise {
def result(atMost: Duration)(implicit permit: CanAwait): T =
ready(atMost).value.get match {
- case util.Failure(e) => throw e
- case util.Success(r) => r
+ case Left(e) => throw e
+ case Right(r) => r
}
- def value: Option[Try[T]] = getState.value
+ def value: Option[Either[Throwable, T]] = getState.value
@inline
private[this] final def updater = AbstractPromise.updater.asInstanceOf[AtomicReferenceFieldUpdater[AbstractPromise, FState[T]]]
@@ -151,16 +150,16 @@ object Promise {
@inline
protected final def getState: FState[T] = updater.get(this)
- def tryComplete(value: Try[T]): Boolean = {
- val callbacks: List[Try[T] => Any] = {
+ def tryComplete(value: Either[Throwable, T]): Boolean = {
+ val callbacks: List[Either[Throwable, T] => Any] = {
try {
@tailrec
- def tryComplete(v: Try[T]): List[Try[T] => Any] = {
+ def tryComplete(v: Either[Throwable, T]): List[Either[Throwable, T] => Any] = {
getState match {
case cur @ Pending(listeners) =>
val newState =
- if (v.isFailure) Failure(Some(v.asInstanceOf[util.Failure[T]]))
- else Success(Some(v.asInstanceOf[util.Success[T]]))
+ if (v.isLeft) Failure(Some(v.asInstanceOf[Left[Throwable, T]]))
+ else Success(Some(v.asInstanceOf[Right[Throwable, T]]))
if (updateState(cur, newState)) listeners
else tryComplete(v)
@@ -184,7 +183,7 @@ object Promise {
}
}
- def onComplete[U](func: Try[T] => U): this.type = {
+ def onComplete[U](func: Either[Throwable, T] => U): this.type = {
@tailrec // Returns whether the future has already been completed or not
def tryAddCallback(): Boolean = {
val cur = getState
@@ -206,7 +205,7 @@ object Promise {
this
}
- private final def notifyCompleted(func: Try[T] => Any, result: Try[T]) {
+ private final def notifyCompleted(func: Either[Throwable, T] => Any, result: Either[Throwable, T]) {
try {
func(result)
} catch {
@@ -219,12 +218,13 @@ object Promise {
*
* Useful in Future-composition when a value to contribute is already available.
*/
- final class KeptPromise[T](suppliedValue: Try[T])(implicit val executor: ExecutionContext) extends Promise[T] {
+ final class KeptPromise[T](suppliedValue: Either[Throwable, T])(implicit val executor: ExecutionContext) extends Promise[T] {
+
val value = Some(resolve(suppliedValue))
- def tryComplete(value: Try[T]): Boolean = false
+ def tryComplete(value: Either[Throwable, T]): Boolean = false
- def onComplete[U](func: Try[T] => U): this.type = {
+ def onComplete[U](func: Either[Throwable, T] => U): this.type = {
val completedAs = value.get
Future.dispatchFuture(executor, {
() => func(completedAs)
@@ -235,8 +235,8 @@ object Promise {
def ready(atMost: Duration)(implicit permit: CanAwait): this.type = this
def result(atMost: Duration)(implicit permit: CanAwait): T = value.get match {
- case util.Failure(e) => throw e
- case util.Success(r) => r
+ case Left(e) => throw e
+ case Right(r) => r
}
}
diff --git a/src/library/scala/math/BigDecimal.scala b/src/library/scala/math/BigDecimal.scala
index c1f45eccfb..cb42b76b51 100644
--- a/src/library/scala/math/BigDecimal.scala
+++ b/src/library/scala/math/BigDecimal.scala
@@ -183,7 +183,8 @@ extends ScalaNumber with ScalaNumericConversions with Serializable {
override def equals (that: Any): Boolean = that match {
case that: BigDecimal => this equals that
case that: BigInt => this.toBigIntExact exists (that equals _)
- case _: Float | _: Double => unifiedPrimitiveEquals(that)
+ case that: Double => isValidDouble && toDouble == that
+ case that: Float => isValidFloat && toFloat == that
case _ => isValidLong && unifiedPrimitiveEquals(that)
}
override def isValidByte = noArithmeticException(toByteExact)
@@ -191,6 +192,18 @@ extends ScalaNumber with ScalaNumericConversions with Serializable {
override def isValidChar = isValidInt && toIntExact >= Char.MinValue && toIntExact <= Char.MaxValue
override def isValidInt = noArithmeticException(toIntExact)
def isValidLong = noArithmeticException(toLongExact)
+ /** Returns `true` iff this can be represented exactly by [[scala.Float]]; otherwise returns `false`.
+ */
+ def isValidFloat = {
+ val f = toFloat
+ !f.isInfinity && bigDecimal.compareTo(new java.math.BigDecimal(f)) == 0
+ }
+ /** Returns `true` iff this can be represented exactly by [[scala.Double]]; otherwise returns `false`.
+ */
+ def isValidDouble = {
+ val d = toDouble
+ !d.isInfinity && bigDecimal.compareTo(new java.math.BigDecimal(d)) == 0
+ }
private def noArithmeticException(body: => Unit): Boolean = {
try { body ; true }
diff --git a/src/library/scala/math/BigInt.scala b/src/library/scala/math/BigInt.scala
index 8a53afaa62..dbec30b2fe 100644
--- a/src/library/scala/math/BigInt.scala
+++ b/src/library/scala/math/BigInt.scala
@@ -20,6 +20,7 @@ object BigInt {
private val minCached = -1024
private val maxCached = 1024
private val cache = new Array[BigInt](maxCached - minCached + 1)
+ private val minusOne = BigInteger.valueOf(-1)
@deprecated("Use Long.MinValue", "2.9.0")
val MinLong = BigInt(Long.MinValue)
@@ -122,6 +123,8 @@ class BigInt(val bigInteger: BigInteger) extends ScalaNumber with ScalaNumericCo
override def equals(that: Any): Boolean = that match {
case that: BigInt => this equals that
case that: BigDecimal => that.toBigIntExact exists (this equals _)
+ case that: Double => isValidDouble && toDouble == that
+ case that: Float => isValidFloat && toFloat == that
case x => isValidLong && unifiedPrimitiveEquals(x)
}
override def isValidByte = this >= Byte.MinValue && this <= Byte.MaxValue
@@ -129,6 +132,41 @@ class BigInt(val bigInteger: BigInteger) extends ScalaNumber with ScalaNumericCo
override def isValidChar = this >= Char.MinValue && this <= Char.MaxValue
override def isValidInt = this >= Int.MinValue && this <= Int.MaxValue
def isValidLong = this >= Long.MinValue && this <= Long.MaxValue
+ /** Returns `true` iff this can be represented exactly by [[scala.Float]]; otherwise returns `false`.
+ */
+ def isValidFloat = {
+ val bitLen = bitLength
+ (bitLen <= 24 ||
+ {
+ val lowest = lowestSetBit
+ bitLen <= java.lang.Float.MAX_EXPONENT + 1 && // exclude this < -2^128 && this >= 2^128
+ lowest >= bitLen - 24 &&
+ lowest < java.lang.Float.MAX_EXPONENT + 1 // exclude this == -2^128
+ }
+ ) && !bitLengthOverflow
+ }
+ /** Returns `true` iff this can be represented exactly by [[scala.Double]]; otherwise returns `false`.
+ */
+ def isValidDouble = {
+ val bitLen = bitLength
+ (bitLen <= 53 ||
+ {
+ val lowest = lowestSetBit
+ bitLen <= java.lang.Double.MAX_EXPONENT + 1 && // exclude this < -2^1024 && this >= 2^1024
+ lowest >= bitLen - 53 &&
+ lowest < java.lang.Double.MAX_EXPONENT + 1 // exclude this == -2^1024
+ }
+ ) && !bitLengthOverflow
+ }
+ /** Some implementations of java.math.BigInteger allow huge values with bit length greater than Int.MaxValue .
+ * The BigInteger.bitLength method returns truncated bit length in this case .
+ * This method tests if result of bitLength is valid.
+ * This method will become unnecessary if BigInt constructors reject huge BigIntegers.
+ */
+ private def bitLengthOverflow = {
+ val shifted = bigInteger.shiftRight(Int.MaxValue)
+ (shifted.signum != 0) && !(shifted equals BigInt.minusOne)
+ }
protected[math] def isWhole = true
def underlying = bigInteger
diff --git a/src/library/scala/util/Try.scala b/src/library/scala/util/Try.scala
index c9bde81317..efa2fcabb8 100644
--- a/src/library/scala/util/Try.scala
+++ b/src/library/scala/util/Try.scala
@@ -101,9 +101,9 @@ sealed abstract class Try[+T] {
}
-final case class Failure[+T](val exception: Throwable) extends Try[T] {
- def isFailure = true
- def isSuccess = false
+final class Failure[+T](val exception: Throwable) extends Try[T] {
+ def isFailure: Boolean = true
+ def isSuccess: Boolean = false
def rescue[U >: T](rescueException: PartialFunction[Throwable, Try[U]]): Try[U] = {
try {
if (rescueException.isDefinedAt(exception)) rescueException(exception) else this
@@ -129,30 +129,49 @@ final case class Failure[+T](val exception: Throwable) extends Try[T] {
}
-final case class Success[+T](r: T) extends Try[T] {
- def isFailure = false
- def isSuccess = true
- def rescue[U >: T](rescueException: PartialFunction[Throwable, Try[U]]): Try[U] = Success(r)
- def get = r
+final class Success[+T](value: T) extends Try[T] {
+ def isFailure: Boolean = false
+ def isSuccess: Boolean = true
+ def rescue[U >: T](rescueException: PartialFunction[Throwable, Try[U]]): Try[U] = Success(value)
+ def get = value
def flatMap[U](f: T => Try[U]): Try[U] =
- try f(r)
+ try f(value)
catch {
case e => Failure(e)
}
- def flatten[U](implicit ev: T <:< Try[U]): Try[U] = r
- def foreach[U](f: T => U): Unit = f(r)
- def map[U](f: T => U): Try[U] = Try[U](f(r))
+ def flatten[U](implicit ev: T <:< Try[U]): Try[U] = value
+ def foreach[U](f: T => U): Unit = f(value)
+ def map[U](f: T => U): Try[U] = Try[U](f(value))
def collect[U](pf: PartialFunction[T, U]): Try[U] =
- if (pf isDefinedAt r) Success(pf(r))
- else Failure[U](new NoSuchElementException("Partial function not defined at " + r))
+ if (pf isDefinedAt value) Success(pf(value))
+ else Failure[U](new NoSuchElementException("Partial function not defined at " + value))
def filter(p: T => Boolean): Try[T] =
- if (p(r)) this
- else Failure(new NoSuchElementException("Predicate does not hold for " + r))
+ if (p(value)) this
+ else Failure(new NoSuchElementException("Predicate does not hold for " + value))
def recover[U >: T](rescueException: PartialFunction[Throwable, U]): Try[U] = this
- def exists(p: T => Boolean): Boolean = p(r)
+ def exists(p: T => Boolean): Boolean = p(value)
def failed: Try[Throwable] = Failure(new UnsupportedOperationException("Success.failed"))
}
+object Failure {
+ def apply[T](e: Throwable): Failure[T] = new Failure(e)
+ def unapply(scrutinizee: Any): Option[Throwable] = scrutinizee match {
+ case Right(_) => None
+ case Left(e) => Some(e.asInstanceOf[Throwable])
+ case s: Success[_] => None
+ case f: Failure[_] => Some(f.exception)
+ }
+}
+
+object Success {
+ def apply[T](value: T): Success[T] = new Success(value)
+ def unapply[T](scrutinizee: Any): Option[T] = scrutinizee match {
+ case Right(v) => Some(v.asInstanceOf[T])
+ case Left(_) => None
+ case s: Success[_] => Some(s.get.asInstanceOf[T])
+ case f: Failure[Throwable] => None
+ }
+}
object Try {
diff --git a/test/files/continuations-neg/infer0.check b/test/disabled/continuations-neg/infer0.check
index 1dd072ef09..1dd072ef09 100644
--- a/test/files/continuations-neg/infer0.check
+++ b/test/disabled/continuations-neg/infer0.check
diff --git a/test/files/continuations-neg/infer0.scala b/test/disabled/continuations-neg/infer0.scala
index 9cf69c5d35..6d97d7504d 100644
--- a/test/files/continuations-neg/infer0.scala
+++ b/test/disabled/continuations-neg/infer0.scala
@@ -4,11 +4,9 @@ import scala.util.continuations._
object Test {
-
def test(x: => Int @cpsParam[String,Int]) = 7
-
- def main(args: Array[String]): Any = {
+
+ def main(args: Array[String]) {
test(8)
}
-
-} \ No newline at end of file
+}
diff --git a/test/files/continuations-run/shift-pct.check b/test/files/continuations-run/shift-pct.check
new file mode 100644
index 0000000000..fb190e770a
--- /dev/null
+++ b/test/files/continuations-run/shift-pct.check
@@ -0,0 +1,25 @@
+d = 1, d2 = 1.0, pct = 1.000
+d = 2, d2 = 4.0, pct = 0.500
+d = 3, d2 = 9.0, pct = 0.333
+d = 4, d2 = 16.0, pct = 0.250
+d = 5, d2 = 25.0, pct = 0.200
+d = 6, d2 = 36.0, pct = 0.167
+d = 7, d2 = 49.0, pct = 0.143
+d = 8, d2 = 64.0, pct = 0.125
+d = 9, d2 = 81.0, pct = 0.111
+d = 10, d2 = 100.0, pct = 0.100
+d = 11, d2 = 121.0, pct = 0.091
+d = 12, d2 = 144.0, pct = 0.083
+d = 13, d2 = 169.0, pct = 0.077
+d = 14, d2 = 196.0, pct = 0.071
+d = 15, d2 = 225.0, pct = 0.067
+d = 16, d2 = 256.0, pct = 0.063
+d = 17, d2 = 289.0, pct = 0.059
+d = 18, d2 = 324.0, pct = 0.056
+d = 19, d2 = 361.0, pct = 0.053
+d = 20, d2 = 400.0, pct = 0.050
+d = 21, d2 = 441.0, pct = 0.048
+d = 22, d2 = 484.0, pct = 0.045
+d = 23, d2 = 529.0, pct = 0.043
+d = 24, d2 = 576.0, pct = 0.042
+d = 25, d2 = 625.0, pct = 0.040
diff --git a/test/files/continuations-run/shift-pct.scala b/test/files/continuations-run/shift-pct.scala
new file mode 100644
index 0000000000..7ef9922168
--- /dev/null
+++ b/test/files/continuations-run/shift-pct.scala
@@ -0,0 +1,30 @@
+import scala.util.continuations._
+
+object Test {
+ abstract class IfReturnRepro {
+ def s1: Double @cpsParam[Any, Unit]
+ def s2: Double @cpsParam[Any, Unit]
+
+ def p(i: Int): Double @cpsParam[Unit, Any] = {
+ val px = s1
+ val pct = if (px > 100) px else px / s2
+ println("pct = %.3f".format(pct))
+ pct
+ }
+ }
+
+ def main(args: Array[String]) : Unit = {
+ var d: Double = 0d
+ def d2 = d * d
+
+ val irr = new IfReturnRepro {
+ def s1 = shift(f => f(d))
+ def s2 = shift(f => f(d2))
+ }
+ 1 to 25 foreach { i =>
+ d = i
+ print("d = " + i + ", d2 = " + d2 + ", ")
+ run(irr p i)
+ }
+ }
+}
diff --git a/test/files/continuations-run/z1673.check b/test/files/continuations-run/z1673.check
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/test/files/continuations-run/z1673.check
diff --git a/test/files/continuations-run/z1673.scala b/test/files/continuations-run/z1673.scala
new file mode 100644
index 0000000000..716b374860
--- /dev/null
+++ b/test/files/continuations-run/z1673.scala
@@ -0,0 +1,31 @@
+import scala.util.continuations._
+
+class MatchRepro {
+ def s: String @cps[Any] = shift { k => k("foo") }
+
+ def p = {
+ val k = s
+ s match { case lit0 => }
+ }
+
+ def q = {
+ val k = s
+ k match { case lit1 => }
+ }
+
+ def r = {
+ s match { case "FOO" => }
+ }
+
+ def t = {
+ val k = s
+ k match { case "FOO" => }
+ }
+}
+
+object Test {
+ def main(args: Array[String]): Unit = {
+ val m = new MatchRepro
+ ()
+ }
+}
diff --git a/test/files/jvm/scala-concurrent-tck.scala b/test/files/jvm/scala-concurrent-tck.scala
index 75e2b92ff6..b3470d275d 100644
--- a/test/files/jvm/scala-concurrent-tck.scala
+++ b/test/files/jvm/scala-concurrent-tck.scala
@@ -1,6 +1,3 @@
-
-
-
import scala.concurrent.{
Future,
Promise,
@@ -398,6 +395,80 @@ trait Exceptions extends TestBase {
}
+trait TryEitherExtractor extends TestBase {
+
+ import scala.util.{Try, Success, Failure}
+
+ def testSuccessMatch(): Unit = once {
+ done =>
+ val thisIsASuccess = Success(42)
+ thisIsASuccess match {
+ case Success(v) =>
+ done()
+ assert(v == 42)
+ case Failure(e) =>
+ done()
+ assert(false)
+ case other =>
+ done()
+ assert(false)
+ }
+ }
+
+ def testRightMatch(): Unit = once {
+ done =>
+ val thisIsNotASuccess: Right[Throwable, Int] = Right(43)
+ thisIsNotASuccess match {
+ case Success(v) =>
+ done()
+ assert(v == 43)
+ case Failure(e) =>
+ done()
+ assert(false)
+ case other =>
+ done()
+ assert(false)
+ }
+ }
+
+ def testFailureMatch(): Unit = once {
+ done =>
+ val thisIsAFailure = Failure(new Exception("I'm an exception"))
+ thisIsAFailure match {
+ case Success(v) =>
+ done()
+ assert(false)
+ case Failure(e) =>
+ done()
+ assert(e.getMessage == "I'm an exception")
+ case other =>
+ done()
+ assert(false)
+ }
+ }
+
+ def testLeftMatch(): Unit = once {
+ done =>
+ val thisIsNotAFailure: Left[Throwable, Int] = Left(new Exception("I'm an exception"))
+ thisIsNotAFailure match {
+ case Success(v) =>
+ done()
+ assert(false)
+ case Failure(e) =>
+ done()
+ assert(e.getMessage == "I'm an exception")
+ case other =>
+ done()
+ assert(false)
+ }
+
+ }
+
+ testSuccessMatch()
+ testRightMatch()
+ testFailureMatch()
+ testLeftMatch()
+}
object Test
extends App
@@ -406,8 +477,11 @@ with FutureCombinators
with FutureProjections
with Promises
with Exceptions
+with TryEitherExtractor
{
System.exit(0)
}
+
+
diff --git a/test/files/neg/variances.check b/test/files/neg/variances.check
index dc72b05e1e..0643e533b7 100644
--- a/test/files/neg/variances.check
+++ b/test/files/neg/variances.check
@@ -1,16 +1,19 @@
variances.scala:4: error: covariant type A occurs in contravariant position in type test.Vector[A] of value x
- def append(x: Vector[A]): Vector[A]
+ def append(x: Vector[A]): Vector[A]
^
-variances.scala:14: error: covariant type A occurs in contravariant position in type A of value a
- private[this] def setA(a : A) = this.a = a
- ^
-variances.scala:16: error: covariant type A occurs in invariant position in supertype test.C[A] of object Baz
+variances.scala:18: error: covariant type A occurs in contravariant position in type A of value a
+ private def setA3(a : A) = this.a = a
+ ^
+variances.scala:19: error: covariant type A occurs in contravariant position in type A of value a
+ protected def setA4(a : A) = this.a = a
+ ^
+variances.scala:21: error: covariant type A occurs in invariant position in supertype test.C[A] of object Baz
object Baz extends C[A]
^
-variances.scala:63: error: covariant type A occurs in contravariant position in type => test.Covariant.T[A]{val m: A => A} of value x
+variances.scala:74: error: covariant type A occurs in contravariant position in type => test.Covariant.T[A]{val m: A => A} of value x
val x: T[A] {
^
-variances.scala:79: error: covariant type T occurs in contravariant position in type => test.TestAlias.B[C.this.A] of method foo
+variances.scala:90: error: covariant type T occurs in contravariant position in type => test.TestAlias.B[C.this.A] of method foo
def foo: B[A]
^
-5 errors found
+6 errors found
diff --git a/test/files/neg/variances.scala b/test/files/neg/variances.scala
index 726bc35270..10ca111cd0 100644
--- a/test/files/neg/variances.scala
+++ b/test/files/neg/variances.scala
@@ -1,7 +1,7 @@
package test
trait Vector[+A] {
- def append(x: Vector[A]): Vector[A]
+ def append(x: Vector[A]): Vector[A]
private[this] def append3(x: Vector[A]): Vector[A] = append(x)
}
@@ -11,19 +11,27 @@ object Covariant {
class Foo[+A] {
private[this] var a : A = _
def getA : A = a
- private[this] def setA(a : A) = this.a = a
-
+ // allowed
+ private[this] def setA1(a : A) = this.a = a
+ protected[this] def setA2(a : A) = this.a = a
+ // forbidden
+ private def setA3(a : A) = this.a = a
+ protected def setA4(a : A) = this.a = a
+
object Baz extends C[A]
trait Convert[B] {
def b2a(b : B) : A
- def doit(b : B) = setA(b2a(b))
+ def doit1(b : B) = setA1(b2a(b))
+ def doit2(b : B) = setA2(b2a(b))
+ def doit3(b : B) = setA3(b2a(b))
+ def doit4(b : B) = setA4(b2a(b))
}
}
class Foo2[+A] {
private[this] var a : A = _
def getA : A = a
- private[this] def setA(a : A) = this.a = a
-
+ private[this] def setA(a : A) = this.a = a
+
{
trait Convert[B] {
def b2a(b : B) : A
@@ -35,8 +43,8 @@ object Covariant {
class Foo3[+A] {
private[this] var a : A = _
def getA : A = a
- private[this] def setA(a : A) = this.a = a
-
+ private[this] def setA(a : A) = this.a = a
+
private[this] trait Convert[B] {
def b2a(b : B) : A
def doit(b : B) = setA(b2a(b))
@@ -54,7 +62,10 @@ object Covariant {
}
def main(args : Array[String]) {
val test = new Test
- test.c.doit(test.b)
+ test.c.doit1(test.b)
+ test.c.doit2(test.b)
+ test.c.doit3(test.b)
+ test.c.doit4(test.b)
val x : java.lang.Character = test.a.getA
Console.println("XXX " + x)
}
diff --git a/test/files/pos/t3272.scala b/test/files/pos/t3272.scala
new file mode 100644
index 0000000000..8efd5ded2c
--- /dev/null
+++ b/test/files/pos/t3272.scala
@@ -0,0 +1,8 @@
+trait A {
+ trait C[+T] {
+ protected[this] def f(t: T) {}
+ }
+ trait D[T] extends C[T] {
+ def g(t: T) { f(t) }
+ }
+}
diff --git a/test/files/pos/t4910.scala b/test/files/pos/t4910.scala
new file mode 100644
index 0000000000..c66fd523f5
--- /dev/null
+++ b/test/files/pos/t4910.scala
@@ -0,0 +1,6 @@
+class A {
+ implicit object foo
+ // it compiles if we uncomment this
+ // implicit val bar = foo
+ implicitly[foo.type]
+}
diff --git a/test/files/presentation/memory-leaks.check b/test/files/presentation/memory-leaks.check
new file mode 100644
index 0000000000..9d8cbb4da4
--- /dev/null
+++ b/test/files/presentation/memory-leaks.check
@@ -0,0 +1,14 @@
+reload: Trees.scala, Typers.scala, Types.scala
+reload: Trees.scala
+reload: Types.scala
+reload: Typers.scala
+reload: Typers.scala
+reload: Typers.scala
+reload: Typers.scala
+reload: Typers.scala
+reload: Typers.scala
+reload: Typers.scala
+reload: Typers.scala
+reload: Typers.scala
+reload: Typers.scala
+No leaks detected.
diff --git a/test/files/presentation/memory-leaks/MemoryLeaksTest.scala b/test/files/presentation/memory-leaks/MemoryLeaksTest.scala
new file mode 100644
index 0000000000..e24f36d7b6
--- /dev/null
+++ b/test/files/presentation/memory-leaks/MemoryLeaksTest.scala
@@ -0,0 +1,125 @@
+import java.io.PrintWriter
+import java.io.FileOutputStream
+import java.util.Calendar
+
+import scala.tools.nsc.interactive.tests._
+import scala.tools.nsc.util._
+import scala.tools.nsc.io._
+
+/** This test runs the presentation compiler on the Scala compiler project itself and records memory consumption.
+ *
+ * The test scenario is to open Typers, Trees and Types, then repeatedly add and remove one character
+ * in Typers.scala. Each step causes the parser, namer, and type checker to run.
+ *
+ * At each step we record the memory usage after the GC has run. At the end of the test,
+ * simple linear regression is used to compute the straight line that best fits the
+ * curve, and if the slope is higher than 1 (meaning a leak of 1MB/run), we fail the test.
+ *
+ * The Scala compiler sources are assumed to be under 'basedir/src/compiler'.
+ *
+ * The individual data points are saved under 'usedMem-<date>.txt', under the test project
+ * directory. Use the cool graph-it.R (https://github.com/scala-ide/scala-ide/blob/master/org.scala-ide.sdt.core.tests/graph-it.R)
+ * script to see the memory curve for the given test run.
+ */
+object Test extends InteractiveTest {
+ final val mega = 1024 * 1024
+
+ override def main(args: Array[String]) {
+ memoryConsumptionTest()
+ compiler.askShutdown()
+ }
+
+ def batchSource(name: String) =
+ new BatchSourceFile(AbstractFile.getFile(name))
+
+ def memoryConsumptionTest() {
+ val N = 10
+ val filename = "usedmem-%tF.txt".format(Calendar.getInstance.getTime)
+
+ val typerUnit = AbstractFile.getFile(baseDir.parent.parent.parent.parent / "src/compiler/scala/tools/nsc/typechecker/Typers.scala")
+ val typesUnit = AbstractFile.getFile(baseDir.parent.parent.parent.parent / "src/compiler/scala/reflect/internal/Types.scala")
+ val treesUnit = AbstractFile.getFile(baseDir.parent.parent.parent.parent / "src/compiler/scala/reflect/internal/Trees.scala")
+
+ askReload(Seq(new BatchSourceFile(typerUnit), new BatchSourceFile(typesUnit), new BatchSourceFile(treesUnit)))
+ typeCheckWith(treesUnit, new String(treesUnit.toCharArray))
+ typeCheckWith(typesUnit, new String(typesUnit.toCharArray))
+
+ val originalTyper = new String(typerUnit.toCharArray)
+
+ val (prefix, postfix) = originalTyper.splitAt(originalTyper.indexOf("import global._"))
+ val changedTyper = prefix + " a\n " + postfix
+
+ val usedMem = for (i <- 1 to N) yield {
+ val src = if (i % 2 == 0) originalTyper else changedTyper
+
+ val usedMem = withGC {
+ typeCheckWith(typerUnit, src)
+ }
+
+// println("UsedMem:\t%d\t%d".format(i, usedMem / mega))
+ usedMem / mega // report size in MB
+ }
+
+ // println("=" * 80)
+
+ val outputFile = new PrintWriter(new FileOutputStream(filename))
+ outputFile.println("\tusedMem")
+ for ((dataPoint, i) <- usedMem.zipWithIndex) {
+ outputFile.println("%d\t%d".format(i, dataPoint))
+ }
+ outputFile.close()
+ // drop the first two measurements, since the compiler needs some memory when initializing
+ val (a, b) = linearModel((3L to N).toSeq, usedMem.drop(2))
+ //println("LinearModel: constant: %.4f\tslope:%.4f".format(a, b))
+
+ if (b > 1.0)
+ println("Rate of memory consumption is alarming! %.4f MB/run".format(b))
+ else
+ println("No leaks detected.")
+ }
+
+ private def typeCheckWith(file: AbstractFile, src: String) = {
+ val sourceFile = new BatchSourceFile(file, src.toCharArray)
+ askReload(Seq(sourceFile))
+ askLoadedTyped(sourceFile).get // block until it's here
+ }
+
+
+ /** Return the linear model of these values, (a, b). First value is the constant factor,
+ * second value is the slope, i.e. `y = a + bx`
+ *
+ * The linear model of a set of points is a straight line that minimizes the square distance
+ * between the each point and the line.
+ *
+ * See: http://en.wikipedia.org/wiki/Simple_linear_regression
+ */
+ def linearModel(xs: Seq[Long], ys: Seq[Long]): (Double, Double) = {
+ require(xs.length == ys.length)
+
+ def mean(v: Seq[Long]): Double = v.sum.toDouble / v.length
+
+ val meanXs = mean(xs)
+ val meanYs = mean(ys)
+
+ val beta = (mean((xs, ys).zipped.map(_ * _)) - meanXs * meanYs) / (mean(xs.map(x => x * x)) - meanXs * meanXs)
+ val alfa = meanYs - beta * meanXs
+
+ (alfa, beta)
+ }
+
+ /** Run the given closure and return the amount of used memory at the end of its execution.
+ *
+ * Runs the GC before and after the execution of `f'.
+ */
+ def withGC(f: => Unit): Long = {
+ val r = Runtime.getRuntime
+ System.gc()
+
+ f;
+
+ System.gc()
+
+ r.totalMemory() - r.freeMemory()
+ }
+
+} \ No newline at end of file
diff --git a/test/files/run/concurrent-map-conversions.scala b/test/files/run/concurrent-map-conversions.scala
new file mode 100644
index 0000000000..0350b69642
--- /dev/null
+++ b/test/files/run/concurrent-map-conversions.scala
@@ -0,0 +1,36 @@
+
+
+
+
+
+object Test {
+
+ def main(args: Array[String]) {
+ testConversions()
+ testConverters()
+ }
+
+ def needPackageConcurrentMap(map: collection.concurrent.Map[Int, Int]) {
+ }
+ def needJavaConcurrent(map: java.util.concurrent.ConcurrentMap[Int, Int]) {
+ }
+
+ def testConversions() {
+ import collection.JavaConversions._
+ val skiplist = new java.util.concurrent.ConcurrentSkipListMap[Int, Int]
+ val ctrie = new collection.concurrent.TrieMap[Int, Int]
+
+ needPackageConcurrentMap(skiplist)
+ needJavaConcurrent(ctrie)
+ }
+
+ def testConverters() {
+ import collection.JavaConverters._
+ val skiplist = new java.util.concurrent.ConcurrentSkipListMap[Int, Int]
+ val ctrie = new collection.concurrent.TrieMap[Int, Int]
+
+ needPackageConcurrentMap(skiplist.asScala)
+ needJavaConcurrent(ctrie.asJava)
+ }
+
+}
diff --git a/test/files/run/is-valid-num.scala b/test/files/run/is-valid-num.scala
index f919a21dee..9c43e98911 100644
--- a/test/files/run/is-valid-num.scala
+++ b/test/files/run/is-valid-num.scala
@@ -1,11 +1,15 @@
object Test {
def x = BigInt("10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000")
def y = BigDecimal("" + (Short.MaxValue + 1) + ".0")
+ def y1 = BigDecimal("0.1")
+ def y2 = BigDecimal("0.5")
def l1 = Int.MaxValue.toLong + 1
def l2 = Int.MinValue.toLong - 1
def main(args: Array[String]): Unit = {
+ assert(!x.isValidDouble, x)
+ assert(!x.isValidFloat, x)
assert(!x.isValidLong, x)
assert(!x.isValidInt, x)
assert(!x.isValidChar, x)
@@ -13,8 +17,81 @@ object Test {
assert(!y.isValidShort, y)
assert(y.isValidChar, y)
assert(y.isValidInt, y)
+ assert(y.isValidFloat, y)
+ assert(y.isValidDouble, y)
+ assert(!y1.isValidLong, y1)
+ assert(!y1.isValidFloat, y1)
+ assert(!y1.isValidDouble, y1)
+ assert(!y2.isValidLong, y2)
+ assert(y2.isValidFloat, y2)
+ assert(y2.isValidDouble, y2)
+
+ testBigIntIsFloat()
+ testBigIntIsDouble()
assert(!l1.isValidInt && (l1 - 1).isValidInt, l1)
assert(!l2.isValidInt && (l2 + 1).isValidInt, l2)
}
+
+ def biExp2(e: Int) = BigInt(1) << e
+
+ def testBigIntIsFloat() {
+ val prec = 24
+ def checkFloatT(x: BigInt) = {
+ assert(x.isValidFloat, x)
+ assert((-x).isValidFloat, -x)
+ }
+ def checkFloatF(x: BigInt) = {
+ assert(!x.isValidFloat, x)
+ assert(!(-x).isValidFloat, -x)
+ }
+ checkFloatT(biExp2(prec) - 1)
+ checkFloatT(biExp2(prec))
+ checkFloatF(biExp2(prec) + 1)
+ checkFloatT(biExp2(prec) + 2)
+ checkFloatT(biExp2(prec) - 2)
+ checkFloatF(biExp2(prec + 1) - 1)
+ checkFloatT(biExp2(prec + 1))
+ checkFloatF(biExp2(prec + 1) + 1)
+ checkFloatF(biExp2(prec + 1) + 2)
+ checkFloatF(biExp2(prec + 1) + 3)
+ checkFloatT(biExp2(prec + 1) + 4)
+ checkFloatT(biExp2(64))
+ checkFloatF(biExp2(64) + biExp2(64 - prec))
+ checkFloatT(biExp2(64) + biExp2(64 - prec + 1))
+ checkFloatT(biExp2(127))
+ checkFloatT(biExp2(128) - biExp2(128 - prec))
+ checkFloatF(biExp2(128) - biExp2(128 - prec - 1))
+ checkFloatF(biExp2(128))
+ }
+
+ def testBigIntIsDouble() {
+ val prec = 53
+ def checkDoubleT(x: BigInt) = {
+ assert(x.isValidDouble, x)
+ assert((-x).isValidDouble, -x)
+ }
+ def checkDoubleF(x: BigInt) = {
+ assert(!x.isValidDouble, x)
+ assert(!(-x).isValidDouble, -x)
+ }
+ checkDoubleT(biExp2(prec) - 1)
+ checkDoubleT(biExp2(prec))
+ checkDoubleF(biExp2(prec) + 1)
+ checkDoubleT(biExp2(prec) + 2)
+ checkDoubleT(biExp2(prec + 1) - 2)
+ checkDoubleF(biExp2(prec + 1) - 1)
+ checkDoubleT(biExp2(prec + 1))
+ checkDoubleF(biExp2(prec + 1) + 1)
+ checkDoubleF(biExp2(prec + 1) + 2)
+ checkDoubleF(biExp2(prec + 1) + 3)
+ checkDoubleT(biExp2(prec + 1) + 4)
+ checkDoubleT(biExp2(64))
+ checkDoubleF(biExp2(64) + biExp2(64 - prec))
+ checkDoubleT(biExp2(64) + biExp2(64 - prec + 1))
+ checkDoubleT(biExp2(1023))
+ checkDoubleT(biExp2(1024) - biExp2(1024 - prec))
+ checkDoubleF(biExp2(1024) - biExp2(1024 - prec - 1))
+ checkDoubleF(biExp2(1024))
+ }
}
diff --git a/test/files/run/numbereq.scala b/test/files/run/numbereq.scala
index 77a217df36..a1f11da205 100644
--- a/test/files/run/numbereq.scala
+++ b/test/files/run/numbereq.scala
@@ -16,7 +16,20 @@ object Test {
base ::: extras
}
-
+
+ def mkNumbers(x: BigInt): List[AnyRef] = {
+ List(
+ List(BigDecimal(x, java.math.MathContext.UNLIMITED)),
+ List(x),
+ if (x.isValidDouble) List(new java.lang.Double(x.toDouble)) else Nil,
+ if (x.isValidFloat) List(new java.lang.Float(x.toFloat)) else Nil,
+ if (x.isValidLong) List(new java.lang.Long(x.toLong)) else Nil,
+ if (x.isValidInt) List(new java.lang.Integer(x.toInt)) else Nil,
+ if (x.isValidShort) List(new java.lang.Short(x.toShort)) else Nil,
+ if (x.isValidByte) List(new java.lang.Byte(x.toByte)) else Nil,
+ if (x.isValidChar) List(new java.lang.Character(x.toChar)) else Nil
+ ).flatten
+ }
def main(args: Array[String]): Unit = {
val ints = (0 to 15).toList map (Short.MinValue >> _)
@@ -37,5 +50,23 @@ object Test {
assert(x == y, "%s/%s != %s/%s".format(x, x.getClass, y, y.getClass))
assert(x.## == y.##, "%s != %s".format(x.getClass, y.getClass))
}
+
+ val bigInts = (0 to 1024).toList map (BigInt(-1) << _)
+ val bigInts2 = bigInts map (x => -x)
+ val bigInts3 = bigInts map (_ + 1)
+ val bigInts4 = bigInts2 map (_ - 1)
+
+ val setneg1b = bigInts map mkNumbers
+ val setneg2b = bigInts3 map mkNumbers
+ val setpos1b = bigInts2 map mkNumbers
+ val setpos2b = bigInts4 map mkNumbers
+
+ val sets2 = setneg1 ++ setneg1b ++ setneg2 ++ setneg2b ++ List(zero) ++ setpos1 ++ setpos1b ++ setpos2 ++ setpos2b
+
+ for (set <- sets2 ; x <- set ; y <- set) {
+// println("'%s' == '%s' (%s == %s) (%s == %s)".format(x, y, x.hashCode, y.hashCode, x.##, y.##))
+ assert(x == y, "%s/%s != %s/%s".format(x, x.getClass, y, y.getClass))
+// assert(x.## == y.##, "%s != %s".format(x.getClass, y.getClass)) Disable until Double.## is fixed (SI-5640)
+ }
}
-} \ No newline at end of file
+}
diff --git a/test/files/run/option-fold.check b/test/files/run/option-fold.check
new file mode 100644
index 0000000000..4e3fe99f98
--- /dev/null
+++ b/test/files/run/option-fold.check
@@ -0,0 +1,5 @@
+List()
+List(5)
+-1
+0
+1
diff --git a/test/files/run/option-fold.scala b/test/files/run/option-fold.scala
new file mode 100644
index 0000000000..d554ba4f9b
--- /dev/null
+++ b/test/files/run/option-fold.scala
@@ -0,0 +1,19 @@
+object Test {
+ sealed class A
+ case object B extends A
+ case class C(x: Int) extends A
+
+ def f[T](x: Option[T]) = x.fold(List.empty[T])(List(_))
+ def g(x: Option[A]) = x.fold(-1) {
+ case B => 0
+ case C(x) => x
+ }
+
+ def main(args: Array[String]): Unit = {
+ println(f(None))
+ println(f(Some(5)))
+ println(g(None))
+ println(g(Some(B)))
+ println(g(Some(C(1))))
+ }
+}
diff --git a/test/files/run/reflect-overload.scala b/test/files/run/reflect-overload.scala
new file mode 100644
index 0000000000..af82a1948d
--- /dev/null
+++ b/test/files/run/reflect-overload.scala
@@ -0,0 +1,16 @@
+object Test extends App {
+ import reflect.mirror._
+
+ val s = "hello world"
+ val sc = symbolOfInstance(s)
+ val st = sc.asType
+ val m = st member newTermName("indexOf")
+ val IntType = definitions.IntClass.asType
+ val indexOf = m resolveOverloaded(actuals = List(IntType))
+ assert(invoke(s, indexOf)('w') == 6)
+ assert((invoke(s, indexOf)('w') match { case x: Int => x }) == 6)
+
+ val m2 = st member newTermName("substring")
+ val substring = m2 resolveOverloaded(actuals = List(IntType, IntType))
+ assert(invoke(s, substring)(2, 6) == "llo ")
+}