summaryrefslogtreecommitdiff
path: root/src
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 /src
parent7f79ef0e30f088b41b14763f44338c240acf1a63 (diff)
parent754b4a85e4093f25cc10f092fefdb34215097c94 (diff)
downloadscala-115f5467e3f3ff07abbba2b23c40c2ff0d7ddd1b.tar.gz
scala-115f5467e3f3ff07abbba2b23c40c2ff0d7ddd1b.tar.bz2
scala-115f5467e3f3ff07abbba2b23c40c2ff0d7ddd1b.zip
Merge branch 'master' into topic/reflect
Diffstat (limited to 'src')
-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
33 files changed, 657 insertions, 221 deletions
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 {