summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/compiler/scala/reflect/internal/Definitions.scala2
-rw-r--r--src/compiler/scala/reflect/internal/Types.scala82
-rw-r--r--src/compiler/scala/reflect/internal/settings/MutableSettings.scala1
-rw-r--r--src/compiler/scala/reflect/internal/util/Collections.scala6
-rw-r--r--src/compiler/scala/reflect/runtime/Settings.scala1
-rw-r--r--src/compiler/scala/tools/ant/templates/tool-unix.tmpl21
-rw-r--r--src/compiler/scala/tools/cmd/gen/AnyVals.scala33
-rw-r--r--src/compiler/scala/tools/nsc/Global.scala30
-rw-r--r--src/compiler/scala/tools/nsc/ast/parser/Parsers.scala113
-rw-r--r--src/compiler/scala/tools/nsc/backend/jvm/GenASM.scala17
-rw-r--r--src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala6
-rw-r--r--src/compiler/scala/tools/nsc/settings/ScalaSettings.scala1
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/PatternMatching.scala1173
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Typers.scala2
-rw-r--r--src/compiler/scala/tools/nsc/util/Statistics.scala29
-rw-r--r--src/forkjoin/scala/concurrent/forkjoin/ForkJoinPool.java19
-rw-r--r--src/forkjoin/scala/concurrent/forkjoin/ForkJoinTask.java19
-rw-r--r--src/forkjoin/scala/concurrent/forkjoin/LinkedTransferQueue.java19
-rw-r--r--src/library/scala/AnyVal.scala4
-rw-r--r--src/library/scala/Boolean.scala29
-rw-r--r--src/library/scala/Byte.scala229
-rw-r--r--src/library/scala/Char.scala229
-rw-r--r--src/library/scala/Double.scala182
-rw-r--r--src/library/scala/Float.scala185
-rw-r--r--src/library/scala/Int.scala229
-rw-r--r--src/library/scala/Long.scala229
-rw-r--r--src/library/scala/Short.scala229
-rw-r--r--src/library/scala/Unit.scala8
-rw-r--r--src/library/scala/collection/GenMapLike.scala2
-rw-r--r--src/library/scala/collection/GenSeqLike.scala2
-rw-r--r--src/library/scala/collection/GenSetLike.scala2
-rw-r--r--src/library/scala/collection/IndexedSeqLike.scala2
-rw-r--r--src/library/scala/collection/LinearSeqLike.scala2
-rw-r--r--src/library/scala/collection/concurrent/TrieMap.scala72
-rw-r--r--src/library/scala/collection/convert/Wrappers.scala5
-rw-r--r--src/library/scala/collection/immutable/HashMap.scala67
-rw-r--r--src/library/scala/collection/mutable/FlatHashTable.scala4
-rw-r--r--src/library/scala/collection/mutable/HashTable.scala7
-rw-r--r--src/library/scala/collection/mutable/UnrolledBuffer.scala2
-rw-r--r--src/library/scala/concurrent/impl/ExecutionContextImpl.scala28
-rw-r--r--src/library/scala/math/Equiv.scala2
-rw-r--r--src/library/scala/math/Ordered.scala11
-rw-r--r--src/library/scala/runtime/ScalaRunTime.scala2
-rw-r--r--src/library/scala/util/hashing/ByteswapHashing.scala35
-rw-r--r--src/library/scala/util/hashing/Hashing.scala42
-rw-r--r--src/library/scala/util/hashing/MurmurHash3.scala (renamed from src/library/scala/util/MurmurHash3.scala)78
-rw-r--r--src/library/scala/util/hashing/package.scala35
-rwxr-xr-xsrc/library/scala/xml/Utility.scala2
48 files changed, 2109 insertions, 1420 deletions
diff --git a/src/compiler/scala/reflect/internal/Definitions.scala b/src/compiler/scala/reflect/internal/Definitions.scala
index 0cdef9e79a..96819eab91 100644
--- a/src/compiler/scala/reflect/internal/Definitions.scala
+++ b/src/compiler/scala/reflect/internal/Definitions.scala
@@ -293,8 +293,6 @@ trait Definitions extends reflect.api.StandardDefinitions {
anyval
}).asInstanceOf[ClassSymbol]
- lazy val AnyVal_getClass = enterNewMethod(AnyValClass, nme.getClass_, Nil, getClassReturnType(AnyValClass.tpe))
-
// bottom types
lazy val RuntimeNothingClass = getClass(fulltpnme.RuntimeNothing)
lazy val RuntimeNullClass = getClass(fulltpnme.RuntimeNull)
diff --git a/src/compiler/scala/reflect/internal/Types.scala b/src/compiler/scala/reflect/internal/Types.scala
index 67c858356c..a839e44182 100644
--- a/src/compiler/scala/reflect/internal/Types.scala
+++ b/src/compiler/scala/reflect/internal/Types.scala
@@ -749,12 +749,18 @@ trait Types extends api.Types { self: SymbolTable =>
def substThis(from: Symbol, to: Symbol): Type =
substThis(from, to.thisType)
- /** Performs both substThis and substSym in one traversal.
+ /** Performs both substThis and substSym, in that order.
+ *
+ * [JZ] Reverted `SubstThisAndSymMap` from 334872, which was not the same as
+ * `substThis(from, to).substSym(symsFrom, symsTo)`.
+ *
+ * `SubstThisAndSymMap` performs a breadth-first map over this type, which meant that
+ * symbol substitution occured before `ThisType` substitution. Consequently, in substitution
+ * of a `SingleType(ThisType(`from`), sym), symbols were rebound to `from` rather than `to`.
*/
- def substThisAndSym(from: Symbol, to: Type, symsFrom: List[Symbol], symsTo: List[Symbol]): Type = {
+ def substThisAndSym(from: Symbol, to: Type, symsFrom: List[Symbol], symsTo: List[Symbol]): Type =
if (symsFrom eq symsTo) substThis(from, to)
- else new SubstThisAndSymMap(from, to, symsFrom, symsTo) apply this
- }
+ else substThis(from, to).substSym(symsFrom, symsTo)
/** Returns all parts of this type which satisfy predicate `p` */
def filter(p: Type => Boolean): List[Type] = new FilterTypeCollector(p) collect this
@@ -4518,13 +4524,6 @@ trait Types extends api.Types { self: SymbolTable =>
case _ => mapOver(tp)
}
}
- class SubstThisAndSymMap(fromThis: Symbol, toThis: Type, fromSyms: List[Symbol], toSyms: List[Symbol])
- extends SubstSymMap(fromSyms, toSyms) {
- override def apply(tp: Type): Type = tp match {
- case ThisType(sym) if sym == fromThis => apply(toThis)
- case _ => super.apply(tp)
- }
- }
class SubstWildcardMap(from: List[Symbol]) extends TypeMap {
def apply(tp: Type): Type = try {
@@ -6572,47 +6571,50 @@ trait Types extends api.Types { self: SymbolTable =>
else Some(typeRef(pre, sym, List(lub(args))))
}
}
- else {
- val args = map2(sym.typeParams, argss.transpose) { (tparam, as) =>
- if (depth == 0) {
- if (tparam.variance == variance) {
- // Take the intersection of the upper bounds of the type parameters
- // rather than falling all the way back to "Any", otherwise we end up not
- // conforming to bounds.
- val bounds0 = sym.typeParams map (_.info.bounds.hi) filterNot (_.typeSymbol == AnyClass)
- if (bounds0.isEmpty) AnyClass.tpe
- else intersectionType(bounds0 map (b => b.asSeenFrom(tps.head, sym)))
+ else transposeSafe(argss) match {
+ case None =>
+ // transpose freaked out because of irregular argss
+ // catching just in case (shouldn't happen, but also doesn't cost us)
+ // [JZ] It happens: see SI-5683.
+ debuglog("transposed irregular matrix!?" +(tps, argss))
+ None
+ case Some(argsst) =>
+ val args = map2(sym.typeParams, argsst) { (tparam, as) =>
+ if (depth == 0) {
+ if (tparam.variance == variance) {
+ // Take the intersection of the upper bounds of the type parameters
+ // rather than falling all the way back to "Any", otherwise we end up not
+ // conforming to bounds.
+ val bounds0 = sym.typeParams map (_.info.bounds.hi) filterNot (_.typeSymbol == AnyClass)
+ if (bounds0.isEmpty) AnyClass.tpe
+ else intersectionType(bounds0 map (b => b.asSeenFrom(tps.head, sym)))
+ }
+ else if (tparam.variance == -variance) NothingClass.tpe
+ else NoType
}
- else if (tparam.variance == -variance) NothingClass.tpe
- else NoType
- }
- else {
- if (tparam.variance == variance) lub(as, decr(depth))
- else if (tparam.variance == -variance) glb(as, decr(depth))
else {
- val l = lub(as, decr(depth))
- val g = glb(as, decr(depth))
- if (l <:< g) l
+ if (tparam.variance == variance) lub(as, decr(depth))
+ else if (tparam.variance == -variance) glb(as, decr(depth))
+ else {
+ val l = lub(as, decr(depth))
+ val g = glb(as, decr(depth))
+ if (l <:< g) l
else { // Martin: I removed this, because incomplete. Not sure there is a good way to fix it. For the moment we
// just err on the conservative side, i.e. with a bound that is too high.
// if(!(tparam.info.bounds contains tparam)) //@M can't deal with f-bounds, see #2251
- val qvar = commonOwner(as) freshExistential "" setInfo TypeBounds(g, l)
- capturedParams += qvar
- qvar.tpe
+ val qvar = commonOwner(as) freshExistential "" setInfo TypeBounds(g, l)
+ capturedParams += qvar
+ qvar.tpe
+ }
}
}
}
- }
- if (args contains NoType) None
- else Some(existentialAbstraction(capturedParams.toList, typeRef(pre, sym, args)))
+ if (args contains NoType) None
+ else Some(existentialAbstraction(capturedParams.toList, typeRef(pre, sym, args)))
}
} catch {
case ex: MalformedType => None
- case ex: IndexOutOfBoundsException => // transpose freaked out because of irregular argss
- // catching just in case (shouldn't happen, but also doesn't cost us)
- debuglog("transposed irregular matrix!?"+ (tps, argss))
- None
}
case SingleType(_, sym) :: rest =>
val pres = tps map (_.prefix)
diff --git a/src/compiler/scala/reflect/internal/settings/MutableSettings.scala b/src/compiler/scala/reflect/internal/settings/MutableSettings.scala
index 45ba4ed3e6..8640a23aa7 100644
--- a/src/compiler/scala/reflect/internal/settings/MutableSettings.scala
+++ b/src/compiler/scala/reflect/internal/settings/MutableSettings.scala
@@ -44,4 +44,5 @@ abstract class MutableSettings extends AbsSettings {
def maxClassfileName: IntSetting
def Xexperimental: BooleanSetting
def XoldPatmat: BooleanSetting
+ def XnoPatmatAnalysis: BooleanSetting
} \ No newline at end of file
diff --git a/src/compiler/scala/reflect/internal/util/Collections.scala b/src/compiler/scala/reflect/internal/util/Collections.scala
index 2e119f8ccc..1f8eb15c90 100644
--- a/src/compiler/scala/reflect/internal/util/Collections.scala
+++ b/src/compiler/scala/reflect/internal/util/Collections.scala
@@ -201,6 +201,12 @@ trait Collections {
}
true
}
+
+ final def transposeSafe[A](ass: List[List[A]]): Option[List[List[A]]] = try {
+ Some(ass.transpose)
+ } catch {
+ case _: IllegalArgumentException => None
+ }
}
object Collections extends Collections { }
diff --git a/src/compiler/scala/reflect/runtime/Settings.scala b/src/compiler/scala/reflect/runtime/Settings.scala
index bbe4d60e9c..b247797c6c 100644
--- a/src/compiler/scala/reflect/runtime/Settings.scala
+++ b/src/compiler/scala/reflect/runtime/Settings.scala
@@ -35,4 +35,5 @@ class Settings extends internal.settings.MutableSettings {
val Xexperimental = new BooleanSetting(false)
val deepCloning = new BooleanSetting (false)
val XoldPatmat = new BooleanSetting(false)
+ val XnoPatmatAnalysis = new BooleanSetting(false)
}
diff --git a/src/compiler/scala/tools/ant/templates/tool-unix.tmpl b/src/compiler/scala/tools/ant/templates/tool-unix.tmpl
index 85bb5f2056..256b5088e9 100644
--- a/src/compiler/scala/tools/ant/templates/tool-unix.tmpl
+++ b/src/compiler/scala/tools/ant/templates/tool-unix.tmpl
@@ -9,19 +9,14 @@
##############################################################################
findScalaHome () {
- # see SI-2092
- local SOURCE="${BASH_SOURCE[0]}"
- while [ -h "$SOURCE" ] ; do SOURCE="$(readlink "$SOURCE")"; done
- local bindir="$( dirname "$SOURCE" )"
- if [[ -d "$bindir"/.. ]]; then
- ( cd -P "$bindir"/.. && pwd )
- else
- # See SI-5792
- local dir=$(dirname "${BASH_SOURCE[0]}")
- local link=$(dirname "$(readlink "${BASH_SOURCE[0]}")")
- local path="$dir/$link/.."
- ( cd "$path" && pwd )
- fi
+ # see SI-2092 and SI-5792
+ local source="${BASH_SOURCE[0]}"
+ while [ -h "$source" ] ; do
+ local linked="$(readlink "$source")"
+ local dir="$( cd -P $(dirname "$source") && cd -P $(dirname "$linked") && pwd )"
+ source="$dir/$(basename "$linked")"
+ done
+ ( cd -P "$(dirname "$source")/.." && pwd )
}
execCommand () {
[[ -n $SCALA_RUNNER_DEBUG ]] && echo "" && for arg in "$@@"; do echo "$arg"; done && echo "";
diff --git a/src/compiler/scala/tools/cmd/gen/AnyVals.scala b/src/compiler/scala/tools/cmd/gen/AnyVals.scala
index 83cd9c2578..9d0795b2f6 100644
--- a/src/compiler/scala/tools/cmd/gen/AnyVals.scala
+++ b/src/compiler/scala/tools/cmd/gen/AnyVals.scala
@@ -177,7 +177,7 @@ trait AnyValReps {
case (res, lines) =>
val xs = lines map {
case "" => ""
- case s => interpolate(s) + " = " + stub
+ case s => interpolate(s)
}
res ++ xs
}
@@ -205,7 +205,7 @@ trait AnyValReps {
def classLines: List[String]
def objectLines: List[String]
def commonClassLines = List(
- "override def getClass(): Class[@name@]"
+ "override def getClass(): Class[@name@] = null"
)
def lcname = name.toLowerCase
@@ -248,7 +248,7 @@ trait AnyValReps {
def objectDoc = ""
def mkImports = ""
- def mkClass = assemble("final class " + name + " private extends AnyVal", classLines)
+ def mkClass = assemble("final abstract class " + name + " private extends AnyVal", classLines)
def mkObject = assemble("object " + name + " extends AnyValCompanion", objectLines)
def make() = List[String](
headerTemplate,
@@ -281,6 +281,8 @@ trait AnyValTemplates {
%s
package scala
+import language.implicitConversions
+
""".trim.format(timestampString) + "\n\n")
def classDocTemplate = ("""
@@ -294,7 +296,6 @@ package scala
""".trim + "\n")
def timestampString = "// DO NOT EDIT, CHANGES WILL BE LOST.\n"
- def stub = """sys.error("stub")"""
def allCompanions = """
/** Transform a value type into a boxed reference type.
@@ -373,7 +374,7 @@ class AnyVals extends AnyValReps with AnyValTemplates {
*
* @return the negated expression
*/
-def unary_! : Boolean = sys.error("stub")
+def unary_! : Boolean
/**
* Compares two Boolean expressions and returns `true` if they evaluate to the same value.
@@ -382,7 +383,7 @@ def unary_! : Boolean = sys.error("stub")
* - `a` and `b` are `true` or
* - `a` and `b` are `false`.
*/
-def ==(x: Boolean): Boolean = sys.error("stub")
+def ==(x: Boolean): Boolean
/**
* Compares two Boolean expressions and returns `true` if they evaluate to a different value.
@@ -391,7 +392,7 @@ def ==(x: Boolean): Boolean = sys.error("stub")
* - `a` is `true` and `b` is `false` or
* - `a` is `false` and `b` is `true`.
*/
-def !=(x: Boolean): Boolean = sys.error("stub")
+def !=(x: Boolean): Boolean
/**
* Compares two Boolean expressions and returns `true` if one or both of them evaluate to true.
@@ -405,7 +406,7 @@ def !=(x: Boolean): Boolean = sys.error("stub")
* behaves as if it was declared as `def ||(x: => Boolean): Boolean`.
* If `a` evaluates to `true`, `true` is returned without evaluating `b`.
*/
-def ||(x: Boolean): Boolean = sys.error("stub")
+def ||(x: Boolean): Boolean
/**
* Compares two Boolean expressions and returns `true` if both of them evaluate to true.
@@ -417,11 +418,11 @@ def ||(x: Boolean): Boolean = sys.error("stub")
* behaves as if it was declared as `def &&(x: => Boolean): Boolean`.
* If `a` evaluates to `false`, `false` is returned without evaluating `b`.
*/
-def &&(x: Boolean): Boolean = sys.error("stub")
+def &&(x: Boolean): Boolean
// Compiler won't build with these seemingly more accurate signatures
-// def ||(x: => Boolean): Boolean = sys.error("stub")
-// def &&(x: => Boolean): Boolean = sys.error("stub")
+// def ||(x: => Boolean): Boolean
+// def &&(x: => Boolean): Boolean
/**
* Compares two Boolean expressions and returns `true` if one or both of them evaluate to true.
@@ -433,7 +434,7 @@ def &&(x: Boolean): Boolean = sys.error("stub")
*
* @note This method evaluates both `a` and `b`, even if the result is already determined after evaluating `a`.
*/
-def |(x: Boolean): Boolean = sys.error("stub")
+def |(x: Boolean): Boolean
/**
* Compares two Boolean expressions and returns `true` if both of them evaluate to true.
@@ -443,7 +444,7 @@ def |(x: Boolean): Boolean = sys.error("stub")
*
* @note This method evaluates both `a` and `b`, even if the result is already determined after evaluating `a`.
*/
-def &(x: Boolean): Boolean = sys.error("stub")
+def &(x: Boolean): Boolean
/**
* Compares two Boolean expressions and returns `true` if they evaluate to a different value.
@@ -452,9 +453,9 @@ def &(x: Boolean): Boolean = sys.error("stub")
* - `a` is `true` and `b` is `false` or
* - `a` is `false` and `b` is `true`.
*/
-def ^(x: Boolean): Boolean = sys.error("stub")
+def ^(x: Boolean): Boolean
-override def getClass(): Class[Boolean] = sys.error("stub")
+override def getClass(): Class[Boolean] = null
""".trim.lines.toList
def objectLines = interpolate(allCompanions + "\n" + nonUnitCompanions).lines.toList
@@ -468,7 +469,7 @@ override def getClass(): Class[Boolean] = sys.error("stub")
*/
"""
def classLines = List(
- """override def getClass(): Class[Unit] = sys.error("stub")"""
+ """override def getClass(): Class[Unit] = null"""
)
def objectLines = interpolate(allCompanions).lines.toList
diff --git a/src/compiler/scala/tools/nsc/Global.scala b/src/compiler/scala/tools/nsc/Global.scala
index ceb75b575d..271dca3157 100644
--- a/src/compiler/scala/tools/nsc/Global.scala
+++ b/src/compiler/scala/tools/nsc/Global.scala
@@ -343,8 +343,8 @@ class Global(var currentSettings: Settings, var reporter: Reporter) extends Symb
def checkPhase = wasActive(settings.check)
def logPhase = isActive(settings.log)
- // Write *.icode files the setting was given.
- def writeICode = settings.writeICode.isSetByUser && isActive(settings.writeICode)
+ // Write *.icode files right after GenICode when -Xprint-icode was given.
+ def writeICodeAtICode = settings.writeICode.isSetByUser && isActive(settings.writeICode)
// showing/printing things
def browsePhase = isActive(settings.browse)
@@ -1384,14 +1384,22 @@ class Global(var currentSettings: Settings, var reporter: Reporter) extends Symb
val mixinPhase = phaseNamed("mixin")
val cleanupPhase = phaseNamed("cleanup")
val icodePhase = phaseNamed("icode")
- // val inlinerPhase = phaseNamed("inliner")
- // val inlineExceptionHandlersPhase = phaseNamed("inlineExceptionHandlers")
- // val closelimPhase = phaseNamed("closelim")
- // val dcePhase = phaseNamed("dce")
+ val inlinerPhase = phaseNamed("inliner")
+ val inlineExceptionHandlersPhase = phaseNamed("inlineExceptionHandlers")
+ val closelimPhase = phaseNamed("closelim")
+ val dcePhase = phaseNamed("dce")
val jvmPhase = phaseNamed("jvm")
+ // val msilPhase = phaseNamed("msil")
def runIsAt(ph: Phase) = globalPhase.id == ph.id
def runIsPast(ph: Phase) = globalPhase.id > ph.id
+ // def runIsAtBytecodeGen = (runIsAt(jvmPhase) || runIsAt(msilPhase))
+ def runIsAtOptimiz = {
+ runIsAt(inlinerPhase) || // listing phases in full for robustness when -Ystop-after has been given.
+ runIsAt(inlineExceptionHandlersPhase) ||
+ runIsAt(closelimPhase) ||
+ runIsAt(dcePhase)
+ }
isDefined = true
@@ -1536,15 +1544,15 @@ class Global(var currentSettings: Settings, var reporter: Reporter) extends Symb
informTime(globalPhase.description, startTime)
phaseTimings(globalPhase) = currentTime - startTime
- // write icode to *.icode files
- if (opt.writeICode)
+ if (opt.writeICodeAtICode || (opt.printPhase && runIsAtOptimiz)) {
+ // Write *.icode files when -Xprint-icode or -Xprint:<some-optimiz-phase> was given.
writeICode()
-
- // print trees
- if (opt.printPhase || opt.printLate && runIsAt(cleanupPhase)) {
+ } else if (opt.printPhase || opt.printLate && runIsAt(cleanupPhase)) {
+ // print trees
if (opt.showTrees) nodePrinters.printAll()
else printAllUnits()
}
+
// print the symbols presently attached to AST nodes
if (opt.showSymbols)
trackerFactory.snapshot()
diff --git a/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala b/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala
index a0524d6932..43560f9d8d 100644
--- a/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala
+++ b/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala
@@ -162,9 +162,9 @@ self =>
def incompleteInputError(msg: String): Unit = throw new MalformedInput(source.content.length - 1, msg)
/** the markup parser */
- lazy val xmlp = new MarkupParser(this, true)
+ lazy val xmlp = new MarkupParser(this, preserveWS = true)
- object symbXMLBuilder extends SymbolicXMLBuilder(this, true) { // DEBUG choices
+ object symbXMLBuilder extends SymbolicXMLBuilder(this, preserveWS = true) { // DEBUG choices
val global: self.global.type = self.global
def freshName(prefix: String): Name = SourceFileParser.this.freshName(prefix)
}
@@ -735,9 +735,9 @@ self =>
}
ts.toList
}
- @inline final def commaSeparated[T](part: => T): List[T] = tokenSeparated(COMMA, false, part)
- @inline final def caseSeparated[T](part: => T): List[T] = tokenSeparated(CASE, true, part)
- @inline final def readAnnots[T](part: => T): List[T] = tokenSeparated(AT, true, part)
+ @inline final def commaSeparated[T](part: => T): List[T] = tokenSeparated(COMMA, sepFirst = false, part)
+ @inline final def caseSeparated[T](part: => T): List[T] = tokenSeparated(CASE, sepFirst = true, part)
+ @inline final def readAnnots[T](part: => T): List[T] = tokenSeparated(AT, sepFirst = true, part)
/* --------- OPERAND/OPERATOR STACK --------------------------------------- */
@@ -776,8 +776,7 @@ self =>
syntaxError(
offset, "left- and right-associative operators with same precedence may not be mixed", false)
- def reduceStack(isExpr: Boolean, base: List[OpInfo], top0: Tree,
- prec: Int, leftAssoc: Boolean): Tree = {
+ def reduceStack(isExpr: Boolean, base: List[OpInfo], top0: Tree, prec: Int, leftAssoc: Boolean): Tree = {
var top = top0
if (opstack != base && precedence(opstack.head.operator) == prec)
checkAssoc(opstack.head.offset, opstack.head.operator, leftAssoc)
@@ -825,7 +824,7 @@ self =>
atPos(start, in.skipToken()) { makeFunctionTypeTree(ts, typ()) }
else {
ts foreach checkNotByNameOrVarargs
- val tuple = atPos(start) { makeTupleType(ts, true) }
+ val tuple = atPos(start) { makeTupleType(ts, flattenUnary = true) }
infixTypeRest(
compoundTypeRest(
annotTypeRest(
@@ -887,10 +886,10 @@ self =>
def simpleType(): Tree = {
val start = in.offset
simpleTypeRest(in.token match {
- case LPAREN => atPos(start)(makeTupleType(inParens(types()), true))
+ case LPAREN => atPos(start)(makeTupleType(inParens(types()), flattenUnary = true))
case USCORE => wildcardType(in.skipToken())
case _ =>
- path(false, true) match {
+ path(thisOK = false, typeOK = true) match {
case r @ SingletonTypeTree(_) => r
case r => convertToTypeId(r)
}
@@ -900,7 +899,7 @@ self =>
private def typeProjection(t: Tree): Tree = {
val hashOffset = in.skipToken()
val nameOffset = in.offset
- val name = identForType(false)
+ val name = identForType(skipIt = false)
val point = if (name == tpnme.ERROR) hashOffset else nameOffset
atPos(t.pos.startOrPoint, point)(SelectFromTypeTree(t, name))
}
@@ -949,7 +948,7 @@ self =>
if (isIdent && in.name != nme.STAR) {
val opOffset = in.offset
val leftAssoc = treeInfo.isLeftAssoc(in.name)
- if (mode != InfixMode.FirstOp) checkAssoc(opOffset, in.name, mode == InfixMode.LeftOp)
+ if (mode != InfixMode.FirstOp) checkAssoc(opOffset, in.name, leftAssoc = mode == InfixMode.LeftOp)
val op = identForType()
val tycon = atPos(opOffset) { Ident(op) }
newLineOptWhenFollowing(isTypeIntroToken)
@@ -986,7 +985,7 @@ self =>
syntaxErrorOrIncomplete(expectedMsg(IDENTIFIER), skipIt)
nme.ERROR
}
- def ident(): Name = ident(true)
+ def ident(): Name = ident(skipIt = true)
def rawIdent(): Name = try in.name finally in.nextToken()
/** For when it's known already to be a type name. */
@@ -997,7 +996,7 @@ self =>
val point = in.offset
//assert(t.pos.isDefined, t)
if (t != EmptyTree)
- Select(t, ident(false)) setPos r2p(t.pos.startOrPoint, point, in.lastOffset)
+ Select(t, ident(skipIt = false)) setPos r2p(t.pos.startOrPoint, point, in.lastOffset)
else
errorTermTree // has already been reported
}
@@ -1055,7 +1054,8 @@ self =>
if (typeOK && in.token == TYPE) {
in.nextToken()
atPos(t.pos.startOrPoint, dotOffset) { SingletonTypeTree(t) }
- } else {
+ }
+ else {
val t1 = selector(t)
if (in.token == DOT) { selectors(t1, typeOK, in.skipToken()) }
else t1
@@ -1076,7 +1076,7 @@ self =>
* }}}
*/
def stableId(): Tree =
- path(false, false)
+ path(thisOK = false, typeOK = false)
/** {{{
* QualId ::= Id {`.' Id}
@@ -1085,7 +1085,7 @@ self =>
def qualId(): Tree = {
val start = in.offset
val id = atPos(start) { Ident(ident()) }
- if (in.token == DOT) { selectors(id, false, in.skipToken()) }
+ if (in.token == DOT) { selectors(id, typeOK = false, in.skipToken()) }
else id
}
/** Calls `qualId()` and manages some package state. */
@@ -1118,7 +1118,7 @@ self =>
if (in.token == SYMBOLLIT)
Apply(scalaDot(nme.Symbol), List(finish(in.strVal)))
else if (in.token == INTERPOLATIONID)
- interpolatedString(inPattern)
+ interpolatedString(inPattern = inPattern)
else finish(in.token match {
case CHARLIT => in.charVal
case INTLIT => in.intVal(isNegated).toInt
@@ -1206,7 +1206,7 @@ self =>
else startInfixType()
def annotTypeRest(t: Tree): Tree =
- (t /: annotations(false)) (makeAnnotated)
+ (t /: annotations(skipNewLines = false)) (makeAnnotated)
/** {{{
* WildcardType ::= `_' TypeBounds
@@ -1385,7 +1385,7 @@ self =>
syntaxErrorOrIncomplete("`*' expected", true)
}
} else if (in.token == AT) {
- t = (t /: annotations(false)) (makeAnnotated)
+ t = (t /: annotations(skipNewLines = false)) (makeAnnotated)
} else {
t = atPos(t.pos.startOrPoint, colonPos) {
val tpt = typeOrInfixType(location)
@@ -1451,7 +1451,7 @@ self =>
var top = prefixExpr()
while (isIdent) {
- top = reduceStack(true, base, top, precedence(in.name), treeInfo.isLeftAssoc(in.name))
+ top = reduceStack(isExpr = true, base, top, precedence(in.name), leftAssoc = treeInfo.isLeftAssoc(in.name))
val op = in.name
opstack = OpInfo(top, op, in.offset) :: opstack
ident()
@@ -1459,19 +1459,19 @@ self =>
if (isExprIntro) {
val next = prefixExpr()
if (next == EmptyTree)
- return reduceStack(true, base, top, 0, true)
+ return reduceStack(isExpr = true, base, top, 0, leftAssoc = true)
top = next
} else {
// postfix expression
val topinfo = opstack.head
opstack = opstack.tail
- val od = stripParens(reduceStack(true, base, topinfo.operand, 0, true))
+ val od = stripParens(reduceStack(isExpr = true, base, topinfo.operand, 0, leftAssoc = true))
return atPos(od.pos.startOrPoint, topinfo.offset) {
new PostfixSelect(od, topinfo.operator.encode)
}
}
}
- reduceStack(true, base, top, 0, true)
+ reduceStack(isExpr = true, base, top, 0, leftAssoc = true)
}
/** {{{
@@ -1482,9 +1482,10 @@ self =>
if (isUnaryOp) {
atPos(in.offset) {
val name = nme.toUnaryName(rawIdent())
- // val name = nme.toUnaryName(ident()) // val name: Name = "unary_" + ident()
- if (name == nme.UNARY_- && isNumericLit) simpleExprRest(atPos(in.offset)(literal(isNegated = true)), true)
- else Select(stripParens(simpleExpr()), name)
+ if (name == nme.UNARY_- && isNumericLit)
+ simpleExprRest(atPos(in.offset)(literal(isNegated = true)), canApply = true)
+ else
+ Select(stripParens(simpleExpr()), name)
}
}
else simpleExpr()
@@ -1512,7 +1513,7 @@ self =>
case XMLSTART =>
xmlLiteral()
case IDENTIFIER | BACKQUOTED_IDENT | THIS | SUPER =>
- path(true, false)
+ path(thisOK = true, typeOK = false)
case USCORE =>
val start = in.offset
val pname = freshName("x$")
@@ -1531,14 +1532,14 @@ self =>
val nstart = in.skipToken()
val npos = r2p(nstart, nstart, in.lastOffset)
val tstart = in.offset
- val (parents, argss, self, stats) = template(false)
+ val (parents, argss, self, stats) = template(isTrait = false)
val cpos = r2p(tstart, tstart, in.lastOffset max tstart)
makeNew(parents, self, stats, argss, npos, cpos)
case _ =>
syntaxErrorOrIncomplete("illegal start of simple expression", true)
errorTermTree
}
- simpleExprRest(t, canApply)
+ simpleExprRest(t, canApply = canApply)
}
def simpleExprRest(t: Tree, canApply: Boolean): Tree = {
@@ -1546,7 +1547,7 @@ self =>
in.token match {
case DOT =>
in.nextToken()
- simpleExprRest(selector(stripParens(t)), true)
+ simpleExprRest(selector(stripParens(t)), canApply = true)
case LBRACKET =>
val t1 = stripParens(t)
t1 match {
@@ -1555,7 +1556,7 @@ self =>
while (in.token == LBRACKET)
app = atPos(app.pos.startOrPoint, in.offset)(TypeApply(app, exprTypeArgs()))
- simpleExprRest(app, true)
+ simpleExprRest(app, canApply = true)
case _ =>
t1
}
@@ -1571,7 +1572,7 @@ self =>
}
Apply(sel, argumentExprs())
}
- simpleExprRest(app, true)
+ simpleExprRest(app, canApply = true)
case USCORE =>
atPos(t.pos.startOrPoint, in.skipToken()) {
Typed(stripParens(t), Function(Nil, EmptyTree))
@@ -1659,11 +1660,11 @@ self =>
*/
def enumerators(): List[Enumerator] = {
val enums = new ListBuffer[Enumerator]
- generator(enums, false)
+ generator(enums, eqOK = false)
while (isStatSep) {
in.nextToken()
if (in.token == IF) enums += makeFilter(in.offset, guard())
- else generator(enums, true)
+ else generator(enums, eqOK = true)
}
enums.toList
}
@@ -1827,13 +1828,13 @@ self =>
}
val base = opstack
while (isIdent && in.name != raw.BAR) {
- top = reduceStack(false, base, top, precedence(in.name), treeInfo.isLeftAssoc(in.name))
+ top = reduceStack(isExpr = false, base, top, precedence(in.name), leftAssoc = treeInfo.isLeftAssoc(in.name))
val op = in.name
opstack = OpInfo(top, op, in.offset) :: opstack
ident()
top = simplePattern(badPattern3)
}
- stripParens(reduceStack(false, base, top, 0, true))
+ stripParens(reduceStack(isExpr = false, base, top, 0, leftAssoc = true))
}
def badPattern3(): Tree = {
def isComma = in.token == COMMA
@@ -2096,7 +2097,7 @@ self =>
var caseParam = ofCaseClass
def param(): ValDef = {
val start = in.offset
- val annots = annotations(false)
+ val annots = annotations(skipNewLines = false)
var mods = Modifiers(Flags.PARAM)
if (owner.isTypeName) {
mods = modifiers() | Flags.PARAMACCESSOR
@@ -2244,7 +2245,7 @@ self =>
param
}
newLineOptWhenFollowedBy(LBRACKET)
- if (in.token == LBRACKET) inBrackets(commaSeparated(typeParam(NoMods withAnnotations annotations(true))))
+ if (in.token == LBRACKET) inBrackets(commaSeparated(typeParam(NoMods withAnnotations annotations(skipNewLines = true))))
else Nil
}
@@ -2401,7 +2402,7 @@ self =>
private def caseAwareTokenOffset = if (in.token == CASECLASS || in.token == CASEOBJECT) in.prev.offset else in.offset
def nonLocalDefOrDcl : List[Tree] = {
- val annots = annotations(true)
+ val annots = annotations(skipNewLines = true)
defOrDcl(caseAwareTokenOffset, modifiers() withAnnotations annots)
}
@@ -2495,7 +2496,7 @@ self =>
in.nextToken
if (in.token == THIS) {
atPos(start, in.skipToken()) {
- val vparamss = paramClauses(nme.CONSTRUCTOR, classContextBounds map (_.duplicate), false)
+ val vparamss = paramClauses(nme.CONSTRUCTOR, classContextBounds map (_.duplicate), ofCaseClass = false)
newLineOptWhenFollowedBy(LBRACE)
val rhs = in.token match {
case LBRACE => atPos(in.offset) { constrBlock(vparamss) }
@@ -2519,7 +2520,7 @@ self =>
// i.e. (B[T] or T => B)
val contextBoundBuf = new ListBuffer[Tree]
val tparams = typeParamClauseOpt(name, contextBoundBuf)
- val vparamss = paramClauses(name, contextBoundBuf.toList, false)
+ val vparamss = paramClauses(name, contextBoundBuf.toList, ofCaseClass = false)
newLineOptWhenFollowedBy(LBRACE)
var restype = fromWithinReturnType(typedOpt())
val rhs =
@@ -2618,7 +2619,7 @@ self =>
/** Hook for IDE, for top-level classes/objects. */
def topLevelTmplDef: Tree = {
- val annots = annotations(true)
+ val annots = annotations(skipNewLines = true)
val pos = caseAwareTokenOffset
val mods = modifiers() withAnnotations annots
tmplDef(pos, mods)
@@ -2672,7 +2673,7 @@ self =>
val constrAnnots = constructorAnnotations()
val (constrMods, vparamss) =
if (mods.isTrait) (Modifiers(Flags.TRAIT), List())
- else (accessModifierOpt(), paramClauses(name, classContextBounds, mods.isCase))
+ else (accessModifierOpt(), paramClauses(name, classContextBounds, ofCaseClass = mods.isCase))
var mods1 = mods
if (mods.isTrait) {
if (settings.YvirtClasses && in.token == SUBTYPE) mods1 |= Flags.DEFERRED
@@ -2739,7 +2740,7 @@ self =>
newLineOptWhenFollowedBy(LBRACE)
if (in.token == LBRACE) {
// @S: pre template body cannot stub like post body can!
- val (self, body) = templateBody(true)
+ val (self, body) = templateBody(isPre = true)
if (in.token == WITH && self.isEmpty) {
val earlyDefs: List[Tree] = body flatMap {
case vdef @ ValDef(mods, _, _, _) if !mods.isDeferred =>
@@ -2752,15 +2753,15 @@ self =>
case _ => List()
}
in.nextToken()
- val (parents, argss) = templateParents(isTrait)
- val (self1, body1) = templateBodyOpt(isTrait)
+ val (parents, argss) = templateParents(isTrait = isTrait)
+ val (self1, body1) = templateBodyOpt(traitParentSeen = isTrait)
(parents, argss, self1, earlyDefs ::: body1)
} else {
(List(), List(List()), self, body)
}
} else {
- val (parents, argss) = templateParents(isTrait)
- val (self, body) = templateBodyOpt(isTrait)
+ val (parents, argss) = templateParents(isTrait = isTrait)
+ val (self, body) = templateBodyOpt(traitParentSeen = isTrait)
(parents, argss, self, body)
}
}
@@ -2778,11 +2779,11 @@ self =>
val (parents0, argss, self, body) = (
if (in.token == EXTENDS || in.token == SUBTYPE && mods.isTrait) {
in.nextToken()
- template(mods.isTrait)
+ template(isTrait = mods.isTrait)
}
else {
newLineOptWhenFollowedBy(LBRACE)
- val (self, body) = templateBodyOpt(false)
+ val (self, body) = templateBodyOpt(traitParentSeen = false)
(List(), List(List()), self, body)
}
)
@@ -2816,14 +2817,14 @@ self =>
* }}}
* @param isPre specifies whether in early initializer (true) or not (false)
*/
- def templateBody(isPre: Boolean) = inBraces(templateStatSeq(isPre)) match {
+ def templateBody(isPre: Boolean) = inBraces(templateStatSeq(isPre = isPre)) match {
case (self, Nil) => (self, List(EmptyTree))
case result => result
}
def templateBodyOpt(traitParentSeen: Boolean): (ValDef, List[Tree]) = {
newLineOptWhenFollowedBy(LBRACE)
if (in.token == LBRACE) {
- templateBody(false)
+ templateBody(isPre = false)
} else {
if (in.token == LPAREN)
syntaxError((if (traitParentSeen) "parents of traits" else "traits or objects")+
@@ -2920,7 +2921,7 @@ self =>
/** Informal - for the repl and other direct parser accessors.
*/
- def templateStats(): List[Tree] = templateStatSeq(false)._2 match {
+ def templateStats(): List[Tree] = templateStatSeq(isPre = false)._2 match {
case Nil => List(EmptyTree)
case stats => stats
}
@@ -3004,7 +3005,7 @@ self =>
def localDef : List[Tree] = {
atEndPos {
atStartPos(in.offset) {
- val annots = annotations(true)
+ val annots = annotations(skipNewLines = true)
val mods = localModifiers() withAnnotations annots
if (!(mods hasFlag ~(Flags.IMPLICIT | Flags.LAZY))) defOrDcl(mods)
else List(tmplDef(mods))
@@ -3014,7 +3015,7 @@ self =>
*/
def localDef(implicitMod: Int): List[Tree] = {
- val annots = annotations(true)
+ val annots = annotations(skipNewLines = true)
val pos = in.offset
val mods = (localModifiers() | implicitMod) withAnnotations annots
val defs =
diff --git a/src/compiler/scala/tools/nsc/backend/jvm/GenASM.scala b/src/compiler/scala/tools/nsc/backend/jvm/GenASM.scala
index 97b2426646..3f193672ec 100644
--- a/src/compiler/scala/tools/nsc/backend/jvm/GenASM.scala
+++ b/src/compiler/scala/tools/nsc/backend/jvm/GenASM.scala
@@ -283,12 +283,16 @@ abstract class GenASM extends SubComponent with BytecodeWriters {
&& !sym.isMutable // lazy vals and vars both
)
+ // Primitives are "abstract final" to prohibit instantiation
+ // without having to provide any implementations, but that is an
+ // illegal combination of modifiers at the bytecode level so
+ // suppress final if abstract if present.
import asm.Opcodes._
mkFlags(
if (privateFlag) ACC_PRIVATE else ACC_PUBLIC,
if (sym.isDeferred || sym.hasAbstractFlag) ACC_ABSTRACT else 0,
if (sym.isInterface) ACC_INTERFACE else 0,
- if (finalFlag) ACC_FINAL else 0,
+ if (finalFlag && !sym.hasAbstractFlag) ACC_FINAL else 0,
if (sym.isStaticMember) ACC_STATIC else 0,
if (sym.isBridge) ACC_BRIDGE | ACC_SYNTHETIC else 0,
if (sym.isClass && !sym.isInterface) ACC_SUPER else 0,
@@ -433,10 +437,11 @@ abstract class GenASM extends SubComponent with BytecodeWriters {
}
private val majorVersion: Int = (classfileVersion & 0xFF)
+ private val emitStackMapFrame = (majorVersion >= 50)
private val extraProc: Int = mkFlags(
asm.ClassWriter.COMPUTE_MAXS,
- if(majorVersion >= 50) asm.ClassWriter.COMPUTE_FRAMES else 0
+ if(emitStackMapFrame) asm.ClassWriter.COMPUTE_FRAMES else 0
)
val JAVA_LANG_OBJECT = asm.Type.getObjectType("java/lang/Object")
@@ -580,14 +585,14 @@ abstract class GenASM extends SubComponent with BytecodeWriters {
else { sym.javaSimpleName }
})
- if(hasInternalName) {
+ if(emitStackMapFrame && hasInternalName) {
val internalName = cachedJN.toString()
val trackedSym = jsymbol(sym)
reverseJavaName.get(internalName) match {
case None =>
reverseJavaName.put(internalName, trackedSym)
case Some(oldsym) =>
- assert((oldsym == trackedSym) || List(RuntimeNothingClass, RuntimeNullClass).contains(oldsym), // NothingClass, NullClass,
+ assert((oldsym == trackedSym) || (oldsym == RuntimeNothingClass) || (oldsym == RuntimeNullClass), // In contrast, neither NothingClass nor NullClass show up bytecode-level.
"how can getCommonSuperclass() do its job if different class symbols get the same bytecode-level internal name.")
}
}
@@ -2720,7 +2725,7 @@ abstract class GenASM extends SubComponent with BytecodeWriters {
// TODO Logical's 2nd elem should be declared ValueTypeKind, to better approximate its allowed values (isIntSized, its comments appears to convey)
// TODO GenICode uses `toTypeKind` to define that elem, `toValueTypeKind` would be needed instead.
// TODO How about adding some asserts to Logical and similar ones to capture the remaining constraint (UNIT not allowed).
- case Logical(op, kind) => (op, kind) match {
+ case Logical(op, kind) => ((op, kind): @unchecked) match {
case (AND, LONG) => emit(Opcodes.LAND)
case (AND, INT) => emit(Opcodes.IAND)
case (AND, _) =>
@@ -2740,7 +2745,7 @@ abstract class GenASM extends SubComponent with BytecodeWriters {
if (kind != BOOL) { emitT2T(INT, kind) }
}
- case Shift(op, kind) => (op, kind) match {
+ case Shift(op, kind) => ((op, kind): @unchecked) match {
case (LSL, LONG) => emit(Opcodes.LSHL)
case (LSL, INT) => emit(Opcodes.ISHL)
case (LSL, _) =>
diff --git a/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala b/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala
index c29630d04b..73bcd08f4b 100644
--- a/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala
+++ b/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala
@@ -1961,11 +1961,15 @@ abstract class GenJVM extends SubComponent with GenJVMUtil with GenAndroid with
&& !sym.isMutable // lazy vals and vars both
)
+ // Primitives are "abstract final" to prohibit instantiation
+ // without having to provide any implementations, but that is an
+ // illegal combination of modifiers at the bytecode level so
+ // suppress final if abstract if present.
mkFlags(
if (privateFlag) ACC_PRIVATE else ACC_PUBLIC,
if (sym.isDeferred || sym.hasAbstractFlag) ACC_ABSTRACT else 0,
if (sym.isInterface) ACC_INTERFACE else 0,
- if (finalFlag) ACC_FINAL else 0,
+ if (finalFlag && !sym.hasAbstractFlag) ACC_FINAL else 0,
if (sym.isStaticMember) ACC_STATIC else 0,
if (sym.isBridge) ACC_BRIDGE | ACC_SYNTHETIC else 0,
if (sym.isClass && !sym.isInterface) ACC_SUPER else 0,
diff --git a/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala b/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala
index efde2cee25..88a89d54eb 100644
--- a/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala
+++ b/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala
@@ -109,6 +109,7 @@ trait ScalaSettings extends AbsScalaSettings
val sourceReader = StringSetting ("-Xsource-reader", "classname", "Specify a custom method for reading source files.", "")
val XoldPatmat = BooleanSetting ("-Xoldpatmat", "Use the pre-2.10 pattern matcher. Otherwise, the 'virtualizing' pattern matcher is used in 2.10.")
+ val XnoPatmatAnalysis = BooleanSetting ("-Xno-patmat-analysis", "Don't perform exhaustivity/unreachability analysis. Also, ignore @switch annotation.")
/** Compatibility stubs for options whose value name did
* not previously match the option name.
diff --git a/src/compiler/scala/tools/nsc/typechecker/PatternMatching.scala b/src/compiler/scala/tools/nsc/typechecker/PatternMatching.scala
index b36a92a186..48985213d1 100644
--- a/src/compiler/scala/tools/nsc/typechecker/PatternMatching.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/PatternMatching.scala
@@ -14,6 +14,7 @@ import scala.tools.nsc.transform.TypingTransformers
import scala.tools.nsc.transform.Transform
import scala.collection.mutable.HashSet
import scala.collection.mutable.HashMap
+import scala.tools.nsc.util.Statistics
/** Translate pattern matching.
*
@@ -26,11 +27,9 @@ import scala.collection.mutable.HashMap
* Cases are combined into a pattern match using the `orElse` combinator (the implicit failure case is expressed using the monad's `zero`).
*
* TODO:
- * - exhaustivity
- * - DCE (unreachability/refutability/optimization)
* - use TypeTags for type testing
- * - Array patterns
- * - implement spec more closely (see TODO's)
+ * - DCE (on irrefutable patterns)
+ * - update spec and double check it's implemented correctly (see TODO's)
*
* (longer-term) TODO:
* - user-defined unapplyProd
@@ -38,6 +37,8 @@ import scala.collection.mutable.HashMap
* - recover exhaustivity and unreachability checking using a variation on the type-safe builder pattern
*/
trait PatternMatching extends Transform with TypingTransformers with ast.TreeDSL { // self: Analyzer =>
+ import Statistics._
+
val global: Global // need to repeat here because otherwise last mixin defines global as
// SymbolTable. If we had DOT this would not be an issue
import global._ // the global environment
@@ -45,6 +46,8 @@ trait PatternMatching extends Transform with TypingTransformers with ast.TreeDSL
val phaseName: String = "patmat"
+ def patmatDebug(msg: String) = println(msg)
+
def newTransformer(unit: CompilationUnit): Transformer =
if (opt.virtPatmat) new MatchTransformer(unit)
else noopTransformer
@@ -173,13 +176,15 @@ trait PatternMatching extends Transform with TypingTransformers with ast.TreeDSL
// (that would require more sophistication when generating trees,
// and the only place that emits Matches after typers is for exception handling anyway)
if(phase.id >= currentRun.uncurryPhase.id) debugwarn("running translateMatch at "+ phase +" on "+ selector +" match "+ cases)
- // println("translating "+ cases.mkString("{", "\n", "}"))
+ // patmatDebug("translating "+ cases.mkString("{", "\n", "}"))
def repeatedToSeq(tp: Type): Type = (tp baseType RepeatedParamClass) match {
case TypeRef(_, RepeatedParamClass, arg :: Nil) => seqType(arg)
case _ => tp
}
+ val start = startTimer(patmatNanos)
+
val selectorTp = repeatedToSeq(elimAnonymousClass(selector.tpe.widen.withoutAnnotations))
val origPt = match_.tpe
@@ -203,7 +208,10 @@ trait PatternMatching extends Transform with TypingTransformers with ast.TreeDSL
val selectorSym = freshSym(selector.pos, pureType(selectorTp)) setFlag SYNTH_CASE
// pt = Any* occurs when compiling test/files/pos/annotDepMethType.scala with -Xexperimental
- combineCases(selector, selectorSym, cases map translateCase(selectorSym, pt), pt, matchOwner, matchFailGenOverride)
+ val combined = combineCases(selector, selectorSym, cases map translateCase(selectorSym, pt), pt, matchOwner, matchFailGenOverride)
+
+ stopTimer(patmatNanos, start)
+ combined
}
// return list of typed CaseDefs that are supported by the backend (typed/bind/wildcard)
@@ -297,9 +305,9 @@ trait PatternMatching extends Transform with TypingTransformers with ast.TreeDSL
// as b.info may be based on a Typed type ascription, which has not been taken into account yet by the translation
// (it will later result in a type test when `tp` is not a subtype of `b.info`)
// TODO: can we simplify this, together with the Bound case?
- (extractor.subPatBinders, extractor.subPatTypes).zipped foreach { case (b, tp) => b setInfo tp } // println("changing "+ b +" : "+ b.info +" -> "+ tp);
+ (extractor.subPatBinders, extractor.subPatTypes).zipped foreach { case (b, tp) => b setInfo tp } // patmatDebug("changing "+ b +" : "+ b.info +" -> "+ tp);
- // println("translateExtractorPattern checking parameter type: "+ (patBinder, patBinder.info.widen, extractor.paramType, patBinder.info.widen <:< extractor.paramType))
+ // patmatDebug("translateExtractorPattern checking parameter type: "+ (patBinder, patBinder.info.widen, extractor.paramType, patBinder.info.widen <:< extractor.paramType))
// example check: List[Int] <:< ::[Int]
// TODO: extractor.paramType may contain unbound type params (run/t2800, run/t3530)
val (typeTestTreeMaker, patBinderOrCasted) =
@@ -337,7 +345,7 @@ trait PatternMatching extends Transform with TypingTransformers with ast.TreeDSL
case WildcardPattern() => noFurtherSubPats()
case UnApply(unfun, args) =>
// TODO: check unargs == args
- // println("unfun: "+ (unfun.tpe, unfun.symbol.ownerChain, unfun.symbol.info, patBinder.info))
+ // patmatDebug("unfun: "+ (unfun.tpe, unfun.symbol.ownerChain, unfun.symbol.info, patBinder.info))
translateExtractorPattern(ExtractorCall(unfun, args))
/** A constructor pattern is of the form c(p1, ..., pn) where n ≥ 0.
@@ -403,7 +411,7 @@ trait PatternMatching extends Transform with TypingTransformers with ast.TreeDSL
*/
case Bind(n, p) => // this happens in certain ill-formed programs, there'll be an error later
- // println("WARNING: Bind tree with unbound symbol "+ patTree)
+ // patmatDebug("WARNING: Bind tree with unbound symbol "+ patTree)
noFurtherSubPats() // there's no symbol -- something's wrong... don't fail here though (or should we?)
// case Star(_) | ArrayValue | This => error("stone age pattern relics encountered!")
@@ -476,13 +484,13 @@ trait PatternMatching extends Transform with TypingTransformers with ast.TreeDSL
// this fails to resolve overloading properly...
// Apply(typedOperator(Select(orig, extractor)), List(Ident(nme.SELECTOR_DUMMY))) // no need to set the type of the dummy arg, it will be replaced anyway
- // println("funtpe after = "+ fun.tpe.finalResultType)
- // println("orig: "+(orig, orig.tpe))
+ // patmatDebug("funtpe after = "+ fun.tpe.finalResultType)
+ // patmatDebug("orig: "+(orig, orig.tpe))
val tgt = typed(orig, EXPRmode | QUALmode | POLYmode, HasMember(extractor.name)) // can't specify fun.tpe.finalResultType as the type for the extractor's arg,
// as it may have been inferred incorrectly (see t602, where it's com.mosol.sl.Span[Any], instead of com.mosol.sl.Span[?K])
- // println("tgt = "+ (tgt, tgt.tpe))
+ // patmatDebug("tgt = "+ (tgt, tgt.tpe))
val oper = typed(Select(tgt, extractor.name), EXPRmode | FUNmode | POLYmode | TAPPmode, WildcardType)
- // println("oper: "+ (oper, oper.tpe))
+ // patmatDebug("oper: "+ (oper, oper.tpe))
Apply(oper, List(Ident(nme.SELECTOR_DUMMY))) // no need to set the type of the dummy arg, it will be replaced anyway
}
} finally context.undetparams = savedUndets
@@ -598,8 +606,8 @@ trait PatternMatching extends Transform with TypingTransformers with ast.TreeDSL
// private val orig = fun match {case tpt: TypeTree => tpt.original case _ => fun}
// private val origExtractorTp = unapplyMember(orig.symbol.filter(sym => reallyExists(unapplyMember(sym.tpe))).tpe).tpe
// private val extractorTp = if (wellKinded(fun.tpe)) fun.tpe else existentialAbstraction(origExtractorTp.typeParams, origExtractorTp.resultType)
- // println("ExtractorCallProd: "+ (fun.tpe, existentialAbstraction(origExtractorTp.typeParams, origExtractorTp.resultType)))
- // println("ExtractorCallProd: "+ (fun.tpe, args map (_.tpe)))
+ // patmatDebug("ExtractorCallProd: "+ (fun.tpe, existentialAbstraction(origExtractorTp.typeParams, origExtractorTp.resultType)))
+ // patmatDebug("ExtractorCallProd: "+ (fun.tpe, args map (_.tpe)))
private def constructorTp = fun.tpe
def isTyped = fun.isTyped
@@ -627,14 +635,14 @@ trait PatternMatching extends Transform with TypingTransformers with ast.TreeDSL
def indexInCPA(acc: Symbol) =
constrParamAccessors indexWhere { orig =>
- // println("compare: "+ (orig, acc, orig.name, acc.name, (acc.name == orig.name), (acc.name startsWith (orig.name append "$"))))
+ // patmatDebug("compare: "+ (orig, acc, orig.name, acc.name, (acc.name == orig.name), (acc.name startsWith (orig.name append "$"))))
val origName = orig.name.toString.trim
val accName = acc.name.toString.trim
(accName == origName) || (accName startsWith (origName + "$"))
}
- // println("caseFieldAccessors: "+ (accessors, binder.caseFieldAccessors map indexInCPA))
- // println("constrParamAccessors: "+ constrParamAccessors)
+ // patmatDebug("caseFieldAccessors: "+ (accessors, binder.caseFieldAccessors map indexInCPA))
+ // patmatDebug("constrParamAccessors: "+ constrParamAccessors)
val accessorsSorted = accessors sortBy indexInCPA
if (accessorsSorted isDefinedAt (i-1)) REF(binder) DOT accessorsSorted(i-1)
@@ -793,6 +801,8 @@ trait PatternMatching extends Transform with TypingTransformers with ast.TreeDSL
None
abstract class TreeMaker {
+ def pos: Position
+
/** captures the scope and the value of the bindings in patterns
* important *when* the substitution happens (can't accumulate and do at once after the full matcher has been constructed)
*/
@@ -804,7 +814,7 @@ trait PatternMatching extends Transform with TypingTransformers with ast.TreeDSL
private[TreeMakers] def incorporateOuterSubstitution(outerSubst: Substitution): Unit = {
if (currSub ne null) {
- println("BUG: incorporateOuterSubstitution called more than once for "+ (this, currSub, outerSubst))
+ // patmatDebug("BUG: incorporateOuterSubstitution called more than once for "+ (this, currSub, outerSubst))
Thread.dumpStack()
}
else currSub = outerSubst >> substitution
@@ -820,16 +830,22 @@ trait PatternMatching extends Transform with TypingTransformers with ast.TreeDSL
}
case class TrivialTreeMaker(tree: Tree) extends TreeMaker with NoNewBinders {
+ def pos = tree.pos
+
def chainBefore(next: Tree)(casegen: Casegen): Tree = tree
}
case class BodyTreeMaker(body: Tree, matchPt: Type) extends TreeMaker with NoNewBinders {
+ def pos = body.pos
+
def chainBefore(next: Tree)(casegen: Casegen): Tree = // assert(next eq EmptyTree)
atPos(body.pos)(casegen.one(substitution(body))) // since SubstOnly treemakers are dropped, need to do it here
override def toString = "B"+(body, matchPt)
}
case class SubstOnlyTreeMaker(prevBinder: Symbol, nextBinder: Symbol) extends TreeMaker {
+ val pos = NoPosition
+
val localSubstitution = Substitution(prevBinder, CODE.REF(nextBinder))
def chainBefore(next: Tree)(casegen: Casegen): Tree = substitution(next)
override def toString = "S"+ localSubstitution
@@ -837,10 +853,10 @@ trait PatternMatching extends Transform with TypingTransformers with ast.TreeDSL
abstract class FunTreeMaker extends TreeMaker {
val nextBinder: Symbol
+ def pos = nextBinder.pos
}
abstract class CondTreeMaker extends FunTreeMaker {
- val pos: Position
val prevBinder: Symbol
val nextBinderTp: Type
val cond: Tree
@@ -962,11 +978,9 @@ trait PatternMatching extends Transform with TypingTransformers with ast.TreeDSL
- A parameterized type pattern scala.Array[T1], where T1 is a type pattern. // TODO
This type pattern matches any non-null instance of type scala.Array[U1], where U1 is a type matched by T1.
**/
- case class TypeTestTreeMaker(prevBinder: Symbol, testedBinder: Symbol, expectedTp: Type, nextBinderTp: Type)(_pos: Position, extractorArgTypeTest: Boolean = false) extends CondTreeMaker {
- val pos = _pos
-
+ case class TypeTestTreeMaker(prevBinder: Symbol, testedBinder: Symbol, expectedTp: Type, nextBinderTp: Type)(override val pos: Position, extractorArgTypeTest: Boolean = false) extends CondTreeMaker {
import TypeTestTreeMaker._
- // println("TTTM"+(prevBinder, extractorArgTypeTest, testedBinder, expectedTp, nextBinderTp))
+ // patmatDebug("TTTM"+(prevBinder, extractorArgTypeTest, testedBinder, expectedTp, nextBinderTp))
lazy val outerTestNeeded = (
!((expectedTp.prefix eq NoPrefix) || expectedTp.prefix.typeSymbol.isPackageClass)
@@ -985,6 +999,9 @@ trait PatternMatching extends Transform with TypingTransformers with ast.TreeDSL
if (outerTestNeeded) and(typeTest(testedBinder, expectedTp), outerTest(testedBinder, expectedTp))
else typeTest(testedBinder, expectedTp)
+ // propagate expected type
+ @inline def expTp(t: Tree): t.type = t setType expectedTp
+
// true when called to type-test the argument to an extractor
// don't do any fancy equality checking, just test the type
if (extractorArgTypeTest) default
@@ -994,11 +1011,10 @@ trait PatternMatching extends Transform with TypingTransformers with ast.TreeDSL
case SingleType(_, sym) => and(equalsTest(CODE.REF(sym), testedBinder), typeTest(testedBinder, expectedTp.widen))
// must use == to support e.g. List() == Nil
case ThisType(sym) if sym.isModule => and(equalsTest(CODE.REF(sym), testedBinder), typeTest(testedBinder, expectedTp.widen))
- case ConstantType(const) => equalsTest(Literal(const), testedBinder)
-
- case ThisType(sym) => eqTest(This(sym), testedBinder)
case ConstantType(Constant(null)) if testedBinder.info.widen <:< AnyRefClass.tpe
- => eqTest(CODE.NULL, testedBinder)
+ => eqTest(expTp(CODE.NULL), testedBinder)
+ case ConstantType(const) => equalsTest(expTp(Literal(const)), testedBinder)
+ case ThisType(sym) => eqTest(expTp(This(sym)), testedBinder)
// TODO: verify that we don't need to special-case Array
// I think it's okay:
@@ -1023,7 +1039,7 @@ trait PatternMatching extends Transform with TypingTransformers with ast.TreeDSL
}
// need to substitute to deal with existential types -- TODO: deal with existentials better, don't substitute (see RichClass during quick.comp)
- case class EqualityTestTreeMaker(prevBinder: Symbol, patTree: Tree, pos: Position) extends CondTreeMaker {
+ case class EqualityTestTreeMaker(prevBinder: Symbol, patTree: Tree, override val pos: Position) extends CondTreeMaker {
val nextBinderTp = prevBinder.info.widen
// NOTE: generate `patTree == patBinder`, since the extractor must be in control of the equals method (also, patBinder may be null)
@@ -1056,6 +1072,8 @@ trait PatternMatching extends Transform with TypingTransformers with ast.TreeDSL
}
case class GuardTreeMaker(guardTree: Tree) extends TreeMaker with NoNewBinders {
+ val pos = guardTree.pos
+
def chainBefore(next: Tree)(casegen: Casegen): Tree = casegen.flatMapGuard(substitution(guardTree), next)
override def toString = "G("+ guardTree +")"
}
@@ -1090,19 +1108,21 @@ trait PatternMatching extends Transform with TypingTransformers with ast.TreeDSL
fixerUpper(owner, scrut.pos){
val ptDefined = if (isFullyDefined(pt)) pt else NoType
def matchFailGen = (matchFailGenOverride orElse Some(CODE.MATCHERROR(_: Tree)))
- // println("combining cases: "+ (casesNoSubstOnly.map(_.mkString(" >> ")).mkString("{", "\n", "}")))
+ // patmatDebug("combining cases: "+ (casesNoSubstOnly.map(_.mkString(" >> ")).mkString("{", "\n", "}")))
def isSwitchAnnotation(tpe: Type) = tpe hasAnnotation SwitchClass
def isUncheckedAnnotation(tpe: Type) = tpe hasAnnotation UncheckedClass
- val (unchecked, requireSwitch) = scrut match {
- case Typed(_, tpt) =>
- (isUncheckedAnnotation(tpt.tpe),
- // matches with two or fewer cases need not apply for switchiness (if-then-else will do)
- isSwitchAnnotation(tpt.tpe) && casesNoSubstOnly.lengthCompare(2) > 0)
- case _ =>
- (false, false)
- }
+ val (unchecked, requireSwitch) =
+ if (settings.XnoPatmatAnalysis.value) (true, false)
+ else scrut match {
+ case Typed(_, tpt) =>
+ (isUncheckedAnnotation(tpt.tpe),
+ // matches with two or fewer cases need not apply for switchiness (if-then-else will do)
+ isSwitchAnnotation(tpt.tpe) && casesNoSubstOnly.lengthCompare(2) > 0)
+ case _ =>
+ (false, false)
+ }
emitSwitch(scrut, scrutSym, casesNoSubstOnly, pt, matchFailGenOverride).getOrElse{
if (requireSwitch) typer.context.unit.warning(scrut.pos, "could not emit switch for @switch annotated match")
@@ -1145,12 +1165,12 @@ trait PatternMatching extends Transform with TypingTransformers with ast.TreeDSL
t match {
case Function(_, _) if t.symbol == NoSymbol =>
t.symbol = currentOwner.newAnonymousFunctionValue(t.pos)
- // println("new symbol for "+ (t, t.symbol.ownerChain))
+ // patmatDebug("new symbol for "+ (t, t.symbol.ownerChain))
case Function(_, _) if (t.symbol.owner == NoSymbol) || (t.symbol.owner == origOwner) =>
- // println("fundef: "+ (t, t.symbol.ownerChain, currentOwner.ownerChain))
+ // patmatDebug("fundef: "+ (t, t.symbol.ownerChain, currentOwner.ownerChain))
t.symbol.owner = currentOwner
case d : DefTree if (d.symbol != NoSymbol) && ((d.symbol.owner == NoSymbol) || (d.symbol.owner == origOwner)) => // don't indiscriminately change existing owners! (see e.g., pos/t3440, pos/t3534, pos/unapplyContexts2)
- // println("def: "+ (d, d.symbol.ownerChain, currentOwner.ownerChain))
+ // patmatDebug("def: "+ (d, d.symbol.ownerChain, currentOwner.ownerChain))
if(d.symbol.isLazy) { // for lazy val's accessor -- is there no tree??
assert(d.symbol.lazyAccessor != NoSymbol && d.symbol.lazyAccessor.owner == d.symbol.owner, d.symbol.lazyAccessor)
d.symbol.lazyAccessor.owner = currentOwner
@@ -1160,16 +1180,16 @@ trait PatternMatching extends Transform with TypingTransformers with ast.TreeDSL
d.symbol.owner = currentOwner
// case _ if (t.symbol != NoSymbol) && (t.symbol ne null) =>
- // println("untouched "+ (t, t.getClass, t.symbol.ownerChain, currentOwner.ownerChain))
+ // patmatDebug("untouched "+ (t, t.getClass, t.symbol.ownerChain, currentOwner.ownerChain))
case _ =>
}
super.traverse(t)
}
// override def apply
- // println("before fixerupper: "+ xTree)
+ // patmatDebug("before fixerupper: "+ xTree)
// currentRun.trackerFactory.snapshot()
- // println("after fixerupper")
+ // patmatDebug("after fixerupper")
// currentRun.trackerFactory.snapshot()
}
}
@@ -1234,7 +1254,7 @@ trait PatternMatching extends Transform with TypingTransformers with ast.TreeDSL
def _asInstanceOf(t: Tree, tp: Type, force: Boolean = false): Tree = if (!force && (t.tpe ne NoType) && t.isTyped && typesConform(t.tpe, tp)) t else mkCast(t, tp)
def _asInstanceOf(b: Symbol, tp: Type): Tree = if (typesConform(b.info, tp)) REF(b) else mkCast(REF(b), tp)
def _isInstanceOf(b: Symbol, tp: Type): Tree = gen.mkIsInstanceOf(REF(b), tp.withoutAnnotations, true, false)
- // if (typesConform(b.info, tpX)) { println("warning: emitted spurious isInstanceOf: "+(b, tp)); TRUE }
+ // if (typesConform(b.info, tpX)) { patmatDebug("warning: emitted spurious isInstanceOf: "+(b, tp)); TRUE }
// duplicated out of frustration with cast generation
def mkZero(tp: Type): Tree = {
@@ -1315,11 +1335,11 @@ trait PatternMatching extends Transform with TypingTransformers with ast.TreeDSL
// def andThen_: (prev: List[Test]): List[Test] =
// prev.filterNot(this <:< _) :+ this
- private val reusedBy = new collection.mutable.HashSet[Test]
+ // private val reusedBy = new collection.mutable.HashSet[Test]
var reuses: Option[Test] = None
def registerReuseBy(later: Test): Unit = {
assert(later.reuses.isEmpty, later.reuses)
- reusedBy += later
+ // reusedBy += later
later.reuses = Some(this)
}
@@ -1414,19 +1434,51 @@ trait PatternMatching extends Transform with TypingTransformers with ast.TreeDSL
// returns (tree, tests), where `tree` will be used to refer to `root` in `tests`
- abstract class TreeMakersToConds(val root: Symbol, val cases: List[List[TreeMaker]]) {
+ abstract class TreeMakersToConds(val root: Symbol) {
+ def discard() = {
+ pointsToBound.clear()
+ trees.clear()
+ normalize = EmptySubstitution
+ accumSubst = EmptySubstitution
+ }
// a variable in this set should never be replaced by a tree that "does not consist of a selection on a variable in this set" (intuitively)
- private val pointsToBound = collection.mutable.HashSet(root)
+ private val pointsToBound = collection.mutable.HashSet(root)
+ private val trees = collection.mutable.HashSet.empty[Tree]
// the substitution that renames variables to variables in pointsToBound
private var normalize: Substitution = EmptySubstitution
// replaces a variable (in pointsToBound) by a selection on another variable in pointsToBound
+ // in the end, instead of having x1, x1.hd, x2, x2.hd, ... flying around,
+ // we want something like x1, x1.hd, x1.hd.tl, x1.hd.tl.hd, so that we can easily recognize when
+ // we're testing the same variable
// TODO check:
// pointsToBound -- accumSubst.from == Set(root) && (accumSubst.from.toSet -- pointsToBound) isEmpty
private var accumSubst: Substitution = EmptySubstitution
- private val trees = new collection.mutable.HashSet[Tree]
+ private def updateSubstitution(subst: Substitution) = {
+ // find part of substitution that replaces bound symbols by new symbols, and reverse that part
+ // so that we don't introduce new aliases for existing symbols, thus keeping the set of bound symbols minimal
+ val (boundSubst, unboundSubst) = (subst.from zip subst.to) partition {
+ case (f, t) =>
+ t.isInstanceOf[Ident] && (t.symbol ne NoSymbol) && pointsToBound(f)
+ }
+ val (boundFrom, boundTo) = boundSubst.unzip
+ val (unboundFrom, unboundTo) = unboundSubst.unzip
+
+ // reverse substitution that would otherwise replace a variable we already encountered by a new variable
+ // NOTE: this forgets the more precise type we have for these later variables, but that's probably okay
+ normalize >>= Substitution(boundTo map (_.symbol), boundFrom map (CODE.REF(_)))
+ // patmatDebug("normalize: "+ normalize)
+
+ val okSubst = Substitution(unboundFrom, unboundTo map (normalize(_))) // it's important substitution does not duplicate trees here -- it helps to keep hash consing simple, anyway
+ pointsToBound ++= ((okSubst.from, okSubst.to).zipped filter { (f, t) => pointsToBound exists (sym => t.exists(_.symbol == sym)) })._1
+ // patmatDebug("pointsToBound: "+ pointsToBound)
+
+ accumSubst >>= okSubst
+ // patmatDebug("accumSubst: "+ accumSubst)
+ }
+
// TODO: improve, e.g., for constants
def sameValue(a: Tree, b: Tree): Boolean = (a eq b) || ((a, b) match {
@@ -1437,7 +1489,7 @@ trait PatternMatching extends Transform with TypingTransformers with ast.TreeDSL
// hashconsing trees (modulo value-equality)
def unique(t: Tree, tpOverride: Type = NoType): Tree =
trees find (a => a.equalsStructure0(t)(sameValue)) match {
- case Some(orig) => orig // println("unique: "+ (t eq orig, orig));
+ case Some(orig) => orig // patmatDebug("unique: "+ (t eq orig, orig));
case _ =>
trees += t
if (tpOverride != NoType) t setType tpOverride
@@ -1454,7 +1506,7 @@ trait PatternMatching extends Transform with TypingTransformers with ast.TreeDSL
// produce the unique tree used to refer to this binder
// the type of the binder passed to the first invocation
// determines the type of the tree that'll be returned for that binder as of then
- def binderToUniqueTree(b: Symbol) =
+ final def binderToUniqueTree(b: Symbol) =
unique(accumSubst(normalize(CODE.REF(b))), b.tpe)
@inline def /\(conds: Iterable[Cond]) = if (conds.isEmpty) Top else conds.reduceLeft(AndCond(_, _))
@@ -1462,23 +1514,32 @@ trait PatternMatching extends Transform with TypingTransformers with ast.TreeDSL
// note that the sequencing of operations is important: must visit in same order as match execution
// binderToUniqueTree uses the type of the first symbol that was encountered as the type for all future binders
- def treeMakerToCond(tm: TreeMaker): Cond = {
+ final protected def treeMakerToCond(tm: TreeMaker, condMaker: CondMaker): Cond = {
updateSubstitution(tm.substitution)
+ condMaker(tm)(treeMakerToCond(_, condMaker))
+ }
+
+ final protected def treeMakerToCondNoSubst(tm: TreeMaker, condMaker: CondMaker): Cond =
+ condMaker(tm)(treeMakerToCondNoSubst(_, condMaker))
+ type CondMaker = TreeMaker => (TreeMaker => Cond) => Cond
+ final def makeCond(tm: TreeMaker)(recurse: TreeMaker => Cond): Cond = {
tm match {
case ttm@TypeTestTreeMaker(prevBinder, testedBinder, pt, _) =>
object condStrategy extends TypeTestTreeMaker.TypeTestCondStrategy {
type Result = Cond
def and(a: Result, b: Result) = AndCond(a, b)
def outerTest(testedBinder: Symbol, expectedTp: Type) = Top // TODO OuterEqCond(testedBinder, expectedType)
- def typeTest(b: Symbol, pt: Type) = TypeCond(binderToUniqueTree(b), uniqueTp(pt))
+ def typeTest(b: Symbol, pt: Type) = { // a type test implies the tested path is non-null (null.isInstanceOf[T] is false for all T)
+ val p = binderToUniqueTree(b); AndCond(NonNullCond(p), TypeCond(p, uniqueTp(pt)))
+ }
def nonNullTest(testedBinder: Symbol) = NonNullCond(binderToUniqueTree(testedBinder))
def equalsTest(pat: Tree, testedBinder: Symbol) = EqualityCond(binderToUniqueTree(testedBinder), unique(pat))
def eqTest(pat: Tree, testedBinder: Symbol) = EqualityCond(binderToUniqueTree(testedBinder), unique(pat)) // TODO: eq, not ==
}
ttm.renderCondition(condStrategy)
case EqualityTestTreeMaker(prevBinder, patTree, _) => EqualityCond(binderToUniqueTree(prevBinder), unique(patTree))
- case AlternativesTreeMaker(_, altss, _) => \/(altss map (alts => /\(alts map treeMakerToCond)))
+ case AlternativesTreeMaker(_, altss, _) => \/(altss map (alts => /\(alts map recurse)))
case ProductExtractorTreeMaker(testedBinder, None, subst) => NonNullCond(binderToUniqueTree(testedBinder))
case ExtractorTreeMaker(_, _, _, _)
| GuardTreeMaker(_)
@@ -1488,47 +1549,24 @@ trait PatternMatching extends Transform with TypingTransformers with ast.TreeDSL
}
}
- private def updateSubstitution(subst: Substitution) = {
- // find part of substitution that replaces bound symbols by new symbols, and reverse that part
- // so that we don't introduce new aliases for existing symbols, thus keeping the set of bound symbols minimal
- val (boundSubst, unboundSubst) = (subst.from zip subst.to) partition {case (f, t) =>
- t.isInstanceOf[Ident] && (t.symbol ne NoSymbol) && pointsToBound(f)
- }
- val (boundFrom, boundTo) = boundSubst.unzip
- val (unboundFrom, unboundTo) = unboundSubst.unzip
-
- // reverse substitution that would otherwise replace a variable we already encountered by a new variable
- // NOTE: this forgets the more precise we have for these later variables, but that's probably okay
- normalize >>= Substitution(boundTo map (_.symbol), boundFrom map (CODE.REF(_)))
- // println("normalize: "+ normalize)
+ final def approximateMatch(cases: List[List[TreeMaker]], condMaker: CondMaker = makeCond): List[List[Test]] = cases.map { _ map (tm => Test(treeMakerToCond(tm, condMaker), tm)) }
- val okSubst = Substitution(unboundFrom, unboundTo map (normalize(_))) // it's important substitution does not duplicate trees here -- it helps to keep hash consing simple, anyway
- pointsToBound ++= ((okSubst.from, okSubst.to).zipped filter { (f, t) => pointsToBound exists (sym => t.exists(_.symbol == sym)) })._1
- // println("pointsToBound: "+ pointsToBound)
-
- accumSubst >>= okSubst
- // println("accumSubst: "+ accumSubst)
- }
-
- def approximateTreeMaker(tm: TreeMaker): Test =
- Test(treeMakerToCond(tm), tm)
-
- def approximateMatch: List[List[Test]] = cases.map { _ map approximateTreeMaker }
+ final def approximateMatchAgain(cases: List[List[TreeMaker]], condMaker: CondMaker = makeCond): List[List[Test]] = cases.map { _ map (tm => Test(treeMakerToCondNoSubst(tm, condMaker), tm)) }
}
def approximateMatch(root: Symbol, cases: List[List[TreeMaker]]): List[List[Test]] = {
- object approximator extends TreeMakersToConds(root, cases)
- approximator.approximateMatch
+ object approximator extends TreeMakersToConds(root)
+ approximator.approximateMatch(cases)
}
def showTreeMakers(cases: List[List[TreeMaker]]) = {
- println("treeMakers:")
- println(alignAcrossRows(cases, ">>"))
+ patmatDebug("treeMakers:")
+ patmatDebug(alignAcrossRows(cases, ">>"))
}
def showTests(testss: List[List[Test]]) = {
- println("tests: ")
- println(alignAcrossRows(testss, "&"))
+ patmatDebug("tests: ")
+ patmatDebug(alignAcrossRows(testss, "&"))
}
}
@@ -1563,18 +1601,33 @@ trait PatternMatching extends Transform with TypingTransformers with ast.TreeDSL
class Prop
case class Eq(p: Var, q: Const) extends Prop
- type Const
+ type Const <: AbsConst
+
+ trait AbsConst {
+ def implies(other: Const): Boolean
+ def excludes(other: Const): Boolean
+ }
+
type Var <: AbsVar
trait AbsVar {
- // if the domain is enumerable, at least one assignment must be true
- def domainEnumerable: Boolean
- def domain: Option[Set[Const]]
+ // indicate we may later require a prop for V = C
+ def registerEquality(c: Const): Unit
+
+ // indicates null is part of the domain
+ def considerNull: Unit
+
+ // compute the domain and return it (call considerNull first!)
+ def domainSyms: Option[Set[Sym]]
// for this var, call it V, turn V = C into the equivalent proposition in boolean logic
+ // registerEquality(c) must have been called prior to this call
+ // in fact, all equalities relevant to this variable must have been registered
def propForEqualsTo(c: Const): Prop
- def equalitySyms: Set[Sym]
+ // populated by registerEquality
+ // once equalitySyms has been called, must not call registerEquality anymore
+ def equalitySyms: List[Sym]
}
// would be nice to statically check whether a prop is equational or pure,
@@ -1586,12 +1639,17 @@ trait PatternMatching extends Transform with TypingTransformers with ast.TreeDSL
case object True extends Prop
case object False extends Prop
- private def nextSymId = {_symId += 1; _symId}; private var _symId = 0
-
// symbols are propositions
case class Sym(val variable: Var, val const: Const) extends Prop {
- override val toString = variable +"="+ const +"#"+ nextSymId
+ private[this] val id = nextSymId
+ override def toString = variable +"="+ const +"#"+ id
}
+ private def nextSymId = {_symId += 1; _symId}; private var _symId = 0
+
+
+ @inline def /\(props: Iterable[Prop]) = if (props.isEmpty) True else props.reduceLeft(And(_, _))
+ @inline def \/(props: Iterable[Prop]) = if (props.isEmpty) False else props.reduceLeft(Or(_, _))
+
trait PropTraverser {
def apply(x: Prop): Unit = x match {
@@ -1605,6 +1663,14 @@ trait PatternMatching extends Transform with TypingTransformers with ast.TreeDSL
def applyConst(x: Const): Unit = {}
}
+ def gatherVariables(p: Prop): Set[Var] = {
+ val vars = new HashSet[Var]()
+ (new PropTraverser {
+ override def applyVar(v: Var) = vars += v
+ })(p)
+ vars.toSet
+ }
+
trait PropMap {
def apply(x: Prop): Prop = x match { // TODO: mapConserve
case And(a, b) => And(apply(a), apply(b))
@@ -1614,287 +1680,670 @@ trait PatternMatching extends Transform with TypingTransformers with ast.TreeDSL
}
}
- // plan: (aka TODO)
+ // convert finite domain propositional logic with subtyping to pure boolean propositional logic
+ // a type test or a value equality test are modelled as a variable being equal to some constant
+ // a variable V may be assigned multiple constants, as long as they do not contradict each other
+ // according to subtyping, e.g., V = ConstantType(1) and V = Int are valid assignments
+ // we rewrite V = C to a fresh boolean symbol, and model what we know about the variable's domain
+ // in a prelude (the equality axioms)
+ // 1. a variable with a closed domain (of a sealed type) must be assigned one of the instantiatable types in its domain
+ // 2. for each variable V in props, and each constant C it is compared to,
+ // compute which assignments imply each other (as in the example above: V = 1 implies V = Int)
+ // and which assignments are mutually exclusive (V = String implies -(V = Int))
+ //
+ // note that this is a conservative approximation: V = Constant(A) and V = Constant(B)
+ // are considered mutually exclusive (and thus both cases are considered reachable in {case A => case B =>}),
+ // even though A may be equal to B (and thus the second case is not "dynamically reachable")
+ //
+ // TODO: for V1 representing x1 and V2 standing for x1.head, encode that
+ // V1 = Nil implies -(V2 = Ci) for all Ci in V2's domain (i.e., it is unassignable)
+ def removeVarEq(props: List[Prop], considerNull: Boolean = false): (Prop, List[Prop]) = {
+ val start = startTimer(patmatAnaVarEq)
- // convert finite domain propositional logic to boolean propositional logic
- // for all c in C, there is a corresponding (meta-indexed) proposition Qv(c) that represents V = c,
- // the only property of equality that is encoded is that a variable can at most be equal to one of the c in C:
- // thus, for each distinct c, c', c'',... in C, a clause `not (Qv(c) /\ (Qv(c') \/ ... \/ Qv(c'')))` is added
- def removeVarEq(prop: Prop): Prop = {
val vars = new collection.mutable.HashSet[Var]
- object dropEquational extends PropMap {
+ object gatherEqualities extends PropTraverser {
+ override def apply(p: Prop) = p match {
+ case Eq(v, c) =>
+ vars += v
+ v.registerEquality(c)
+ case _ => super.apply(p)
+ }
+ }
+
+ object rewriteEqualsToProp extends PropMap {
override def apply(p: Prop) = p match {
- case Eq(v, c) => vars += v; v.propForEqualsTo(c)
+ case Eq(v, c) => v.propForEqualsTo(c)
case _ => super.apply(p)
}
}
- // dropEquational populates vars, and for each var in vars. var.equalitySyms
- val pure = dropEquational(prop)
+ props foreach gatherEqualities.apply
+ if (considerNull) vars foreach (_.considerNull)
- // X = C is translated to P_X=C
- // X = C' is translated to P_X=C'
- // need to enforce X cannot simultaneously equal C and C'
- // thus, all equality syms are mutually exclusive
- // X = A, B, C, D --> Not(And(A, B)) /\ Not(And(A, C)) /\ Not(And(A, D))
- // /\ Not(And(B, C)) /\ Not(And(B, D))
- // /\ Not(And(C, D))
- // equivalently Or(Not(A), Not(B)) /\ Or(...)
+ val pure = props map rewriteEqualsToProp.apply
var eqAxioms: Prop = True
- def mutex(a: Sym)(b: Sym) =
- eqAxioms = And(eqAxioms, Or(Not(a), Not(b)))
+ @inline def addAxiom(p: Prop) = eqAxioms = And(eqAxioms, p)
- // at least one assignment from the domain must be true
- def assigned(dom: Set[Sym]) =
- eqAxioms = And(eqAxioms, dom.reduceLeft(Or))
+ case class ExcludedPair(a: Const, b: Const) {
+ override def equals(o: Any) = o match {
+ case ExcludedPair(aa, bb) => (a == aa && b == bb) || (a == bb && b == aa)
+ case _ => false
+ }
+ // make ExcludedPair(a, b).hashCode == ExcludedPair(b, a).hashCode
+ override def hashCode = a.hashCode ^ b.hashCode
+ }
- // println("vars: "+ vars)
+ // patmatDebug("vars: "+ vars)
vars.foreach { v =>
- // is the domain enumerable? then create equality syms for all elements in the domain and
- // assert at least one of them must be selected
- // if v.domain.isEmpty, we must consider the domain to be infinite
- v.domain foreach { dom =>
- // get the Syms for the constants in the domain (making fresh ones for those not encountered in the formula)
- val domProps = dom map {c => v.propForEqualsTo(c)}
- val domSyms = new collection.mutable.HashSet[Sym]()
- object collectSyms extends PropTraverser {
- override def apply(p: Prop) = p match {
- case domSym: Sym => domSyms += domSym
- case _ => super.apply(p)
- }
+ val excludedPair = new collection.mutable.HashSet[ExcludedPair]
+
+ // if v.domainSyms.isEmpty, we must consider the domain to be infinite
+ // otherwise, since the domain fully partitions the type of the value,
+ // exactly one of the types (and whatever it implies, imposed separately) must be chosen
+ // consider X ::= A | B | C, and A => B
+ // coverage is formulated as: A \/ B \/ C and the implications are
+ v.domainSyms foreach { dsyms => addAxiom(\/(dsyms)) }
+
+ val syms = v.equalitySyms
+ // patmatDebug("eqSyms "+(v, syms))
+ syms foreach { sym =>
+ // if we've already excluded the pair at some point (-A \/ -B), then don't exclude the symmetric one (-B \/ -A)
+ // (nor the positive implications -B \/ A, or -A \/ B, which would entail the equality axioms falsifying the whole formula)
+ val todo = syms filterNot (b => (b.const == sym.const) || excludedPair(ExcludedPair(b.const, sym.const)))
+ val (excluded, notExcluded) = todo partition (b => sym.const.excludes(b.const))
+ val implied = notExcluded filter (b => sym.const.implies(b.const))
+ // patmatDebug("implications: "+ (sym.const, excluded, implied, syms))
+
+ // when this symbol is true, what must hold...
+ implied foreach (impliedSym => addAxiom(Or(Not(sym), impliedSym)))
+
+ // ... and what must not?
+ excluded foreach {excludedSym =>
+ excludedPair += ExcludedPair(sym.const, excludedSym.const)
+ addAxiom(Or(Not(sym), Not(excludedSym)))
}
- domProps foreach collectSyms.apply
-
- // TODO: an empty domain means involved type tests can never be true --> always non-exhaustive?
- if (domSyms.nonEmpty) assigned(domSyms.toSet)
- }
-
- // recover mutual-exclusivity (a variable can never be assigned two different constants)
- var syms = v.equalitySyms.toList
- while (syms.nonEmpty) {
- syms.tail.foreach(mutex(syms.head))
- syms = syms.tail
}
}
- // println("eqAxioms:\n"+ cnfString(conjunctiveNormalForm(negationNormalForm(eqAxioms))))
- // println("pure:\n"+ cnfString(conjunctiveNormalForm(negationNormalForm(pure))))
+ // patmatDebug("eqAxioms:\n"+ cnfString(eqFreePropToSolvable(eqAxioms)))
+ // patmatDebug("pure:\n"+ cnfString(eqFreePropToSolvable(pure)))
+
+ stopTimer(patmatAnaVarEq, start)
- And(eqAxioms, pure)
+ (eqAxioms, pure)
}
- // convert propositional logic formula to CNF
- // http://www.dcs.warwick.ac.uk/people/academic/Ranko.Lazic/fsv/fsv6.pdf
- def negationNormalForm(p: Prop): Prop = p match {
- case And(a, b) => And(negationNormalForm(a), negationNormalForm(b))
- case Or(a, b) => Or(negationNormalForm(a), negationNormalForm(b))
- case Not(And(a, b)) => negationNormalForm(Or(Not(a), Not(b)))
- case Not(Or(a, b)) => negationNormalForm(And(Not(a), Not(b)))
- case Not(Not(p)) => negationNormalForm(p)
- case Not(True) => False
- case Not(False) => True
- case True
- | False
- | (_ : Sym)
- | Not(_ : Sym) => p
+
+ type Formula
+ def andFormula(a: Formula, b: Formula): Formula
+
+ class CNFBudgetExceeded extends RuntimeException("CNF budget exceeded")
+
+ // may throw an CNFBudgetExceeded
+ def propToSolvable(p: Prop) = {
+ val (eqAxioms, pure :: Nil) = removeVarEq(List(p), considerNull = false)
+ eqFreePropToSolvable(And(eqAxioms, pure))
}
+ def eqFreePropToSolvable(p: Prop): Formula
+ def cnfString(f: Formula): String
+
+ type Model = Map[Sym, Boolean]
+ val EmptyModel: Model
+ val NoModel: Model
+
+ def findModelFor(f: Formula): Model
+ def findAllModelsFor(f: Formula): List[Model]
+ }
+
+ trait CNF extends Logic {
// CNF: a formula is a conjunction of clauses
- type Formula = List[Clause] ; def formula(c: Clause*): Formula = c.toList
+ type Formula = Array[Clause]
+ def formula(c: Clause*): Formula = c.toArray
+ def andFormula(a: Formula, b: Formula): Formula = a ++ b
// a clause is a disjunction of distinct literals
- type Clause = Set[Lit] ; def clause(l: Lit*): Clause = l.toSet
+ type Clause = Set[Lit]
+ def clause(l: Lit*): Clause = l.toSet
+ @inline private def merge(a: Clause, b: Clause) = a ++ b
+
+ type Lit
+ def Lit(sym: Sym, pos: Boolean = true): Lit
+
+ // throws an CNFBudgetExceeded when the prop results in a CNF that's too big
+ def eqFreePropToSolvable(p: Prop): Formula = {
+ // TODO: for now, reusing the normalization from DPLL
+ def negationNormalForm(p: Prop): Prop = p match {
+ case And(a, b) => And(negationNormalForm(a), negationNormalForm(b))
+ case Or(a, b) => Or(negationNormalForm(a), negationNormalForm(b))
+ case Not(And(a, b)) => negationNormalForm(Or(Not(a), Not(b)))
+ case Not(Or(a, b)) => negationNormalForm(And(Not(a), Not(b)))
+ case Not(Not(p)) => negationNormalForm(p)
+ case Not(True) => False
+ case Not(False) => True
+ case True
+ | False
+ | (_ : Sym)
+ | Not(_ : Sym) => p
+ }
+
+ val TrueF = formula()
+ val FalseF = formula(clause())
+ def lit(s: Sym) = formula(clause(Lit(s)))
+ def negLit(s: Sym) = formula(clause(Lit(s, false)))
+
+ def conjunctiveNormalForm(p: Prop, budget: Int = 256): Formula = {
+ def distribute(a: Formula, b: Formula, budget: Int): Formula =
+ if (budget <= 0) throw new CNFBudgetExceeded
+ else
+ (a, b) match {
+ // true \/ _ = true
+ // _ \/ true = true
+ case (trueA, trueB) if trueA.size == 0 || trueB.size == 0 => TrueF
+ // lit \/ lit
+ case (a, b) if a.size == 1 && b.size == 1 => formula(merge(a(0), b(0)))
+ // (c1 /\ ... /\ cn) \/ d = ((c1 \/ d) /\ ... /\ (cn \/ d))
+ // d \/ (c1 /\ ... /\ cn) = ((d \/ c1) /\ ... /\ (d \/ cn))
+ case (cs, ds) =>
+ val (big, small) = if (cs.size > ds.size) (cs, ds) else (ds, cs)
+ big flatMap (c => distribute(formula(c), small, budget - (big.size*small.size)))
+ }
- // a literal is a (possibly negated) variable
- case class Lit(sym: Sym, pos: Boolean = true) {
- override def toString = if (!pos) "-"+ sym.toString else sym.toString
- def unary_- = Lit(sym, !pos)
+ if (budget <= 0) throw new CNFBudgetExceeded
+
+ p match {
+ case True => TrueF
+ case False => FalseF
+ case s: Sym => lit(s)
+ case Not(s: Sym) => negLit(s)
+ case And(a, b) =>
+ val cnfA = conjunctiveNormalForm(a, budget - 1)
+ val cnfB = conjunctiveNormalForm(b, budget - cnfA.size)
+ cnfA ++ cnfB
+ case Or(a, b) =>
+ val cnfA = conjunctiveNormalForm(a)
+ val cnfB = conjunctiveNormalForm(b)
+ distribute(cnfA, cnfB, budget - (cnfA.size + cnfB.size))
+ }
+ }
+
+ val start = startTimer(patmatCNF)
+ val res = conjunctiveNormalForm(negationNormalForm(p))
+ stopTimer(patmatCNF, start)
+ patmatCNFSizes(res.size) += 1
+
+// patmatDebug("cnf for\n"+ p +"\nis:\n"+cnfString(res))
+ res
}
- val TrueF = formula()
- val FalseF = formula(clause())
- def lit(s: Sym) = formula(clause(Lit(s)))
- def negLit(s: Sym) = formula(clause(Lit(s, false)))
+ }
- def conjunctiveNormalForm(p: Prop): Formula = {
- def distribute(a: Formula, b: Formula): Formula = (a, b) match {
- // true \/ _ = true
- case (TrueF, _) => TrueF
- // _ \/ true = true
- case (_, TrueF) => TrueF
- // lit \/ lit
- case (List(a), List(b)) => formula(a ++ b)
- // (c1 /\ ... /\ cn) \/ d = ((c1 \/ d) /\ ... /\ (cn \/ d))
- case (cs, d) if cs.tail nonEmpty => cs flatMap (c => distribute(formula(c), d))
- // d \/ (c1 /\ ... /\ cn) = ((d \/ c1) /\ ... /\ (d \/ cn))
- case (d, cs) if cs.tail nonEmpty => cs flatMap (c => distribute(d, formula(c)))
+ trait DPLLSolver extends CNF {
+ // a literal is a (possibly negated) variable
+ def Lit(sym: Sym, pos: Boolean = true) = new Lit(sym, pos)
+ class Lit(val sym: Sym, val pos: Boolean) {
+ override def toString = if (!pos) "-"+ sym.toString else sym.toString
+ override def equals(o: Any) = o match {
+ case o: Lit => (o.sym == sym) && (o.pos == pos)
+ case _ => false
}
+ override def hashCode = sym.hashCode + pos.hashCode
- p match {
- case True => TrueF
- case False => FalseF
- case s: Sym => lit(s)
- case Not(s: Sym) => negLit(s)
- case And(a, b) => conjunctiveNormalForm(a) ++ conjunctiveNormalForm(b)
- case Or(a, b) => distribute(conjunctiveNormalForm(a), conjunctiveNormalForm(b))
- }
+ def unary_- = Lit(sym, !pos)
}
- def normalize(p: Prop) = conjunctiveNormalForm(negationNormalForm(removeVarEq(p)))
def cnfString(f: Formula) = alignAcrossRows(f map (_.toList) toList, "\\/", " /\\\n")
// adapted from http://lara.epfl.ch/w/sav10:simple_sat_solver (original by Hossein Hojjat)
- type Model = Map[Sym, Boolean]
val EmptyModel = Map.empty[Sym, Boolean]
+ val NoModel: Model = null
// returns all solutions, if any (TODO: better infinite recursion backstop -- detect fixpoint??)
- def fullDPLL(f: Formula): List[Model] = {
+ def findAllModelsFor(f: Formula): List[Model] = {
+ val vars: Set[Sym] = f.flatMap(_ collect {case l: Lit => l.sym}).toSet
+ // patmatDebug("vars "+ vars)
// the negation of a model -(S1=True/False /\ ... /\ SN=True/False) = clause(S1=False/True, ...., SN=False/True)
def negateModel(m: Model) = clause(m.toSeq.map{ case (sym, pos) => Lit(sym, !pos) } : _*)
- def findAllModels(f: Formula, models: List[Model], recursionDepthAllowed: Int = 20): List[Model]=
+ def findAllModels(f: Formula, models: List[Model], recursionDepthAllowed: Int = 10): List[Model]=
if (recursionDepthAllowed == 0) models
else {
- val (ok, model) = DPLL(f)
+ // patmatDebug("solving\n"+ cnfString(f))
+ val model = findModelFor(f)
// if we found a solution, conjunct the formula with the model's negation and recurse
- if (ok) findAllModels(f :+ negateModel(model), model :: models, recursionDepthAllowed - 1)
+ if (model ne NoModel) {
+ val unassigned = (vars -- model.keySet).toList
+ // patmatDebug("unassigned "+ unassigned +" in "+ model)
+ def force(lit: Lit) = {
+ val model = withLit(findModelFor(dropUnit(f, lit)), lit)
+ if (model ne NoModel) List(model)
+ else Nil
+ }
+ val forced = unassigned flatMap { s =>
+ force(Lit(s, true)) ++ force(Lit(s, false))
+ }
+ // patmatDebug("forced "+ forced)
+ val negated = negateModel(model)
+ findAllModels(f :+ negated, model :: (forced ++ models), recursionDepthAllowed - 1)
+ }
else models
}
findAllModels(f, Nil)
}
- def DPLL(f: Formula): (Boolean, Model) = {
- @inline def withLit(res: (Boolean, Model), l: Lit) = (res._1, res._2 + (l.sym -> l.pos))
- @inline def orElse(a: (Boolean, Model), b: => (Boolean, Model)) = if (a._1) a else b
-
-// println("dpll\n"+ cnfString(f))
-
- if (f isEmpty) (true, EmptyModel)
- else if(f exists (_.isEmpty)) (false, EmptyModel)
- else f.find(_.size == 1) map { unitClause =>
- val unitLit = unitClause.head
-// println("unit: "+ unitLit)
- val negated = -unitLit
- // drop entire clauses that are trivially true
- // (i.e., disjunctions that contain the literal we're making true in the returned model),
- // and simplify clauses by dropping the negation of the literal we're making true
- // (since False \/ X == X)
- val simplified = f.filterNot(_.contains(unitLit)).map(_ - negated)
- withLit(DPLL(simplified), unitLit)
- } getOrElse {
- // partition symbols according to whether they appear in positive and/or negative literals
- val pos = new HashSet[Sym]()
- val neg = new HashSet[Sym]()
- f.foreach{_.foreach{ lit =>
- if (lit.pos) pos += lit.sym else neg += lit.sym
- }}
- // appearing in both positive and negative
- val impures = pos intersect neg
- // appearing only in either positive/negative positions
- val pures = (pos ++ neg) -- impures
-
- if (pures nonEmpty) {
- val pureSym = pures.head
- // turn it back into a literal
- // (since equality on literals is in terms of equality
- // of the underlying symbol and its positivity, simply construct a new Lit)
- val pureLit = Lit(pureSym, pos(pureSym))
-// println("pure: "+ pureLit +" pures: "+ pures +" impures: "+ impures)
- val simplified = f.filterNot(_.contains(pureLit))
- withLit(DPLL(simplified), pureLit)
- } else {
- val split = f.head.head
-// println("split: "+ split)
- orElse(DPLL(f :+ clause(split)), DPLL(f :+ clause(-split)))
+ @inline private def withLit(res: Model, l: Lit): Model = if (res eq NoModel) NoModel else res + (l.sym -> l.pos)
+ @inline private def dropUnit(f: Formula, unitLit: Lit) = {
+ val negated = -unitLit
+ // drop entire clauses that are trivially true
+ // (i.e., disjunctions that contain the literal we're making true in the returned model),
+ // and simplify clauses by dropping the negation of the literal we're making true
+ // (since False \/ X == X)
+ f.filterNot(_.contains(unitLit)).map(_ - negated)
+ }
+
+ def findModelFor(f: Formula): Model = {
+ @inline def orElse(a: Model, b: => Model) = if (a ne NoModel) a else b
+
+ // patmatDebug("dpll\n"+ cnfString(f))
+
+ val start = startTimer(patmatAnaDPLL)
+
+ val satisfiableWithModel: Model =
+ if (f isEmpty) EmptyModel
+ else if(f exists (_.isEmpty)) NoModel
+ else f.find(_.size == 1) match {
+ case Some(unitClause) =>
+ val unitLit = unitClause.head
+ // patmatDebug("unit: "+ unitLit)
+ withLit(findModelFor(dropUnit(f, unitLit)), unitLit)
+ case _ =>
+ // partition symbols according to whether they appear in positive and/or negative literals
+ val pos = new HashSet[Sym]()
+ val neg = new HashSet[Sym]()
+ f.foreach{_.foreach{ lit =>
+ if (lit.pos) pos += lit.sym else neg += lit.sym
+ }}
+ // appearing in both positive and negative
+ val impures = pos intersect neg
+ // appearing only in either positive/negative positions
+ val pures = (pos ++ neg) -- impures
+
+ if (pures nonEmpty) {
+ val pureSym = pures.head
+ // turn it back into a literal
+ // (since equality on literals is in terms of equality
+ // of the underlying symbol and its positivity, simply construct a new Lit)
+ val pureLit = Lit(pureSym, pos(pureSym))
+ // patmatDebug("pure: "+ pureLit +" pures: "+ pures +" impures: "+ impures)
+ val simplified = f.filterNot(_.contains(pureLit))
+ withLit(findModelFor(simplified), pureLit)
+ } else {
+ val split = f.head.head
+ // patmatDebug("split: "+ split)
+ orElse(findModelFor(f :+ clause(split)), findModelFor(f :+ clause(-split)))
+ }
}
- }
+
+ stopTimer(patmatAnaDPLL, start)
+
+ satisfiableWithModel
}
}
+
/**
* Represent a match as a formula in propositional logic that encodes whether the match matches (abstractly: we only consider types)
*
*/
trait SymbolicMatchAnalysis extends TreeMakerApproximation with Logic { self: CodegenCore =>
+ def prepareNewAnalysis() = { Var.resetUniques(); Const.resetUniques() }
+
object Var {
private var _nextId = 0
def nextId = {_nextId += 1; _nextId}
+ def resetUniques() = {_nextId = 0; uniques.clear()}
private val uniques = new collection.mutable.HashMap[Tree, Var]
def apply(x: Tree): Var = uniques getOrElseUpdate(x, new Var(x, x.tpe))
}
class Var(val path: Tree, fullTp: Type, checked: Boolean = true) extends AbsVar {
+ private[this] val id: Int = Var.nextId
+
+ // private[this] var canModify: Option[Array[StackTraceElement]] = None
+ @inline private[this] def ensureCanModify = {} //if (canModify.nonEmpty) patmatDebug("BUG!"+ this +" modified after having been observed: "+ canModify.get.mkString("\n"))
+
+ @inline private[this] def observed = {} //canModify = Some(Thread.currentThread.getStackTrace)
+
+ // don't access until all potential equalities have been registered using registerEquality
+ private[this] val symForEqualsTo = new collection.mutable.HashMap[Const, Sym]
+
// when looking at the domain, we only care about types we can check at run time
val domainTp: Type = checkableType(fullTp)
+ private[this] var _considerNull = false
+ def considerNull: Unit = { ensureCanModify; if (NullTp <:< domainTp) _considerNull = true }
+
// case None => domain is unknown,
// case Some(List(tps: _*)) => domain is exactly tps
// we enumerate the subtypes of the full type, as that allows us to filter out more types statically,
// once we go to run-time checks (on Const's), convert them to checkable types
// TODO: there seems to be bug for singleton domains (variable does not show up in model)
- val domain = if (checked) enumerateSubtypes(fullTp).map(_.map(Const).toSet) else None
-
- def describe = toString + ": "+ fullTp + domain.map(_.map(_.tp).mkString(" ::= ", " | ", "")).getOrElse(" ::= ??") +" // = "+ path
- def domainEnumerable = domain.nonEmpty
+ lazy val domain: Option[Set[Const]] =
+ if (!checked) None
+ else {
+ val subConsts = enumerateSubtypes(fullTp).map{ tps =>
+ tps.toSet[Type].map{ tp =>
+ val domainC = TypeConst(tp)
+ registerEquality(domainC)
+ domainC
+ }
+ }
- private val domMap = new collection.mutable.HashMap[Const, Sym]
- private def symForEqualsTo(c: Const) = {
- domMap getOrElseUpdate(c, {
- // println("creating symbol for equality "+ this +" = "+ c)
- Sym(this, c)
- })
- }
+ val allConsts =
+ if (! _considerNull) subConsts
+ else {
+ registerEquality(NullConst)
+ subConsts map (_ + NullConst)
+ }
- // for this var, call it V, turn V = C into the equivalent proposition in boolean logic
- // over all executions of this method on the same Var object,
- def propForEqualsTo(c: Const): Prop = {
- domain match {
- case None => symForEqualsTo(c)
- case Some(domainConsts) =>
- val domainTps = domainConsts map (_.tp)
- val checkedTp = c.tp
- // find all the domain types that could make the type test true
- // if the checked type is a supertype of the lub of the domain,
- // we'll end up \/'ing the whole domain together,
- // but must not simplify to True, as the type test may also fail...
- val matches = domainTps.filter(_ <:< checkedTp).map{ tp => symForEqualsTo(Const(tp)) }
- // println("type-equals-prop for "+ this +" = "+ c +": "+ (checkedTp, domainTp, domainTps) +" matches: "+ matches)
-
- if (matches isEmpty) False else matches.reduceLeft(Or)
+ observed; allConsts
}
- }
- def equalitySyms: Set[Sym] = domMap.values.toSet
+ // accessing after calling considerNull will result in inconsistencies
+ lazy val domainSyms: Option[Set[Sym]] = domain map { _ map symForEqualsTo }
- private[this] val id: Int = Var.nextId
+
+ // populate equalitySyms
+ // don't care about the result, but want only one fresh symbol per distinct constant c
+ def registerEquality(c: Const): Unit = {ensureCanModify; symForEqualsTo getOrElseUpdate(c, Sym(this, c))}
+
+ // don't access until all potential equalities have been registered using registerEquality
+ lazy val equalitySyms = {observed; symForEqualsTo.values.toList}
+
+ // return the symbol that represents this variable being equal to the constant `c`, if it exists, otherwise False (for robustness)
+ // (registerEquality(c) must have been called prior, either when constructing the domain or from outside)
+ def propForEqualsTo(c: Const): Prop = {observed; symForEqualsTo.getOrElse(c, False)}
+
+
+ // don't call until all equalities have been registered and considerNull has been called (if needed)
+ def describe = toString + ": " + fullTp + domain.map(_.mkString(" ::= ", " | ", "// "+ symForEqualsTo.keys)).getOrElse(symForEqualsTo.keys.mkString(" ::= ", " | ", " | ...")) + " // = " + path
override def toString = "V"+ id
}
+
// all our variables range over types
// a literal constant becomes ConstantType(Constant(v)) when the type allows it (roughly, anyval + string + null)
// equality between variables: SingleType(x) (note that pattern variables cannot relate to each other -- it's always patternVar == nonPatternVar)
- case class Const(tp: Type) {
- override def toString = tp.toString
+ object Const {
+ def resetUniques() = {_nextTypeId = 0; _nextValueId = 0; uniques.clear()} // patmatDebug("RESET")
+
+ private var _nextTypeId = 0
+ def nextTypeId = {_nextTypeId += 1; _nextTypeId}
+
+ private var _nextValueId = 0
+ def nextValueId = {_nextValueId += 1; _nextValueId}
+
+ private val uniques = new collection.mutable.HashMap[Type, Const]
+ private[SymbolicMatchAnalysis] def unique(tp: Type, mkFresh: => Const): Const =
+ uniques.get(tp).getOrElse(
+ uniques.find {case (oldTp, oldC) => oldTp =:= tp} match {
+ case Some((_, c)) => c
+ case _ =>
+ val fresh = mkFresh
+ uniques(tp) = fresh
+ fresh
+ })
+ }
- def toValueString = tp match {
- case ConstantType(c) => c.escapedStringValue
- case _ => tp.toString
+ sealed abstract class Const extends AbsConst {
+ protected def tp: Type
+ protected def wideTp: Type
+
+ def isAny = wideTp.typeSymbol == AnyClass
+
+ final def implies(other: Const): Boolean = {
+ val r = (this, other) match {
+ case (_: ValueConst, _: ValueConst) => this == other // hashconsed
+ case (_: ValueConst, _: TypeConst) => tp <:< other.tp
+ case (_: TypeConst, _) => tp <:< other.tp
+ case _ => false
+ }
+ // if(r) patmatDebug("implies : "+(this, other))
+ // else patmatDebug("NOT implies: "+(this, other))
+ r
+ }
+
+ // does V = C preclude V having value `other`? V = null is an exclusive assignment,
+ // but V = 1 does not preclude V = Int, or V = Any
+ final def excludes(other: Const): Boolean = {
+ val r = (this, other) match {
+ case (_, NullConst) => true
+ case (NullConst, _) => true
+ // this causes false negative for unreachability, but that's ok:
+ // example: val X = 1; val Y = 1; (2: Int) match { case X => case Y => /* considered reachable */ }
+ case (_: ValueConst, _: ValueConst) => this != other
+ case (_: ValueConst, _: TypeConst) => !((tp <:< other.tp) || (other.tp <:< wideTp))
+ case (_: TypeConst, _: ValueConst) => !((other.tp <:< tp) || (tp <:< other.wideTp))
+ case (_: TypeConst, _: TypeConst) => !((tp <:< other.tp) || (other.tp <:< tp))
+ case _ => false
+ }
+ // if(r) patmatDebug("excludes : "+(this, other))
+ // else patmatDebug("NOT excludes: "+(this, other))
+ r
}
+
+ // note: use reference equality on Const since they're hash-consed (doing type equality all the time is too expensive)
+ // the equals inherited from AnyRef does just this
+ }
+
+
+ object TypeConst {
+ def apply(tp: Type) = {
+ if (tp =:= NullTp) NullConst
+ else if (tp.isInstanceOf[SingletonType]) ValueConst.fromType(tp)
+ else Const.unique(tp, new TypeConst(tp))
+ }
+ def unapply(c: TypeConst): Some[Type] = Some(c.tp)
+ }
+
+ // corresponds to a type test that does not imply any value-equality (well, except for outer checks, which we don't model yet)
+ sealed class TypeConst(val tp: Type) extends Const {
+ assert(!(tp =:= NullTp))
+ private[this] val id: Int = Const.nextTypeId
+
+ val wideTp = tp.widen
+
+ override def toString = tp.toString //+"#"+ id
+ }
+
+ // p is a unique type or a constant value
+ object ValueConst {
+ def fromType(tp: Type) = {
+ assert(tp.isInstanceOf[SingletonType])
+ val toString = tp match {
+ case ConstantType(c) => c.escapedStringValue
+ case _ => tp.toString
+ }
+ Const.unique(tp, new ValueConst(tp, tp.widen, toString))
+ }
+ def apply(p: Tree) = {
+ val tp = p.tpe.normalize
+ if (tp =:= NullTp) NullConst
+ else {
+ val wideTp = {
+ if (p.hasSymbol && p.symbol.isStable) tp.asSeenFrom(tp.prefix, p.symbol.owner).widen
+ else tp.widen
+ }
+
+ val narrowTp =
+ if (tp.isInstanceOf[SingletonType]) tp
+ else p match {
+ case Literal(c) =>
+ if (c.tpe.typeSymbol == UnitClass) c.tpe
+ else ConstantType(c)
+ case p if p.symbol.isStable =>
+ singleType(tp.prefix, p.symbol)
+ case x =>
+ // TODO: better type
+ x.tpe.narrow
+ }
+
+ val toString =
+ if (p.hasSymbol && p.symbol.isStable) p.symbol.name.toString // tp.toString
+ else p.toString //+"#"+ id
+
+ Const.unique(narrowTp, new ValueConst(narrowTp, checkableType(wideTp), toString)) // must make wide type checkable so that it is comparable to types from TypeConst
+ }
+ }
+ }
+ sealed class ValueConst(val tp: Type, val wideTp: Type, override val toString: String) extends Const {
+ // patmatDebug("VC"+(tp, wideTp, toString))
+ assert(!(tp =:= NullTp))
+ private[this] val id: Int = Const.nextValueId
+ }
+
+ lazy val NullTp = ConstantType(Constant(null))
+ case object NullConst extends Const {
+ protected def tp = NullTp
+ protected def wideTp = NullTp
+
+ def isValue = true
+ override def toString = "null"
+ }
+
+
+ // turns a case (represented as a list of abstract tests)
+ // into a proposition that is satisfiable if the case may match
+ def symbolicCase(tests: List[Test], modelNull: Boolean = false): Prop = {
+ def symbolic(t: Cond): Prop = t match {
+ case AndCond(a, b) => And(symbolic(a), symbolic(b))
+ case OrCond(a, b) => Or(symbolic(a), symbolic(b))
+ case Top => True
+ case Havoc => False
+ case TypeCond(p, pt) => Eq(Var(p), TypeConst(checkableType(pt)))
+ case EqualityCond(p, q) => Eq(Var(p), ValueConst(q))
+ case NonNullCond(p) => if (!modelNull) True else Not(Eq(Var(p), NullConst))
+ }
+
+ val testsBeforeBody = tests.takeWhile(t => !t.treeMaker.isInstanceOf[BodyTreeMaker])
+ /\(testsBeforeBody.map(t => symbolic(t.cond)))
}
+ // TODO: model dependencies between variables: if V1 corresponds to (x: List[_]) and V2 is (x.hd), V2 cannot be assigned when V1 = null or V1 = Nil
+ // right now hackily implement this by pruning counter-examples
+ // unreachability would also benefit from a more faithful representation
+
+ // reachability (dead code)
+
+ // computes the first 0-based case index that is unreachable (if any)
+ // a case is unreachable if it implies its preceding cases
+ // call C the formula that is satisfiable if the considered case matches
+ // call P the formula that is satisfiable if the cases preceding it match
+ // the case is reachable if there is a model for -P /\ C,
+ // thus, the case is unreachable if there is no model for -(-P /\ C),
+ // or, equivalently, P \/ -C, or C => P
+ def unreachableCase(prevBinder: Symbol, cases: List[List[TreeMaker]], pt: Type): Option[Int] = {
+ // customize TreeMakersToConds (which turns a tree of tree makers into a more abstract DAG of tests)
+ // when approximating the current case (which we hope is reachable), be optimistic about the unknowns
+ object reachabilityApproximation extends TreeMakersToConds(prevBinder) {
+ def makeCondOptimistic(tm: TreeMaker)(recurse: TreeMaker => Cond): Cond = tm match {
+ // for unreachability, let's assume a guard always matches (unless we statically determined otherwise)
+ // otherwise, a guarded case would be considered unreachable
+ case GuardTreeMaker(guard) =>
+ guard.tpe match {
+ case ConstantType(Constant(false)) => Havoc // not the best name; however, symbolically, 'Havoc' becomes 'False'
+ case _ => Top
+ }
+ // similar to a guard, user-defined extractors should not cause us to freak out
+ // if we're not 100% sure it does not match (i.e., its result type is None or Constant(false) -- TODO),
+ // let's stay optimistic and assume it does
+ case ExtractorTreeMaker(_, _, _, _)
+ | ProductExtractorTreeMaker(_, Some(_), _) => Top
+ // TODO: consider length-checks
+ case _ =>
+ makeCond(tm)(recurse)
+ }
+
+ // be pessimistic when approximating the prefix of the current case
+ // we hope the prefix fails so that we might get to the current case, which we hope is not dead
+ def makeCondPessimistic(tm: TreeMaker)(recurse: TreeMaker => Cond): Cond = makeCond(tm)(recurse)
+ }
+
+ val start = startTimer(patmatAnaReach)
+
+ // use the same approximator so we share variables,
+ // but need different conditions depending on whether we're conservatively looking for failure or success
+ val testCasesOk = reachabilityApproximation.approximateMatch(cases, reachabilityApproximation.makeCondOptimistic)
+ val testCasesFail = reachabilityApproximation.approximateMatchAgain(cases, reachabilityApproximation.makeCondPessimistic)
+
+ reachabilityApproximation.discard()
+ prepareNewAnalysis()
+
+ val propsCasesOk = testCasesOk map (t => symbolicCase(t, modelNull = true))
+ val propsCasesFail = testCasesFail map (t => Not(symbolicCase(t, modelNull = true)))
+ val (eqAxiomsFail, symbolicCasesFail) = removeVarEq(propsCasesFail, considerNull = true)
+ val (eqAxiomsOk, symbolicCasesOk) = removeVarEq(propsCasesOk, considerNull = true)
+
+ try {
+ // most of the time eqAxiomsFail == eqAxiomsOk, but the different approximations might cause different variables to disapper in general
+ val eqAxiomsCNF =
+ if (eqAxiomsFail == eqAxiomsOk) eqFreePropToSolvable(eqAxiomsFail)
+ else eqFreePropToSolvable(And(eqAxiomsFail, eqAxiomsOk))
+
+ var prefix = eqAxiomsCNF
+ var prefixRest = symbolicCasesFail
+ var current = symbolicCasesOk
+ var reachable = true
+ var caseIndex = 0
+
+ // patmatDebug("reachability, vars:\n"+ ((propsCasesFail flatMap gatherVariables) map (_.describe) mkString ("\n")))
+ // patmatDebug("equality axioms:\n"+ cnfString(eqAxiomsCNF))
+
+ // invariant (prefixRest.length == current.length) && (prefix.reverse ++ prefixRest == symbolicCasesFail)
+ // termination: prefixRest.length decreases by 1
+ while (prefixRest.nonEmpty && reachable) {
+ val prefHead = prefixRest.head
+ caseIndex += 1
+ prefixRest = prefixRest.tail
+ if (prefixRest.isEmpty) reachable = true
+ else {
+ prefix = andFormula(eqFreePropToSolvable(prefHead), prefix)
+ current = current.tail
+ val model = findModelFor(andFormula(eqFreePropToSolvable(current.head), prefix))
+
+ // patmatDebug("trying to reach:\n"+ cnfString(current.head) +"\nunder prefix:\n"+ cnfString(prefix))
+ // if (ok) patmatDebug("reached: "+ modelString(model))
+
+ reachable = model ne NoModel
+ }
+ }
+
+ stopTimer(patmatAnaReach, start)
+
+ if (reachable) None else Some(caseIndex)
+ } catch {
+ case e : CNFBudgetExceeded =>
+// debugWarn(util.Position.formatMessage(prevBinder.pos, "Cannot check match for reachability", false))
+// e.printStackTrace()
+ None // CNF budget exceeded
+ }
+ }
+
+ // exhaustivity
+
// make sure it's not a primitive, else (5: Byte) match { case 5 => ... } sees no Byte
// TODO: domain of feasibly enumerable built-in types (enums, char?)
def enumerateSubtypes(tp: Type): Option[List[Type]] =
tp.typeSymbol match {
case BooleanClass =>
- // println("enum bool "+ tp)
+ // patmatDebug("enum bool "+ tp)
Some(List(ConstantType(Constant(true)), ConstantType(Constant(false))))
// TODO case _ if tp.isTupleType => // recurse into component types
case sym if !sym.isSealed || isPrimitiveValueClass(sym) =>
- // println("enum unsealed "+ (tp, sym, sym.isSealed, isPrimitiveValueClass(sym)))
+ // patmatDebug("enum unsealed "+ (tp, sym, sym.isSealed, isPrimitiveValueClass(sym)))
None
case sym =>
val subclasses = (
@@ -1902,7 +2351,7 @@ trait PatternMatching extends Transform with TypingTransformers with ast.TreeDSL
// symbols which are both sealed and abstract need not be covered themselves, because
// all of their children must be and they cannot otherwise be created.
filterNot (x => x.isSealed && x.isAbstractClass && !isPrimitiveValueClass(x)))
- // println("subclasses "+ (sym, subclasses))
+ // patmatDebug("subclasses "+ (sym, subclasses))
val tpApprox = typer.infer.approximateAbstracts(tp)
val pre = tpApprox.prefix
@@ -1914,20 +2363,14 @@ trait PatternMatching extends Transform with TypingTransformers with ast.TreeDSL
// however, must approximate abstract types in
val subTp = appliedType(pre.memberType(sym), sym.typeParams.map(_ => WildcardType))
val subTpApprox = typer.infer.approximateAbstracts(subTp) // TODO: needed?
- // println("subtp"+(subTpApprox <:< tpApprox, subTpApprox, tpApprox))
+ // patmatDebug("subtp"+(subTpApprox <:< tpApprox, subTpApprox, tpApprox))
if (subTpApprox <:< tpApprox) Some(checkableType(subTp))
else None
})
- // println("enum sealed "+ (tp, tpApprox) + " as "+ validSubTypes)
+ // patmatDebug("enum sealed "+ (tp, tpApprox) + " as "+ validSubTypes)
Some(validSubTypes)
}
- def narrowTypeOf(p: Tree) = p match {
- case Literal(c) => ConstantType(c)
- case Ident(_) if p.symbol.isStable => singleType(p.tpe.prefix, p.symbol)
- case x => x.tpe.narrow
- }
-
// approximate a type to the static type that is fully checkable at run time,
// hiding statically known but dynamically uncheckable information using existential quantification
// TODO: this is subject to the availability of TypeTags (since an abstract type with a type tag is checkable at run time)
@@ -1944,7 +2387,7 @@ trait PatternMatching extends Transform with TypingTransformers with ast.TreeDSL
}
}
val res = toCheckable(tp)
- // println("checkable "+(tp, res))
+ // patmatDebug("checkable "+(tp, res))
res
}
@@ -1955,7 +2398,7 @@ trait PatternMatching extends Transform with TypingTransformers with ast.TreeDSL
val checkable = (
(isTupleType(tp) && tupleComponents(tp).exists(tp => !uncheckableType(tp)))
|| enumerateSubtypes(tp).nonEmpty)
- // if (!checkable) println("deemed uncheckable: "+ tp)
+ // if (!checkable) patmatDebug("deemed uncheckable: "+ tp)
!checkable
}
@@ -1966,10 +2409,11 @@ trait PatternMatching extends Transform with TypingTransformers with ast.TreeDSL
// - back off (to avoid crying exhaustive too often) when:
// - there are guards -->
// - there are extractor calls (that we can't secretly/soundly) rewrite
+ val start = startTimer(patmatAnaExhaust)
var backoff = false
- object exhaustivityApproximation extends TreeMakersToConds(prevBinder, cases) {
- override def treeMakerToCond(tm: TreeMaker): Cond = tm match {
- case p@ExtractorTreeMaker(extractor, Some(lenCheck), testedBinder, _) =>
+ object exhaustivityApproximation extends TreeMakersToConds(prevBinder) {
+ def makeCondExhaustivity(tm: TreeMaker)(recurse: TreeMaker => Cond): Cond = tm match {
+ case p @ ExtractorTreeMaker(extractor, Some(lenCheck), testedBinder, _) =>
p.checkedLength match {
// pattern: `List()` (interpret as `Nil`)
// TODO: make it more general List(1, 2) => 1 :: 2 :: Nil
@@ -1977,47 +2421,36 @@ trait PatternMatching extends Transform with TypingTransformers with ast.TreeDSL
EqualityCond(binderToUniqueTree(p.prevBinder), unique(Ident(NilModule) setType NilModule.tpe))
case _ =>
backoff = true
- super.treeMakerToCond(tm)
+ makeCond(tm)(recurse)
}
case ExtractorTreeMaker(_, _, _, _) =>
-// println("backing off due to "+ tm)
+// patmatDebug("backing off due to "+ tm)
backoff = true
- super.treeMakerToCond(tm)
+ makeCond(tm)(recurse)
case GuardTreeMaker(guard) =>
guard.tpe match {
case ConstantType(Constant(true)) => Top
case ConstantType(Constant(false)) => Havoc
case _ =>
-// println("can't statically interpret guard: "+(guard, guard.tpe))
+// patmatDebug("can't statically interpret guard: "+(guard, guard.tpe))
backoff = true
Havoc
}
case _ =>
- super.treeMakerToCond(tm)
+ makeCond(tm)(recurse)
}
}
- def symbolic(t: Cond): Prop = t match {
- case AndCond(a, b) => And(symbolic(a), symbolic(b))
- case OrCond(a, b) => Or(symbolic(a), symbolic(b))
- case Top => True
- case Havoc => False
- case TypeCond(p, pt) => Eq(Var(p), Const(checkableType(pt)))
- case EqualityCond(p, q) => Eq(Var(p), Const(narrowTypeOf(q)))
- case NonNullCond(p) => True // ignoring nullness because it generates too much noise Not(Eq(Var(p), Const(NullClass.tpe)))
- }
+ val tests = exhaustivityApproximation.approximateMatch(cases, exhaustivityApproximation.makeCondExhaustivity)
- def symbolicCase(tests: List[Test]) = {
- val testsBeforeBody = tests.takeWhile(t => !t.treeMaker.isInstanceOf[BodyTreeMaker])
- testsBeforeBody.map(t => symbolic(t.cond)).foldLeft(True: Prop)(And)
- }
+ if (backoff) Nil else {
+ val prevBinderTree = exhaustivityApproximation.binderToUniqueTree(prevBinder)
- val tests = exhaustivityApproximation.approximateMatch
+ exhaustivityApproximation.discard()
+ prepareNewAnalysis()
- if (backoff) Nil else {
- val symbolicCases = tests map symbolicCase
+ val symbolicCases = tests map (symbolicCase(_, modelNull = false))
- val prevBinderTree = exhaustivityApproximation.binderToUniqueTree(prevBinder)
// TODO: null tests generate too much noise, so disabled them -- is there any way to bring them back?
// assuming we're matching on a non-null scrutinee (prevBinder), when does the match fail?
@@ -2030,33 +2463,35 @@ trait PatternMatching extends Transform with TypingTransformers with ast.TreeDSL
// val matchFails = And(symbolic(nonNullScrutineeCond), Not(symbolicCases reduceLeft (Or(_, _))))
// when does the match fail?
- val matchFails = Not(symbolicCases reduceLeft (Or(_, _)))
-
+ val matchFails = Not(\/(symbolicCases))
// debug output:
- // println("analysing:")
+ // patmatDebug("analysing:")
// showTreeMakers(cases)
// showTests(tests)
//
- // def gatherVariables(p: Prop): Set[Var] = {
- // val vars = new HashSet[Var]()
- // (new PropTraverser {
- // override def applyVar(v: Var) = vars += v
- // })(p)
- // vars.toSet
- // }
// val vars = gatherVariables(matchFails)
- // println("\nvars:\n"+ (vars map (_.describe) mkString ("\n")))
+ // patmatDebug("\nvars:\n"+ (vars map (_.describe) mkString ("\n")))
//
- // println("\nmatchFails as CNF:\n"+ cnfString(normalize(matchFails)))
+ // patmatDebug("\nmatchFails as CNF:\n"+ cnfString(propToSolvable(matchFails)))
+
+ try {
+ // find the models (under which the match fails)
+ val matchFailModels = findAllModelsFor(propToSolvable(matchFails))
- // find the models (under which the match fails)
- val matchFailModels = fullDPLL(normalize(matchFails))
+ val scrutVar = Var(prevBinderTree)
+ val counterExamples = matchFailModels.map(modelToCounterExample(scrutVar))
- val scrutVar = Var(prevBinderTree)
- val counterExamples = matchFailModels.map(modelToCounterExample(scrutVar))
+ val pruned = CounterExample.prune(counterExamples).map(_.toString).sorted
- CounterExample.prune(counterExamples).map(_.toString).sorted
+ stopTimer(patmatAnaExhaust, start)
+ pruned
+ } catch {
+ case e : CNFBudgetExceeded =>
+ // patmatDebug(util.Position.formatMessage(prevBinder.pos, "Cannot check match for exhaustivity", false))
+ // e.printStackTrace()
+ Nil // CNF budget exceeded
+ }
}
}
@@ -2072,13 +2507,14 @@ trait PatternMatching extends Transform with TypingTransformers with ast.TreeDSL
protected[SymbolicMatchAnalysis] def flattenConsArgs: List[CounterExample] = Nil
def coveredBy(other: CounterExample): Boolean = this == other || other == WildcardExample
}
- case class ValueExample(c: Const) extends CounterExample { override def toString = c.toValueString }
+ case class ValueExample(c: ValueConst) extends CounterExample { override def toString = c.toString }
case class TypeExample(c: Const) extends CounterExample { override def toString = "(_ : "+ c +")" }
case class NegativeExample(nonTrivialNonEqualTo: List[Const]) extends CounterExample {
+ // require(nonTrivialNonEqualTo.nonEmpty, nonTrivialNonEqualTo)
override def toString = {
val negation =
- if (nonTrivialNonEqualTo.tail.isEmpty) nonTrivialNonEqualTo.head.toValueString
- else nonTrivialNonEqualTo.map(_.toValueString).sorted.mkString("in (", ", ", ")")
+ if (nonTrivialNonEqualTo.tail.isEmpty) nonTrivialNonEqualTo.head.toString
+ else nonTrivialNonEqualTo.map(_.toString).sorted.mkString("in (", ", ", ")")
"<not "+ negation +">"
}
}
@@ -2115,6 +2551,21 @@ trait PatternMatching extends Transform with TypingTransformers with ast.TreeDSL
case object WildcardExample extends CounterExample { override def toString = "_" }
case object NoExample extends CounterExample { override def toString = "??" }
+ @inline def modelToVarAssignment(model: Model): Map[Var, (Seq[Const], Seq[Const])] =
+ model.toSeq.groupBy{f => f match {case (sym, value) => sym.variable} }.mapValues{ xs =>
+ val (trues, falses) = xs.partition(_._2)
+ (trues map (_._1.const), falses map (_._1.const))
+ // should never be more than one value in trues...
+ }
+
+ def varAssignmentString(varAssignment: Map[Var, (Seq[Const], Seq[Const])]) =
+ varAssignment.toSeq.sortBy(_._1.toString).map { case (v, (trues, falses)) =>
+ val assignment = "== "+ (trues mkString("(", ", ", ")")) +" != ("+ (falses mkString(", ")) +")"
+ v +"(="+ v.path +": "+ v.domainTp +") "+ assignment
+ }.mkString("\n")
+
+ def modelString(model: Model) = varAssignmentString(modelToVarAssignment(model))
+
// return constructor call when the model is a true counter example
// (the variables don't take into account type information derived from other variables,
// so, naively, you might try to construct a counter example like _ :: Nil(_ :: _, _ :: _),
@@ -2125,24 +2576,16 @@ trait PatternMatching extends Transform with TypingTransformers with ast.TreeDSL
// x1.tl = ...
// x1.hd.hd = ...
// ...
- val varAssignment = model.toSeq.groupBy{f => f match {case (sym, value) => sym.variable} }.mapValues{ xs =>
- val (trues, falses) = xs.partition(_._2)
- (trues map (_._1.const), falses map (_._1.const))
- // should never be more than one value in trues...
- }
-
- // println("var assignment:\n"+
- // varAssignment.toSeq.sortBy(_._1.toString).map { case (v, (trues, falses)) =>
- // val assignment = "== "+ (trues mkString("(", ", ", ")")) +" != ("+ (falses mkString(", ")) +")"
- // v +"(="+ v.path +": "+ v.domainTp +") "+ assignment
- // }.mkString("\n"))
+ val varAssignment = modelToVarAssignment(model)
+ // patmatDebug("var assignment for model "+ model +":\n"+ varAssignmentString(varAssignment))
// chop a path into a list of symbols
def chop(path: Tree): List[Symbol] = path match {
case Ident(_) => List(path.symbol)
case Select(pre, name) => chop(pre) :+ path.symbol
- case _ => println("don't know how to chop "+ path); Nil
+ case _ => // patmatDebug("don't know how to chop "+ path)
+ Nil
}
// turn the variable assignments into a tree
@@ -2181,7 +2624,9 @@ trait PatternMatching extends Transform with TypingTransformers with ast.TreeDSL
// node in the tree that describes how to construct a counter-example
case class VariableAssignment(variable: Var, equalTo: List[Const], notEqualTo: List[Const], fields: collection.mutable.Map[Symbol, VariableAssignment]) {
- private lazy val ctor = (equalTo match { case List(Const(tp)) => tp case _ => variable.domainTp }).typeSymbol.primaryConstructor
+ // need to prune since the model now incorporates all super types of a constant (needed for reachability)
+ private lazy val prunedEqualTo = equalTo filterNot (subsumed => equalTo.exists(better => (better ne subsumed) && (better implies subsumed)))
+ private lazy val ctor = (prunedEqualTo match { case List(TypeConst(tp)) => tp case _ => variable.domainTp }).typeSymbol.primaryConstructor
private lazy val ctorParams = if (ctor == NoSymbol || ctor.paramss.isEmpty) Nil else ctor.paramss.head
private lazy val cls = if (ctor == NoSymbol) NoSymbol else ctor.owner
private lazy val caseFieldAccs = if (cls == NoSymbol) Nil else cls.caseFieldAccessors
@@ -2190,7 +2635,7 @@ trait PatternMatching extends Transform with TypingTransformers with ast.TreeDSL
def allFieldAssignmentsLegal: Boolean =
(fields.keySet subsetOf caseFieldAccs.toSet) && fields.values.forall(_.allFieldAssignmentsLegal)
- private lazy val nonTrivialNonEqualTo = notEqualTo.filterNot{c => val sym = c.tp.typeSymbol; sym == AnyClass } // sym == NullClass ||
+ private lazy val nonTrivialNonEqualTo = notEqualTo.filterNot{c => c.isAny }
// NoExample if the constructor call is ill-typed
// (thus statically impossible -- can we incorporate this into the formula?)
@@ -2198,17 +2643,17 @@ trait PatternMatching extends Transform with TypingTransformers with ast.TreeDSL
def toCounterExample(beBrief: Boolean = false): CounterExample =
if (!allFieldAssignmentsLegal) NoExample
else {
-// println("describing "+ (variable, equalTo, notEqualTo, fields, cls, allFieldAssignmentsLegal))
- val res = equalTo match {
+ // patmatDebug("describing "+ (variable, equalTo, notEqualTo, fields, cls, allFieldAssignmentsLegal))
+ val res = prunedEqualTo match {
// a definite assignment to a value
- case List(eq@Const(_: ConstantType)) if fields.isEmpty => ValueExample(eq)
+ case List(eq: ValueConst) if fields.isEmpty => ValueExample(eq)
// constructor call
// or we did not gather any information about equality but we have information about the fields
// --> typical example is when the scrutinee is a tuple and all the cases first unwrap that tuple and only then test something interesting
case _ if cls != NoSymbol &&
- ( equalTo.nonEmpty
- || (fields.nonEmpty && !isPrimitiveValueClass(cls) && equalTo.isEmpty && notEqualTo.isEmpty)) =>
+ ( prunedEqualTo.nonEmpty
+ || (fields.nonEmpty && !isPrimitiveValueClass(cls) && prunedEqualTo.isEmpty && notEqualTo.isEmpty)) =>
@inline def args(brevity: Boolean = beBrief) = {
// figure out the constructor arguments from the field assignment
@@ -2235,7 +2680,7 @@ trait PatternMatching extends Transform with TypingTransformers with ast.TreeDSL
// TODO: improve reasoning -- in the mean time, a false negative is better than an annoying false positive
case _ => NoExample
}
-// println("described as: "+ res)
+ // patmatDebug("described as: "+ res)
res
}
@@ -2255,11 +2700,9 @@ trait PatternMatching extends Transform with TypingTransformers with ast.TreeDSL
/** a flow-sensitive, generalised, common sub-expression elimination
* reuse knowledge from performed tests
* the only sub-expressions we consider are the conditions and results of the three tests (type, type&equality, equality)
- * when a sub-expression is share, it is stored in a mutable variable
+ * when a sub-expression is shared, it is stored in a mutable variable
* the variable is floated up so that its scope includes all of the program that shares it
* we generalize sharing to implication, where b reuses a if a => b and priors(a) => priors(b) (the priors of a sub expression form the path through the decision tree)
- *
- * intended to be generalised to exhaustivity/reachability checking
*/
def doCSE(prevBinder: Symbol, cases: List[List[TreeMaker]], pt: Type): List[List[TreeMaker]] = {
val testss = approximateMatch(prevBinder, cases)
@@ -2308,7 +2751,7 @@ trait PatternMatching extends Transform with TypingTransformers with ast.TreeDSL
tested.clear()
tests dropWhile storeDependencies
}
- // println("dependencies: "+ dependencies)
+ // patmatDebug("dependencies: "+ dependencies)
// find longest prefix of tests that reuse a prior test, and whose dependent conditions monotonically increase
// then, collapse these contiguous sequences of reusing tests
@@ -2342,7 +2785,7 @@ trait PatternMatching extends Transform with TypingTransformers with ast.TreeDSL
case _ =>
}
- // println("sharedPrefix: "+ sharedPrefix)
+ // patmatDebug("sharedPrefix: "+ sharedPrefix)
// if the shared prefix contains interesting conditions (!= Top)
// and the last of such interesting shared conditions reuses another treemaker's test
// replace the whole sharedPrefix by a ReusingCondTreeMaker
@@ -2358,7 +2801,7 @@ trait PatternMatching extends Transform with TypingTransformers with ast.TreeDSL
// replace original treemakers that are reused (as determined when computing collapsed),
// by ReusedCondTreeMakers
val reusedMakers = collapsed mapConserve (_ mapConserve reusedOrOrig)
-// println("after CSE:")
+// patmatDebug("after CSE:")
// showTreeMakers(reusedMakers)
reusedMakers
}
@@ -2366,7 +2809,7 @@ trait PatternMatching extends Transform with TypingTransformers with ast.TreeDSL
object ReusedCondTreeMaker {
def apply(orig: CondTreeMaker) = new ReusedCondTreeMaker(orig.prevBinder, orig.nextBinder, orig.cond, orig.res, orig.pos)
}
- class ReusedCondTreeMaker(prevBinder: Symbol, val nextBinder: Symbol, cond: Tree, res: Tree, pos: Position) extends TreeMaker { import CODE._
+ class ReusedCondTreeMaker(prevBinder: Symbol, val nextBinder: Symbol, cond: Tree, res: Tree, val pos: Position) extends TreeMaker { import CODE._
lazy val localSubstitution = Substitution(List(prevBinder), List(CODE.REF(nextBinder)))
lazy val storedCond = freshSym(pos, BooleanClass.tpe, "rc") setFlag MUTABLE
lazy val treesToHoist: List[Tree] = {
@@ -2382,6 +2825,8 @@ trait PatternMatching extends Transform with TypingTransformers with ast.TreeDSL
}
case class ReusingCondTreeMaker(sharedPrefix: List[Test], toReused: TreeMaker => TreeMaker) extends TreeMaker { import CODE._
+ val pos = sharedPrefix.last.treeMaker.pos
+
lazy val localSubstitution = {
// replace binder of each dropped treemaker by corresponding binder bound by the most recent reused treemaker
var mostRecentReusedMaker: ReusedCondTreeMaker = null
@@ -2471,7 +2916,7 @@ trait PatternMatching extends Transform with TypingTransformers with ast.TreeDSL
val substedBody = btm.substitution(body)
CaseDef(Alternative(patterns), EmptyTree, substedBody)
}
- case _ => //println("can't emit switch for "+ makers)
+ case _ => // patmatDebug("can't emit switch for "+ makers)
None //failure (can't translate pattern to a switch)
}
}
@@ -2696,8 +3141,14 @@ trait PatternMatching extends Transform with TypingTransformers with ast.TreeDSL
with DeadCodeElimination
with SwitchEmission
with OptimizedCodegen
- with SymbolicMatchAnalysis { self: TreeMakers =>
+ with SymbolicMatchAnalysis
+ with DPLLSolver { self: TreeMakers =>
override def optimizeCases(prevBinder: Symbol, cases: List[List[TreeMaker]], pt: Type, unchecked: Boolean): (List[List[TreeMaker]], List[Tree]) = {
+ if (!unchecked) {
+ unreachableCase(prevBinder, cases, pt) foreach { caseIndex =>
+ typer.context.unit.warning(cases(caseIndex).last.pos, "unreachable code")
+ }
+ }
val counterExamples = if (unchecked) Nil else exhaustive(prevBinder, cases, pt)
if (counterExamples.nonEmpty) {
val ceString =
diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
index e643a91da7..b0f6e44e88 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
@@ -2237,7 +2237,7 @@ trait Typers extends Modes with Adaptations with Taggings {
// takes untyped sub-trees of a match and type checks them
def typedMatch(selector: Tree, cases: List[CaseDef], mode: Int, pt: Type, tree: Tree = EmptyTree): Match = {
val selector1 = checkDead(typed(selector, EXPRmode | BYVALmode, WildcardType))
- val selectorTp = packCaptured(selector1.tpe.widen)
+ val selectorTp = packCaptured(selector1.tpe.widen).skolemizeExistential(context.owner, selector)
val casesTyped = typedCases(cases, selectorTp, pt)
val (resTp, needAdapt) =
diff --git a/src/compiler/scala/tools/nsc/util/Statistics.scala b/src/compiler/scala/tools/nsc/util/Statistics.scala
index 61c7695911..53ab6654ee 100644
--- a/src/compiler/scala/tools/nsc/util/Statistics.scala
+++ b/src/compiler/scala/tools/nsc/util/Statistics.scala
@@ -60,6 +60,14 @@ class Statistics extends scala.reflect.internal.util.Statistics {
val macroExpandCount = new Counter
val macroExpandNanos = new Timer
+
+ val patmatNanos = new Timer
+ val patmatAnaDPLL = new Timer
+ val patmatAnaVarEq = new Timer
+ val patmatCNF = new Timer
+ val patmatAnaExhaust = new Timer
+ val patmatAnaReach = new Timer
+ val patmatCNFSizes = new collection.mutable.HashMap[Int, Int] withDefaultValue 0
}
object Statistics extends Statistics
@@ -71,7 +79,7 @@ abstract class StatisticsInfo {
val global: Global
import global._
- var phasesShown = List("parser", "typer", "erasure", "cleanup")
+ var phasesShown = List("parser", "typer", "patmat", "erasure", "cleanup")
def countNodes(tree: Tree, counts: ClassCounts) {
for (t <- tree) counts(t.getClass) += 1
@@ -83,10 +91,15 @@ abstract class StatisticsInfo {
def showRelTyper(timer: Timer) =
timer+showPercent(timer.nanos, typerNanos.nanos)
- def showCounts(counts: ClassCounts) =
+ def showRelPatmat(timer: Timer) =
+ timer+showPercent(timer.nanos, patmatNanos.nanos)
+
+ def showCounts[T](counts: scala.collection.mutable.Map[T, Int]) =
counts.toSeq.sortWith(_._2 > _._2).map {
- case (cls, cnt) =>
+ case (cls: Class[_], cnt) =>
cls.toString.substring(cls.toString.lastIndexOf("$") + 1)+": "+cnt
+ case (o, cnt) =>
+ o.toString +": "+cnt
}
def print(phase: Phase) = if (phasesShown contains phase.name) {
@@ -169,6 +182,16 @@ abstract class StatisticsInfo {
if (timer1 != null) inform("#timer1 : " + timer1)
if (timer2 != null) inform("#timer2 : " + timer2)
//for (t <- uniques.iterator) println("unique: "+t)
+
+ if (phase.name == "patmat") {
+ inform("time spent in patmat : " + patmatNanos )
+ inform(" of which DPLL : " + showRelPatmat(patmatAnaDPLL ))
+ inform("of which in CNF conversion : " + showRelPatmat(patmatCNF ))
+ inform(" CNF size counts : " + showCounts(patmatCNFSizes ))
+ inform("of which variable equality : " + showRelPatmat(patmatAnaVarEq ))
+ inform(" of which in exhaustivity : " + showRelPatmat(patmatAnaExhaust))
+ inform("of which in unreachability : " + showRelPatmat(patmatAnaReach ))
+ }
}
}
}
diff --git a/src/forkjoin/scala/concurrent/forkjoin/ForkJoinPool.java b/src/forkjoin/scala/concurrent/forkjoin/ForkJoinPool.java
index 4b5b3382f5..65654be69b 100644
--- a/src/forkjoin/scala/concurrent/forkjoin/ForkJoinPool.java
+++ b/src/forkjoin/scala/concurrent/forkjoin/ForkJoinPool.java
@@ -2864,24 +2864,7 @@ public class ForkJoinPool extends AbstractExecutorService {
* @return a sun.misc.Unsafe
*/
private static sun.misc.Unsafe getUnsafe() {
- try {
- return sun.misc.Unsafe.getUnsafe();
- } catch (SecurityException se) {
- try {
- return java.security.AccessController.doPrivileged
- (new java.security
- .PrivilegedExceptionAction<sun.misc.Unsafe>() {
- public sun.misc.Unsafe run() throws Exception {
- java.lang.reflect.Field f = sun.misc
- .Unsafe.class.getDeclaredField("theUnsafe");
- f.setAccessible(true);
- return (sun.misc.Unsafe) f.get(null);
- }});
- } catch (java.security.PrivilegedActionException e) {
- throw new RuntimeException("Could not initialize intrinsics",
- e.getCause());
- }
- }
+ return scala.concurrent.util.Unsafe.instance;
}
}
diff --git a/src/forkjoin/scala/concurrent/forkjoin/ForkJoinTask.java b/src/forkjoin/scala/concurrent/forkjoin/ForkJoinTask.java
index 2ba146c4da..15c60118b3 100644
--- a/src/forkjoin/scala/concurrent/forkjoin/ForkJoinTask.java
+++ b/src/forkjoin/scala/concurrent/forkjoin/ForkJoinTask.java
@@ -1537,23 +1537,6 @@ public abstract class ForkJoinTask<V> implements Future<V>, Serializable {
* @return a sun.misc.Unsafe
*/
private static sun.misc.Unsafe getUnsafe() {
- try {
- return sun.misc.Unsafe.getUnsafe();
- } catch (SecurityException se) {
- try {
- return java.security.AccessController.doPrivileged
- (new java.security
- .PrivilegedExceptionAction<sun.misc.Unsafe>() {
- public sun.misc.Unsafe run() throws Exception {
- java.lang.reflect.Field f = sun.misc
- .Unsafe.class.getDeclaredField("theUnsafe");
- f.setAccessible(true);
- return (sun.misc.Unsafe) f.get(null);
- }});
- } catch (java.security.PrivilegedActionException e) {
- throw new RuntimeException("Could not initialize intrinsics",
- e.getCause());
- }
- }
+ return scala.concurrent.util.Unsafe.instance;
}
}
diff --git a/src/forkjoin/scala/concurrent/forkjoin/LinkedTransferQueue.java b/src/forkjoin/scala/concurrent/forkjoin/LinkedTransferQueue.java
index ceeb9212d5..07e81b395d 100644
--- a/src/forkjoin/scala/concurrent/forkjoin/LinkedTransferQueue.java
+++ b/src/forkjoin/scala/concurrent/forkjoin/LinkedTransferQueue.java
@@ -1329,24 +1329,7 @@ public class LinkedTransferQueue<E> extends AbstractQueue<E>
* @return a sun.misc.Unsafe
*/
static sun.misc.Unsafe getUnsafe() {
- try {
- return sun.misc.Unsafe.getUnsafe();
- } catch (SecurityException se) {
- try {
- return java.security.AccessController.doPrivileged
- (new java.security
- .PrivilegedExceptionAction<sun.misc.Unsafe>() {
- public sun.misc.Unsafe run() throws Exception {
- java.lang.reflect.Field f = sun.misc
- .Unsafe.class.getDeclaredField("theUnsafe");
- f.setAccessible(true);
- return (sun.misc.Unsafe) f.get(null);
- }});
- } catch (java.security.PrivilegedActionException e) {
- throw new RuntimeException("Could not initialize intrinsics",
- e.getCause());
- }
- }
+ return scala.concurrent.util.Unsafe.instance;
}
}
diff --git a/src/library/scala/AnyVal.scala b/src/library/scala/AnyVal.scala
index 393f0899f4..d637527b30 100644
--- a/src/library/scala/AnyVal.scala
+++ b/src/library/scala/AnyVal.scala
@@ -26,7 +26,5 @@ package scala
* The ''floating point types'' are [[scala.Float]] and [[scala.Double]].
*/
abstract class AnyVal extends Any with NotNull {
- // disabled for now to make the standard build go through.
- // Once we have a new strap we can uncomment this and delete the AnyVal_getClass entry in Definitions.
- def getClass(): Class[_ <: AnyVal] = ???
+ def getClass(): Class[_ <: AnyVal] = null
}
diff --git a/src/library/scala/Boolean.scala b/src/library/scala/Boolean.scala
index edb82b33fe..014928d986 100644
--- a/src/library/scala/Boolean.scala
+++ b/src/library/scala/Boolean.scala
@@ -10,6 +10,8 @@
package scala
+import language.implicitConversions
+
/** `Boolean` (equivalent to Java's `boolean` primitive type) is a
* subtype of [[scala.AnyVal]]. Instances of `Boolean` are not
* represented by an object in the underlying runtime system.
@@ -17,7 +19,7 @@ package scala
* There is an implicit conversion from [[scala.Boolean]] => [[scala.runtime.RichBoolean]]
* which provides useful non-primitive operations.
*/
-final class Boolean private extends AnyVal {
+final abstract class Boolean private extends AnyVal {
/**
* Negates a Boolean expression.
*
@@ -26,7 +28,7 @@ final class Boolean private extends AnyVal {
*
* @return the negated expression
*/
- def unary_! : Boolean = sys.error("stub")
+ def unary_! : Boolean
/**
* Compares two Boolean expressions and returns `true` if they evaluate to the same value.
@@ -35,7 +37,7 @@ final class Boolean private extends AnyVal {
* - `a` and `b` are `true` or
* - `a` and `b` are `false`.
*/
- def ==(x: Boolean): Boolean = sys.error("stub")
+ def ==(x: Boolean): Boolean
/**
* Compares two Boolean expressions and returns `true` if they evaluate to a different value.
@@ -44,7 +46,7 @@ final class Boolean private extends AnyVal {
* - `a` is `true` and `b` is `false` or
* - `a` is `false` and `b` is `true`.
*/
- def !=(x: Boolean): Boolean = sys.error("stub")
+ def !=(x: Boolean): Boolean
/**
* Compares two Boolean expressions and returns `true` if one or both of them evaluate to true.
@@ -58,7 +60,7 @@ final class Boolean private extends AnyVal {
* behaves as if it was declared as `def ||(x: => Boolean): Boolean`.
* If `a` evaluates to `true`, `true` is returned without evaluating `b`.
*/
- def ||(x: Boolean): Boolean = sys.error("stub")
+ def ||(x: Boolean): Boolean
/**
* Compares two Boolean expressions and returns `true` if both of them evaluate to true.
@@ -70,11 +72,11 @@ final class Boolean private extends AnyVal {
* behaves as if it was declared as `def &&(x: => Boolean): Boolean`.
* If `a` evaluates to `false`, `false` is returned without evaluating `b`.
*/
- def &&(x: Boolean): Boolean = sys.error("stub")
+ def &&(x: Boolean): Boolean
// Compiler won't build with these seemingly more accurate signatures
- // def ||(x: => Boolean): Boolean = sys.error("stub")
- // def &&(x: => Boolean): Boolean = sys.error("stub")
+ // def ||(x: => Boolean): Boolean
+ // def &&(x: => Boolean): Boolean
/**
* Compares two Boolean expressions and returns `true` if one or both of them evaluate to true.
@@ -86,7 +88,7 @@ final class Boolean private extends AnyVal {
*
* @note This method evaluates both `a` and `b`, even if the result is already determined after evaluating `a`.
*/
- def |(x: Boolean): Boolean = sys.error("stub")
+ def |(x: Boolean): Boolean
/**
* Compares two Boolean expressions and returns `true` if both of them evaluate to true.
@@ -96,7 +98,7 @@ final class Boolean private extends AnyVal {
*
* @note This method evaluates both `a` and `b`, even if the result is already determined after evaluating `a`.
*/
- def &(x: Boolean): Boolean = sys.error("stub")
+ def &(x: Boolean): Boolean
/**
* Compares two Boolean expressions and returns `true` if they evaluate to a different value.
@@ -105,12 +107,12 @@ final class Boolean private extends AnyVal {
* - `a` is `true` and `b` is `false` or
* - `a` is `false` and `b` is `true`.
*/
- def ^(x: Boolean): Boolean = sys.error("stub")
+ def ^(x: Boolean): Boolean
- override def getClass(): Class[Boolean] = sys.error("stub")
+ override def getClass(): Class[Boolean] = null
}
-object Boolean extends AnyValCompanion {
+object Boolean extends AnyValCompanion {
/** Transform a value type into a boxed reference type.
*
@@ -132,5 +134,6 @@ object Boolean extends AnyValCompanion {
/** The String representation of the scala.Boolean companion object.
*/
override def toString = "object scala.Boolean"
+
}
diff --git a/src/library/scala/Byte.scala b/src/library/scala/Byte.scala
index b5b3d88e3f..6f54f6cedf 100644
--- a/src/library/scala/Byte.scala
+++ b/src/library/scala/Byte.scala
@@ -10,6 +10,8 @@
package scala
+import language.implicitConversions
+
/** `Byte`, a 8-bit signed integer (equivalent to Java's `byte` primitive type) is a
* subtype of [[scala.AnyVal]]. Instances of `Byte` are not
* represented by an object in the underlying runtime system.
@@ -17,14 +19,14 @@ package scala
* There is an implicit conversion from [[scala.Byte]] => [[scala.runtime.RichByte]]
* which provides useful non-primitive operations.
*/
-final class Byte private extends AnyVal {
- def toByte: Byte = sys.error("stub")
- def toShort: Short = sys.error("stub")
- def toChar: Char = sys.error("stub")
- def toInt: Int = sys.error("stub")
- def toLong: Long = sys.error("stub")
- def toFloat: Float = sys.error("stub")
- def toDouble: Double = sys.error("stub")
+final abstract class Byte private extends AnyVal {
+ def toByte: Byte
+ def toShort: Short
+ def toChar: Char
+ def toInt: Int
+ def toLong: Long
+ def toFloat: Float
+ def toDouble: Double
/**
* Returns the bitwise negation of this value.
@@ -34,30 +36,30 @@ final class Byte private extends AnyVal {
* // 11111010
* }}}
*/
- def unary_~ : Int = sys.error("stub")
+ def unary_~ : Int
/**
* Returns this value, unmodified.
*/
- def unary_+ : Int = sys.error("stub")
+ def unary_+ : Int
/**
* Returns the negation of this value.
*/
- def unary_- : Int = sys.error("stub")
+ def unary_- : Int
- def +(x: String): String = sys.error("stub")
+ def +(x: String): String
/**
* Returns this value bit-shifted left by the specified number of bits,
* filling in the new right bits with zeroes.
* @example {{{ 6 << 3 == 48 // in binary: 0110 << 3 == 0110000 }}}
*/
- def <<(x: Int): Int = sys.error("stub")
+ def <<(x: Int): Int
/**
* Returns this value bit-shifted left by the specified number of bits,
* filling in the new right bits with zeroes.
* @example {{{ 6 << 3 == 48 // in binary: 0110 << 3 == 0110000 }}}
*/
- def <<(x: Long): Int = sys.error("stub")
+ def <<(x: Long): Int
/**
* Returns this value bit-shifted right by the specified number of bits,
* filling the new left bits with zeroes.
@@ -68,7 +70,7 @@ final class Byte private extends AnyVal {
* // 00011111 11111111 11111111 11111101
* }}}
*/
- def >>>(x: Int): Int = sys.error("stub")
+ def >>>(x: Int): Int
/**
* Returns this value bit-shifted right by the specified number of bits,
* filling the new left bits with zeroes.
@@ -79,7 +81,7 @@ final class Byte private extends AnyVal {
* // 00011111 11111111 11111111 11111101
* }}}
*/
- def >>>(x: Long): Int = sys.error("stub")
+ def >>>(x: Long): Int
/**
* Returns this value bit-shifted left by the specified number of bits,
* filling in the right bits with the same value as the left-most bit of this.
@@ -90,7 +92,7 @@ final class Byte private extends AnyVal {
* // 11111111 11111111 11111111 11111101
* }}}
*/
- def >>(x: Int): Int = sys.error("stub")
+ def >>(x: Int): Int
/**
* Returns this value bit-shifted left by the specified number of bits,
* filling in the right bits with the same value as the left-most bit of this.
@@ -101,181 +103,181 @@ final class Byte private extends AnyVal {
* // 11111111 11111111 11111111 11111101
* }}}
*/
- def >>(x: Long): Int = sys.error("stub")
+ def >>(x: Long): Int
/**
* Returns `true` if this value is equal to x, `false` otherwise.
*/
- def ==(x: Byte): Boolean = sys.error("stub")
+ def ==(x: Byte): Boolean
/**
* Returns `true` if this value is equal to x, `false` otherwise.
*/
- def ==(x: Short): Boolean = sys.error("stub")
+ def ==(x: Short): Boolean
/**
* Returns `true` if this value is equal to x, `false` otherwise.
*/
- def ==(x: Char): Boolean = sys.error("stub")
+ def ==(x: Char): Boolean
/**
* Returns `true` if this value is equal to x, `false` otherwise.
*/
- def ==(x: Int): Boolean = sys.error("stub")
+ def ==(x: Int): Boolean
/**
* Returns `true` if this value is equal to x, `false` otherwise.
*/
- def ==(x: Long): Boolean = sys.error("stub")
+ def ==(x: Long): Boolean
/**
* Returns `true` if this value is equal to x, `false` otherwise.
*/
- def ==(x: Float): Boolean = sys.error("stub")
+ def ==(x: Float): Boolean
/**
* Returns `true` if this value is equal to x, `false` otherwise.
*/
- def ==(x: Double): Boolean = sys.error("stub")
+ def ==(x: Double): Boolean
/**
* Returns `true` if this value is not equal to x, `false` otherwise.
*/
- def !=(x: Byte): Boolean = sys.error("stub")
+ def !=(x: Byte): Boolean
/**
* Returns `true` if this value is not equal to x, `false` otherwise.
*/
- def !=(x: Short): Boolean = sys.error("stub")
+ def !=(x: Short): Boolean
/**
* Returns `true` if this value is not equal to x, `false` otherwise.
*/
- def !=(x: Char): Boolean = sys.error("stub")
+ def !=(x: Char): Boolean
/**
* Returns `true` if this value is not equal to x, `false` otherwise.
*/
- def !=(x: Int): Boolean = sys.error("stub")
+ def !=(x: Int): Boolean
/**
* Returns `true` if this value is not equal to x, `false` otherwise.
*/
- def !=(x: Long): Boolean = sys.error("stub")
+ def !=(x: Long): Boolean
/**
* Returns `true` if this value is not equal to x, `false` otherwise.
*/
- def !=(x: Float): Boolean = sys.error("stub")
+ def !=(x: Float): Boolean
/**
* Returns `true` if this value is not equal to x, `false` otherwise.
*/
- def !=(x: Double): Boolean = sys.error("stub")
+ def !=(x: Double): Boolean
/**
* Returns `true` if this value is less than x, `false` otherwise.
*/
- def <(x: Byte): Boolean = sys.error("stub")
+ def <(x: Byte): Boolean
/**
* Returns `true` if this value is less than x, `false` otherwise.
*/
- def <(x: Short): Boolean = sys.error("stub")
+ def <(x: Short): Boolean
/**
* Returns `true` if this value is less than x, `false` otherwise.
*/
- def <(x: Char): Boolean = sys.error("stub")
+ def <(x: Char): Boolean
/**
* Returns `true` if this value is less than x, `false` otherwise.
*/
- def <(x: Int): Boolean = sys.error("stub")
+ def <(x: Int): Boolean
/**
* Returns `true` if this value is less than x, `false` otherwise.
*/
- def <(x: Long): Boolean = sys.error("stub")
+ def <(x: Long): Boolean
/**
* Returns `true` if this value is less than x, `false` otherwise.
*/
- def <(x: Float): Boolean = sys.error("stub")
+ def <(x: Float): Boolean
/**
* Returns `true` if this value is less than x, `false` otherwise.
*/
- def <(x: Double): Boolean = sys.error("stub")
+ def <(x: Double): Boolean
/**
* Returns `true` if this value is less than or equal to x, `false` otherwise.
*/
- def <=(x: Byte): Boolean = sys.error("stub")
+ def <=(x: Byte): Boolean
/**
* Returns `true` if this value is less than or equal to x, `false` otherwise.
*/
- def <=(x: Short): Boolean = sys.error("stub")
+ def <=(x: Short): Boolean
/**
* Returns `true` if this value is less than or equal to x, `false` otherwise.
*/
- def <=(x: Char): Boolean = sys.error("stub")
+ def <=(x: Char): Boolean
/**
* Returns `true` if this value is less than or equal to x, `false` otherwise.
*/
- def <=(x: Int): Boolean = sys.error("stub")
+ def <=(x: Int): Boolean
/**
* Returns `true` if this value is less than or equal to x, `false` otherwise.
*/
- def <=(x: Long): Boolean = sys.error("stub")
+ def <=(x: Long): Boolean
/**
* Returns `true` if this value is less than or equal to x, `false` otherwise.
*/
- def <=(x: Float): Boolean = sys.error("stub")
+ def <=(x: Float): Boolean
/**
* Returns `true` if this value is less than or equal to x, `false` otherwise.
*/
- def <=(x: Double): Boolean = sys.error("stub")
+ def <=(x: Double): Boolean
/**
* Returns `true` if this value is greater than x, `false` otherwise.
*/
- def >(x: Byte): Boolean = sys.error("stub")
+ def >(x: Byte): Boolean
/**
* Returns `true` if this value is greater than x, `false` otherwise.
*/
- def >(x: Short): Boolean = sys.error("stub")
+ def >(x: Short): Boolean
/**
* Returns `true` if this value is greater than x, `false` otherwise.
*/
- def >(x: Char): Boolean = sys.error("stub")
+ def >(x: Char): Boolean
/**
* Returns `true` if this value is greater than x, `false` otherwise.
*/
- def >(x: Int): Boolean = sys.error("stub")
+ def >(x: Int): Boolean
/**
* Returns `true` if this value is greater than x, `false` otherwise.
*/
- def >(x: Long): Boolean = sys.error("stub")
+ def >(x: Long): Boolean
/**
* Returns `true` if this value is greater than x, `false` otherwise.
*/
- def >(x: Float): Boolean = sys.error("stub")
+ def >(x: Float): Boolean
/**
* Returns `true` if this value is greater than x, `false` otherwise.
*/
- def >(x: Double): Boolean = sys.error("stub")
+ def >(x: Double): Boolean
/**
* Returns `true` if this value is greater than or equal to x, `false` otherwise.
*/
- def >=(x: Byte): Boolean = sys.error("stub")
+ def >=(x: Byte): Boolean
/**
* Returns `true` if this value is greater than or equal to x, `false` otherwise.
*/
- def >=(x: Short): Boolean = sys.error("stub")
+ def >=(x: Short): Boolean
/**
* Returns `true` if this value is greater than or equal to x, `false` otherwise.
*/
- def >=(x: Char): Boolean = sys.error("stub")
+ def >=(x: Char): Boolean
/**
* Returns `true` if this value is greater than or equal to x, `false` otherwise.
*/
- def >=(x: Int): Boolean = sys.error("stub")
+ def >=(x: Int): Boolean
/**
* Returns `true` if this value is greater than or equal to x, `false` otherwise.
*/
- def >=(x: Long): Boolean = sys.error("stub")
+ def >=(x: Long): Boolean
/**
* Returns `true` if this value is greater than or equal to x, `false` otherwise.
*/
- def >=(x: Float): Boolean = sys.error("stub")
+ def >=(x: Float): Boolean
/**
* Returns `true` if this value is greater than or equal to x, `false` otherwise.
*/
- def >=(x: Double): Boolean = sys.error("stub")
+ def >=(x: Double): Boolean
/**
* Returns the bitwise OR of this value and `x`.
@@ -287,7 +289,7 @@ final class Byte private extends AnyVal {
* // 11111010
* }}}
*/
- def |(x: Byte): Int = sys.error("stub")
+ def |(x: Byte): Int
/**
* Returns the bitwise OR of this value and `x`.
* @example {{{
@@ -298,7 +300,7 @@ final class Byte private extends AnyVal {
* // 11111010
* }}}
*/
- def |(x: Short): Int = sys.error("stub")
+ def |(x: Short): Int
/**
* Returns the bitwise OR of this value and `x`.
* @example {{{
@@ -309,7 +311,7 @@ final class Byte private extends AnyVal {
* // 11111010
* }}}
*/
- def |(x: Char): Int = sys.error("stub")
+ def |(x: Char): Int
/**
* Returns the bitwise OR of this value and `x`.
* @example {{{
@@ -320,7 +322,7 @@ final class Byte private extends AnyVal {
* // 11111010
* }}}
*/
- def |(x: Int): Int = sys.error("stub")
+ def |(x: Int): Int
/**
* Returns the bitwise OR of this value and `x`.
* @example {{{
@@ -331,7 +333,7 @@ final class Byte private extends AnyVal {
* // 11111010
* }}}
*/
- def |(x: Long): Long = sys.error("stub")
+ def |(x: Long): Long
/**
* Returns the bitwise AND of this value and `x`.
@@ -343,7 +345,7 @@ final class Byte private extends AnyVal {
* // 10100000
* }}}
*/
- def &(x: Byte): Int = sys.error("stub")
+ def &(x: Byte): Int
/**
* Returns the bitwise AND of this value and `x`.
* @example {{{
@@ -354,7 +356,7 @@ final class Byte private extends AnyVal {
* // 10100000
* }}}
*/
- def &(x: Short): Int = sys.error("stub")
+ def &(x: Short): Int
/**
* Returns the bitwise AND of this value and `x`.
* @example {{{
@@ -365,7 +367,7 @@ final class Byte private extends AnyVal {
* // 10100000
* }}}
*/
- def &(x: Char): Int = sys.error("stub")
+ def &(x: Char): Int
/**
* Returns the bitwise AND of this value and `x`.
* @example {{{
@@ -376,7 +378,7 @@ final class Byte private extends AnyVal {
* // 10100000
* }}}
*/
- def &(x: Int): Int = sys.error("stub")
+ def &(x: Int): Int
/**
* Returns the bitwise AND of this value and `x`.
* @example {{{
@@ -387,7 +389,7 @@ final class Byte private extends AnyVal {
* // 10100000
* }}}
*/
- def &(x: Long): Long = sys.error("stub")
+ def &(x: Long): Long
/**
* Returns the bitwise XOR of this value and `x`.
@@ -399,7 +401,7 @@ final class Byte private extends AnyVal {
* // 01011010
* }}}
*/
- def ^(x: Byte): Int = sys.error("stub")
+ def ^(x: Byte): Int
/**
* Returns the bitwise XOR of this value and `x`.
* @example {{{
@@ -410,7 +412,7 @@ final class Byte private extends AnyVal {
* // 01011010
* }}}
*/
- def ^(x: Short): Int = sys.error("stub")
+ def ^(x: Short): Int
/**
* Returns the bitwise XOR of this value and `x`.
* @example {{{
@@ -421,7 +423,7 @@ final class Byte private extends AnyVal {
* // 01011010
* }}}
*/
- def ^(x: Char): Int = sys.error("stub")
+ def ^(x: Char): Int
/**
* Returns the bitwise XOR of this value and `x`.
* @example {{{
@@ -432,7 +434,7 @@ final class Byte private extends AnyVal {
* // 01011010
* }}}
*/
- def ^(x: Int): Int = sys.error("stub")
+ def ^(x: Int): Int
/**
* Returns the bitwise XOR of this value and `x`.
* @example {{{
@@ -443,157 +445,157 @@ final class Byte private extends AnyVal {
* // 01011010
* }}}
*/
- def ^(x: Long): Long = sys.error("stub")
+ def ^(x: Long): Long
/**
* Returns the sum of this value and `x`.
*/
- def +(x: Byte): Int = sys.error("stub")
+ def +(x: Byte): Int
/**
* Returns the sum of this value and `x`.
*/
- def +(x: Short): Int = sys.error("stub")
+ def +(x: Short): Int
/**
* Returns the sum of this value and `x`.
*/
- def +(x: Char): Int = sys.error("stub")
+ def +(x: Char): Int
/**
* Returns the sum of this value and `x`.
*/
- def +(x: Int): Int = sys.error("stub")
+ def +(x: Int): Int
/**
* Returns the sum of this value and `x`.
*/
- def +(x: Long): Long = sys.error("stub")
+ def +(x: Long): Long
/**
* Returns the sum of this value and `x`.
*/
- def +(x: Float): Float = sys.error("stub")
+ def +(x: Float): Float
/**
* Returns the sum of this value and `x`.
*/
- def +(x: Double): Double = sys.error("stub")
+ def +(x: Double): Double
/**
* Returns the difference of this value and `x`.
*/
- def -(x: Byte): Int = sys.error("stub")
+ def -(x: Byte): Int
/**
* Returns the difference of this value and `x`.
*/
- def -(x: Short): Int = sys.error("stub")
+ def -(x: Short): Int
/**
* Returns the difference of this value and `x`.
*/
- def -(x: Char): Int = sys.error("stub")
+ def -(x: Char): Int
/**
* Returns the difference of this value and `x`.
*/
- def -(x: Int): Int = sys.error("stub")
+ def -(x: Int): Int
/**
* Returns the difference of this value and `x`.
*/
- def -(x: Long): Long = sys.error("stub")
+ def -(x: Long): Long
/**
* Returns the difference of this value and `x`.
*/
- def -(x: Float): Float = sys.error("stub")
+ def -(x: Float): Float
/**
* Returns the difference of this value and `x`.
*/
- def -(x: Double): Double = sys.error("stub")
+ def -(x: Double): Double
/**
* Returns the product of this value and `x`.
*/
- def *(x: Byte): Int = sys.error("stub")
+ def *(x: Byte): Int
/**
* Returns the product of this value and `x`.
*/
- def *(x: Short): Int = sys.error("stub")
+ def *(x: Short): Int
/**
* Returns the product of this value and `x`.
*/
- def *(x: Char): Int = sys.error("stub")
+ def *(x: Char): Int
/**
* Returns the product of this value and `x`.
*/
- def *(x: Int): Int = sys.error("stub")
+ def *(x: Int): Int
/**
* Returns the product of this value and `x`.
*/
- def *(x: Long): Long = sys.error("stub")
+ def *(x: Long): Long
/**
* Returns the product of this value and `x`.
*/
- def *(x: Float): Float = sys.error("stub")
+ def *(x: Float): Float
/**
* Returns the product of this value and `x`.
*/
- def *(x: Double): Double = sys.error("stub")
+ def *(x: Double): Double
/**
* Returns the quotient of this value and `x`.
*/
- def /(x: Byte): Int = sys.error("stub")
+ def /(x: Byte): Int
/**
* Returns the quotient of this value and `x`.
*/
- def /(x: Short): Int = sys.error("stub")
+ def /(x: Short): Int
/**
* Returns the quotient of this value and `x`.
*/
- def /(x: Char): Int = sys.error("stub")
+ def /(x: Char): Int
/**
* Returns the quotient of this value and `x`.
*/
- def /(x: Int): Int = sys.error("stub")
+ def /(x: Int): Int
/**
* Returns the quotient of this value and `x`.
*/
- def /(x: Long): Long = sys.error("stub")
+ def /(x: Long): Long
/**
* Returns the quotient of this value and `x`.
*/
- def /(x: Float): Float = sys.error("stub")
+ def /(x: Float): Float
/**
* Returns the quotient of this value and `x`.
*/
- def /(x: Double): Double = sys.error("stub")
+ def /(x: Double): Double
/**
* Returns the remainder of the division of this value by `x`.
*/
- def %(x: Byte): Int = sys.error("stub")
+ def %(x: Byte): Int
/**
* Returns the remainder of the division of this value by `x`.
*/
- def %(x: Short): Int = sys.error("stub")
+ def %(x: Short): Int
/**
* Returns the remainder of the division of this value by `x`.
*/
- def %(x: Char): Int = sys.error("stub")
+ def %(x: Char): Int
/**
* Returns the remainder of the division of this value by `x`.
*/
- def %(x: Int): Int = sys.error("stub")
+ def %(x: Int): Int
/**
* Returns the remainder of the division of this value by `x`.
*/
- def %(x: Long): Long = sys.error("stub")
+ def %(x: Long): Long
/**
* Returns the remainder of the division of this value by `x`.
*/
- def %(x: Float): Float = sys.error("stub")
+ def %(x: Float): Float
/**
* Returns the remainder of the division of this value by `x`.
*/
- def %(x: Double): Double = sys.error("stub")
+ def %(x: Double): Double
- override def getClass(): Class[Byte] = sys.error("stub")
+ override def getClass(): Class[Byte] = null
}
-object Byte extends AnyValCompanion {
+object Byte extends AnyValCompanion {
/** The smallest value representable as a Byte.
*/
final val MinValue = java.lang.Byte.MIN_VALUE
@@ -622,6 +624,9 @@ object Byte extends AnyValCompanion {
/** The String representation of the scala.Byte companion object.
*/
override def toString = "object scala.Byte"
+
+ /** Language mandated coercions from Byte to "wider" types.
+ */
implicit def byte2short(x: Byte): Short = x.toShort
implicit def byte2int(x: Byte): Int = x.toInt
implicit def byte2long(x: Byte): Long = x.toLong
diff --git a/src/library/scala/Char.scala b/src/library/scala/Char.scala
index e0ac9a2550..b681ae1693 100644
--- a/src/library/scala/Char.scala
+++ b/src/library/scala/Char.scala
@@ -10,6 +10,8 @@
package scala
+import language.implicitConversions
+
/** `Char`, a 16-bit unsigned integer (equivalent to Java's `char` primitive type) is a
* subtype of [[scala.AnyVal]]. Instances of `Char` are not
* represented by an object in the underlying runtime system.
@@ -17,14 +19,14 @@ package scala
* There is an implicit conversion from [[scala.Char]] => [[scala.runtime.RichChar]]
* which provides useful non-primitive operations.
*/
-final class Char private extends AnyVal {
- def toByte: Byte = sys.error("stub")
- def toShort: Short = sys.error("stub")
- def toChar: Char = sys.error("stub")
- def toInt: Int = sys.error("stub")
- def toLong: Long = sys.error("stub")
- def toFloat: Float = sys.error("stub")
- def toDouble: Double = sys.error("stub")
+final abstract class Char private extends AnyVal {
+ def toByte: Byte
+ def toShort: Short
+ def toChar: Char
+ def toInt: Int
+ def toLong: Long
+ def toFloat: Float
+ def toDouble: Double
/**
* Returns the bitwise negation of this value.
@@ -34,30 +36,30 @@ final class Char private extends AnyVal {
* // 11111010
* }}}
*/
- def unary_~ : Int = sys.error("stub")
+ def unary_~ : Int
/**
* Returns this value, unmodified.
*/
- def unary_+ : Int = sys.error("stub")
+ def unary_+ : Int
/**
* Returns the negation of this value.
*/
- def unary_- : Int = sys.error("stub")
+ def unary_- : Int
- def +(x: String): String = sys.error("stub")
+ def +(x: String): String
/**
* Returns this value bit-shifted left by the specified number of bits,
* filling in the new right bits with zeroes.
* @example {{{ 6 << 3 == 48 // in binary: 0110 << 3 == 0110000 }}}
*/
- def <<(x: Int): Int = sys.error("stub")
+ def <<(x: Int): Int
/**
* Returns this value bit-shifted left by the specified number of bits,
* filling in the new right bits with zeroes.
* @example {{{ 6 << 3 == 48 // in binary: 0110 << 3 == 0110000 }}}
*/
- def <<(x: Long): Int = sys.error("stub")
+ def <<(x: Long): Int
/**
* Returns this value bit-shifted right by the specified number of bits,
* filling the new left bits with zeroes.
@@ -68,7 +70,7 @@ final class Char private extends AnyVal {
* // 00011111 11111111 11111111 11111101
* }}}
*/
- def >>>(x: Int): Int = sys.error("stub")
+ def >>>(x: Int): Int
/**
* Returns this value bit-shifted right by the specified number of bits,
* filling the new left bits with zeroes.
@@ -79,7 +81,7 @@ final class Char private extends AnyVal {
* // 00011111 11111111 11111111 11111101
* }}}
*/
- def >>>(x: Long): Int = sys.error("stub")
+ def >>>(x: Long): Int
/**
* Returns this value bit-shifted left by the specified number of bits,
* filling in the right bits with the same value as the left-most bit of this.
@@ -90,7 +92,7 @@ final class Char private extends AnyVal {
* // 11111111 11111111 11111111 11111101
* }}}
*/
- def >>(x: Int): Int = sys.error("stub")
+ def >>(x: Int): Int
/**
* Returns this value bit-shifted left by the specified number of bits,
* filling in the right bits with the same value as the left-most bit of this.
@@ -101,181 +103,181 @@ final class Char private extends AnyVal {
* // 11111111 11111111 11111111 11111101
* }}}
*/
- def >>(x: Long): Int = sys.error("stub")
+ def >>(x: Long): Int
/**
* Returns `true` if this value is equal to x, `false` otherwise.
*/
- def ==(x: Byte): Boolean = sys.error("stub")
+ def ==(x: Byte): Boolean
/**
* Returns `true` if this value is equal to x, `false` otherwise.
*/
- def ==(x: Short): Boolean = sys.error("stub")
+ def ==(x: Short): Boolean
/**
* Returns `true` if this value is equal to x, `false` otherwise.
*/
- def ==(x: Char): Boolean = sys.error("stub")
+ def ==(x: Char): Boolean
/**
* Returns `true` if this value is equal to x, `false` otherwise.
*/
- def ==(x: Int): Boolean = sys.error("stub")
+ def ==(x: Int): Boolean
/**
* Returns `true` if this value is equal to x, `false` otherwise.
*/
- def ==(x: Long): Boolean = sys.error("stub")
+ def ==(x: Long): Boolean
/**
* Returns `true` if this value is equal to x, `false` otherwise.
*/
- def ==(x: Float): Boolean = sys.error("stub")
+ def ==(x: Float): Boolean
/**
* Returns `true` if this value is equal to x, `false` otherwise.
*/
- def ==(x: Double): Boolean = sys.error("stub")
+ def ==(x: Double): Boolean
/**
* Returns `true` if this value is not equal to x, `false` otherwise.
*/
- def !=(x: Byte): Boolean = sys.error("stub")
+ def !=(x: Byte): Boolean
/**
* Returns `true` if this value is not equal to x, `false` otherwise.
*/
- def !=(x: Short): Boolean = sys.error("stub")
+ def !=(x: Short): Boolean
/**
* Returns `true` if this value is not equal to x, `false` otherwise.
*/
- def !=(x: Char): Boolean = sys.error("stub")
+ def !=(x: Char): Boolean
/**
* Returns `true` if this value is not equal to x, `false` otherwise.
*/
- def !=(x: Int): Boolean = sys.error("stub")
+ def !=(x: Int): Boolean
/**
* Returns `true` if this value is not equal to x, `false` otherwise.
*/
- def !=(x: Long): Boolean = sys.error("stub")
+ def !=(x: Long): Boolean
/**
* Returns `true` if this value is not equal to x, `false` otherwise.
*/
- def !=(x: Float): Boolean = sys.error("stub")
+ def !=(x: Float): Boolean
/**
* Returns `true` if this value is not equal to x, `false` otherwise.
*/
- def !=(x: Double): Boolean = sys.error("stub")
+ def !=(x: Double): Boolean
/**
* Returns `true` if this value is less than x, `false` otherwise.
*/
- def <(x: Byte): Boolean = sys.error("stub")
+ def <(x: Byte): Boolean
/**
* Returns `true` if this value is less than x, `false` otherwise.
*/
- def <(x: Short): Boolean = sys.error("stub")
+ def <(x: Short): Boolean
/**
* Returns `true` if this value is less than x, `false` otherwise.
*/
- def <(x: Char): Boolean = sys.error("stub")
+ def <(x: Char): Boolean
/**
* Returns `true` if this value is less than x, `false` otherwise.
*/
- def <(x: Int): Boolean = sys.error("stub")
+ def <(x: Int): Boolean
/**
* Returns `true` if this value is less than x, `false` otherwise.
*/
- def <(x: Long): Boolean = sys.error("stub")
+ def <(x: Long): Boolean
/**
* Returns `true` if this value is less than x, `false` otherwise.
*/
- def <(x: Float): Boolean = sys.error("stub")
+ def <(x: Float): Boolean
/**
* Returns `true` if this value is less than x, `false` otherwise.
*/
- def <(x: Double): Boolean = sys.error("stub")
+ def <(x: Double): Boolean
/**
* Returns `true` if this value is less than or equal to x, `false` otherwise.
*/
- def <=(x: Byte): Boolean = sys.error("stub")
+ def <=(x: Byte): Boolean
/**
* Returns `true` if this value is less than or equal to x, `false` otherwise.
*/
- def <=(x: Short): Boolean = sys.error("stub")
+ def <=(x: Short): Boolean
/**
* Returns `true` if this value is less than or equal to x, `false` otherwise.
*/
- def <=(x: Char): Boolean = sys.error("stub")
+ def <=(x: Char): Boolean
/**
* Returns `true` if this value is less than or equal to x, `false` otherwise.
*/
- def <=(x: Int): Boolean = sys.error("stub")
+ def <=(x: Int): Boolean
/**
* Returns `true` if this value is less than or equal to x, `false` otherwise.
*/
- def <=(x: Long): Boolean = sys.error("stub")
+ def <=(x: Long): Boolean
/**
* Returns `true` if this value is less than or equal to x, `false` otherwise.
*/
- def <=(x: Float): Boolean = sys.error("stub")
+ def <=(x: Float): Boolean
/**
* Returns `true` if this value is less than or equal to x, `false` otherwise.
*/
- def <=(x: Double): Boolean = sys.error("stub")
+ def <=(x: Double): Boolean
/**
* Returns `true` if this value is greater than x, `false` otherwise.
*/
- def >(x: Byte): Boolean = sys.error("stub")
+ def >(x: Byte): Boolean
/**
* Returns `true` if this value is greater than x, `false` otherwise.
*/
- def >(x: Short): Boolean = sys.error("stub")
+ def >(x: Short): Boolean
/**
* Returns `true` if this value is greater than x, `false` otherwise.
*/
- def >(x: Char): Boolean = sys.error("stub")
+ def >(x: Char): Boolean
/**
* Returns `true` if this value is greater than x, `false` otherwise.
*/
- def >(x: Int): Boolean = sys.error("stub")
+ def >(x: Int): Boolean
/**
* Returns `true` if this value is greater than x, `false` otherwise.
*/
- def >(x: Long): Boolean = sys.error("stub")
+ def >(x: Long): Boolean
/**
* Returns `true` if this value is greater than x, `false` otherwise.
*/
- def >(x: Float): Boolean = sys.error("stub")
+ def >(x: Float): Boolean
/**
* Returns `true` if this value is greater than x, `false` otherwise.
*/
- def >(x: Double): Boolean = sys.error("stub")
+ def >(x: Double): Boolean
/**
* Returns `true` if this value is greater than or equal to x, `false` otherwise.
*/
- def >=(x: Byte): Boolean = sys.error("stub")
+ def >=(x: Byte): Boolean
/**
* Returns `true` if this value is greater than or equal to x, `false` otherwise.
*/
- def >=(x: Short): Boolean = sys.error("stub")
+ def >=(x: Short): Boolean
/**
* Returns `true` if this value is greater than or equal to x, `false` otherwise.
*/
- def >=(x: Char): Boolean = sys.error("stub")
+ def >=(x: Char): Boolean
/**
* Returns `true` if this value is greater than or equal to x, `false` otherwise.
*/
- def >=(x: Int): Boolean = sys.error("stub")
+ def >=(x: Int): Boolean
/**
* Returns `true` if this value is greater than or equal to x, `false` otherwise.
*/
- def >=(x: Long): Boolean = sys.error("stub")
+ def >=(x: Long): Boolean
/**
* Returns `true` if this value is greater than or equal to x, `false` otherwise.
*/
- def >=(x: Float): Boolean = sys.error("stub")
+ def >=(x: Float): Boolean
/**
* Returns `true` if this value is greater than or equal to x, `false` otherwise.
*/
- def >=(x: Double): Boolean = sys.error("stub")
+ def >=(x: Double): Boolean
/**
* Returns the bitwise OR of this value and `x`.
@@ -287,7 +289,7 @@ final class Char private extends AnyVal {
* // 11111010
* }}}
*/
- def |(x: Byte): Int = sys.error("stub")
+ def |(x: Byte): Int
/**
* Returns the bitwise OR of this value and `x`.
* @example {{{
@@ -298,7 +300,7 @@ final class Char private extends AnyVal {
* // 11111010
* }}}
*/
- def |(x: Short): Int = sys.error("stub")
+ def |(x: Short): Int
/**
* Returns the bitwise OR of this value and `x`.
* @example {{{
@@ -309,7 +311,7 @@ final class Char private extends AnyVal {
* // 11111010
* }}}
*/
- def |(x: Char): Int = sys.error("stub")
+ def |(x: Char): Int
/**
* Returns the bitwise OR of this value and `x`.
* @example {{{
@@ -320,7 +322,7 @@ final class Char private extends AnyVal {
* // 11111010
* }}}
*/
- def |(x: Int): Int = sys.error("stub")
+ def |(x: Int): Int
/**
* Returns the bitwise OR of this value and `x`.
* @example {{{
@@ -331,7 +333,7 @@ final class Char private extends AnyVal {
* // 11111010
* }}}
*/
- def |(x: Long): Long = sys.error("stub")
+ def |(x: Long): Long
/**
* Returns the bitwise AND of this value and `x`.
@@ -343,7 +345,7 @@ final class Char private extends AnyVal {
* // 10100000
* }}}
*/
- def &(x: Byte): Int = sys.error("stub")
+ def &(x: Byte): Int
/**
* Returns the bitwise AND of this value and `x`.
* @example {{{
@@ -354,7 +356,7 @@ final class Char private extends AnyVal {
* // 10100000
* }}}
*/
- def &(x: Short): Int = sys.error("stub")
+ def &(x: Short): Int
/**
* Returns the bitwise AND of this value and `x`.
* @example {{{
@@ -365,7 +367,7 @@ final class Char private extends AnyVal {
* // 10100000
* }}}
*/
- def &(x: Char): Int = sys.error("stub")
+ def &(x: Char): Int
/**
* Returns the bitwise AND of this value and `x`.
* @example {{{
@@ -376,7 +378,7 @@ final class Char private extends AnyVal {
* // 10100000
* }}}
*/
- def &(x: Int): Int = sys.error("stub")
+ def &(x: Int): Int
/**
* Returns the bitwise AND of this value and `x`.
* @example {{{
@@ -387,7 +389,7 @@ final class Char private extends AnyVal {
* // 10100000
* }}}
*/
- def &(x: Long): Long = sys.error("stub")
+ def &(x: Long): Long
/**
* Returns the bitwise XOR of this value and `x`.
@@ -399,7 +401,7 @@ final class Char private extends AnyVal {
* // 01011010
* }}}
*/
- def ^(x: Byte): Int = sys.error("stub")
+ def ^(x: Byte): Int
/**
* Returns the bitwise XOR of this value and `x`.
* @example {{{
@@ -410,7 +412,7 @@ final class Char private extends AnyVal {
* // 01011010
* }}}
*/
- def ^(x: Short): Int = sys.error("stub")
+ def ^(x: Short): Int
/**
* Returns the bitwise XOR of this value and `x`.
* @example {{{
@@ -421,7 +423,7 @@ final class Char private extends AnyVal {
* // 01011010
* }}}
*/
- def ^(x: Char): Int = sys.error("stub")
+ def ^(x: Char): Int
/**
* Returns the bitwise XOR of this value and `x`.
* @example {{{
@@ -432,7 +434,7 @@ final class Char private extends AnyVal {
* // 01011010
* }}}
*/
- def ^(x: Int): Int = sys.error("stub")
+ def ^(x: Int): Int
/**
* Returns the bitwise XOR of this value and `x`.
* @example {{{
@@ -443,157 +445,157 @@ final class Char private extends AnyVal {
* // 01011010
* }}}
*/
- def ^(x: Long): Long = sys.error("stub")
+ def ^(x: Long): Long
/**
* Returns the sum of this value and `x`.
*/
- def +(x: Byte): Int = sys.error("stub")
+ def +(x: Byte): Int
/**
* Returns the sum of this value and `x`.
*/
- def +(x: Short): Int = sys.error("stub")
+ def +(x: Short): Int
/**
* Returns the sum of this value and `x`.
*/
- def +(x: Char): Int = sys.error("stub")
+ def +(x: Char): Int
/**
* Returns the sum of this value and `x`.
*/
- def +(x: Int): Int = sys.error("stub")
+ def +(x: Int): Int
/**
* Returns the sum of this value and `x`.
*/
- def +(x: Long): Long = sys.error("stub")
+ def +(x: Long): Long
/**
* Returns the sum of this value and `x`.
*/
- def +(x: Float): Float = sys.error("stub")
+ def +(x: Float): Float
/**
* Returns the sum of this value and `x`.
*/
- def +(x: Double): Double = sys.error("stub")
+ def +(x: Double): Double
/**
* Returns the difference of this value and `x`.
*/
- def -(x: Byte): Int = sys.error("stub")
+ def -(x: Byte): Int
/**
* Returns the difference of this value and `x`.
*/
- def -(x: Short): Int = sys.error("stub")
+ def -(x: Short): Int
/**
* Returns the difference of this value and `x`.
*/
- def -(x: Char): Int = sys.error("stub")
+ def -(x: Char): Int
/**
* Returns the difference of this value and `x`.
*/
- def -(x: Int): Int = sys.error("stub")
+ def -(x: Int): Int
/**
* Returns the difference of this value and `x`.
*/
- def -(x: Long): Long = sys.error("stub")
+ def -(x: Long): Long
/**
* Returns the difference of this value and `x`.
*/
- def -(x: Float): Float = sys.error("stub")
+ def -(x: Float): Float
/**
* Returns the difference of this value and `x`.
*/
- def -(x: Double): Double = sys.error("stub")
+ def -(x: Double): Double
/**
* Returns the product of this value and `x`.
*/
- def *(x: Byte): Int = sys.error("stub")
+ def *(x: Byte): Int
/**
* Returns the product of this value and `x`.
*/
- def *(x: Short): Int = sys.error("stub")
+ def *(x: Short): Int
/**
* Returns the product of this value and `x`.
*/
- def *(x: Char): Int = sys.error("stub")
+ def *(x: Char): Int
/**
* Returns the product of this value and `x`.
*/
- def *(x: Int): Int = sys.error("stub")
+ def *(x: Int): Int
/**
* Returns the product of this value and `x`.
*/
- def *(x: Long): Long = sys.error("stub")
+ def *(x: Long): Long
/**
* Returns the product of this value and `x`.
*/
- def *(x: Float): Float = sys.error("stub")
+ def *(x: Float): Float
/**
* Returns the product of this value and `x`.
*/
- def *(x: Double): Double = sys.error("stub")
+ def *(x: Double): Double
/**
* Returns the quotient of this value and `x`.
*/
- def /(x: Byte): Int = sys.error("stub")
+ def /(x: Byte): Int
/**
* Returns the quotient of this value and `x`.
*/
- def /(x: Short): Int = sys.error("stub")
+ def /(x: Short): Int
/**
* Returns the quotient of this value and `x`.
*/
- def /(x: Char): Int = sys.error("stub")
+ def /(x: Char): Int
/**
* Returns the quotient of this value and `x`.
*/
- def /(x: Int): Int = sys.error("stub")
+ def /(x: Int): Int
/**
* Returns the quotient of this value and `x`.
*/
- def /(x: Long): Long = sys.error("stub")
+ def /(x: Long): Long
/**
* Returns the quotient of this value and `x`.
*/
- def /(x: Float): Float = sys.error("stub")
+ def /(x: Float): Float
/**
* Returns the quotient of this value and `x`.
*/
- def /(x: Double): Double = sys.error("stub")
+ def /(x: Double): Double
/**
* Returns the remainder of the division of this value by `x`.
*/
- def %(x: Byte): Int = sys.error("stub")
+ def %(x: Byte): Int
/**
* Returns the remainder of the division of this value by `x`.
*/
- def %(x: Short): Int = sys.error("stub")
+ def %(x: Short): Int
/**
* Returns the remainder of the division of this value by `x`.
*/
- def %(x: Char): Int = sys.error("stub")
+ def %(x: Char): Int
/**
* Returns the remainder of the division of this value by `x`.
*/
- def %(x: Int): Int = sys.error("stub")
+ def %(x: Int): Int
/**
* Returns the remainder of the division of this value by `x`.
*/
- def %(x: Long): Long = sys.error("stub")
+ def %(x: Long): Long
/**
* Returns the remainder of the division of this value by `x`.
*/
- def %(x: Float): Float = sys.error("stub")
+ def %(x: Float): Float
/**
* Returns the remainder of the division of this value by `x`.
*/
- def %(x: Double): Double = sys.error("stub")
+ def %(x: Double): Double
- override def getClass(): Class[Char] = sys.error("stub")
+ override def getClass(): Class[Char] = null
}
-object Char extends AnyValCompanion {
+object Char extends AnyValCompanion {
/** The smallest value representable as a Char.
*/
final val MinValue = java.lang.Character.MIN_VALUE
@@ -622,6 +624,9 @@ object Char extends AnyValCompanion {
/** The String representation of the scala.Char companion object.
*/
override def toString = "object scala.Char"
+
+ /** Language mandated coercions from Char to "wider" types.
+ */
implicit def char2int(x: Char): Int = x.toInt
implicit def char2long(x: Char): Long = x.toLong
implicit def char2float(x: Char): Float = x.toFloat
diff --git a/src/library/scala/Double.scala b/src/library/scala/Double.scala
index bb659b963a..2ff46c433d 100644
--- a/src/library/scala/Double.scala
+++ b/src/library/scala/Double.scala
@@ -10,6 +10,8 @@
package scala
+import language.implicitConversions
+
/** `Double`, a 64-bit IEEE-754 floating point number (equivalent to Java's `double` primitive type) is a
* subtype of [[scala.AnyVal]]. Instances of `Double` are not
* represented by an object in the underlying runtime system.
@@ -17,349 +19,349 @@ package scala
* There is an implicit conversion from [[scala.Double]] => [[scala.runtime.RichDouble]]
* which provides useful non-primitive operations.
*/
-final class Double private extends AnyVal {
- def toByte: Byte = sys.error("stub")
- def toShort: Short = sys.error("stub")
- def toChar: Char = sys.error("stub")
- def toInt: Int = sys.error("stub")
- def toLong: Long = sys.error("stub")
- def toFloat: Float = sys.error("stub")
- def toDouble: Double = sys.error("stub")
+final abstract class Double private extends AnyVal {
+ def toByte: Byte
+ def toShort: Short
+ def toChar: Char
+ def toInt: Int
+ def toLong: Long
+ def toFloat: Float
+ def toDouble: Double
/**
* Returns this value, unmodified.
*/
- def unary_+ : Double = sys.error("stub")
+ def unary_+ : Double
/**
* Returns the negation of this value.
*/
- def unary_- : Double = sys.error("stub")
+ def unary_- : Double
- def +(x: String): String = sys.error("stub")
+ def +(x: String): String
/**
* Returns `true` if this value is equal to x, `false` otherwise.
*/
- def ==(x: Byte): Boolean = sys.error("stub")
+ def ==(x: Byte): Boolean
/**
* Returns `true` if this value is equal to x, `false` otherwise.
*/
- def ==(x: Short): Boolean = sys.error("stub")
+ def ==(x: Short): Boolean
/**
* Returns `true` if this value is equal to x, `false` otherwise.
*/
- def ==(x: Char): Boolean = sys.error("stub")
+ def ==(x: Char): Boolean
/**
* Returns `true` if this value is equal to x, `false` otherwise.
*/
- def ==(x: Int): Boolean = sys.error("stub")
+ def ==(x: Int): Boolean
/**
* Returns `true` if this value is equal to x, `false` otherwise.
*/
- def ==(x: Long): Boolean = sys.error("stub")
+ def ==(x: Long): Boolean
/**
* Returns `true` if this value is equal to x, `false` otherwise.
*/
- def ==(x: Float): Boolean = sys.error("stub")
+ def ==(x: Float): Boolean
/**
* Returns `true` if this value is equal to x, `false` otherwise.
*/
- def ==(x: Double): Boolean = sys.error("stub")
+ def ==(x: Double): Boolean
/**
* Returns `true` if this value is not equal to x, `false` otherwise.
*/
- def !=(x: Byte): Boolean = sys.error("stub")
+ def !=(x: Byte): Boolean
/**
* Returns `true` if this value is not equal to x, `false` otherwise.
*/
- def !=(x: Short): Boolean = sys.error("stub")
+ def !=(x: Short): Boolean
/**
* Returns `true` if this value is not equal to x, `false` otherwise.
*/
- def !=(x: Char): Boolean = sys.error("stub")
+ def !=(x: Char): Boolean
/**
* Returns `true` if this value is not equal to x, `false` otherwise.
*/
- def !=(x: Int): Boolean = sys.error("stub")
+ def !=(x: Int): Boolean
/**
* Returns `true` if this value is not equal to x, `false` otherwise.
*/
- def !=(x: Long): Boolean = sys.error("stub")
+ def !=(x: Long): Boolean
/**
* Returns `true` if this value is not equal to x, `false` otherwise.
*/
- def !=(x: Float): Boolean = sys.error("stub")
+ def !=(x: Float): Boolean
/**
* Returns `true` if this value is not equal to x, `false` otherwise.
*/
- def !=(x: Double): Boolean = sys.error("stub")
+ def !=(x: Double): Boolean
/**
* Returns `true` if this value is less than x, `false` otherwise.
*/
- def <(x: Byte): Boolean = sys.error("stub")
+ def <(x: Byte): Boolean
/**
* Returns `true` if this value is less than x, `false` otherwise.
*/
- def <(x: Short): Boolean = sys.error("stub")
+ def <(x: Short): Boolean
/**
* Returns `true` if this value is less than x, `false` otherwise.
*/
- def <(x: Char): Boolean = sys.error("stub")
+ def <(x: Char): Boolean
/**
* Returns `true` if this value is less than x, `false` otherwise.
*/
- def <(x: Int): Boolean = sys.error("stub")
+ def <(x: Int): Boolean
/**
* Returns `true` if this value is less than x, `false` otherwise.
*/
- def <(x: Long): Boolean = sys.error("stub")
+ def <(x: Long): Boolean
/**
* Returns `true` if this value is less than x, `false` otherwise.
*/
- def <(x: Float): Boolean = sys.error("stub")
+ def <(x: Float): Boolean
/**
* Returns `true` if this value is less than x, `false` otherwise.
*/
- def <(x: Double): Boolean = sys.error("stub")
+ def <(x: Double): Boolean
/**
* Returns `true` if this value is less than or equal to x, `false` otherwise.
*/
- def <=(x: Byte): Boolean = sys.error("stub")
+ def <=(x: Byte): Boolean
/**
* Returns `true` if this value is less than or equal to x, `false` otherwise.
*/
- def <=(x: Short): Boolean = sys.error("stub")
+ def <=(x: Short): Boolean
/**
* Returns `true` if this value is less than or equal to x, `false` otherwise.
*/
- def <=(x: Char): Boolean = sys.error("stub")
+ def <=(x: Char): Boolean
/**
* Returns `true` if this value is less than or equal to x, `false` otherwise.
*/
- def <=(x: Int): Boolean = sys.error("stub")
+ def <=(x: Int): Boolean
/**
* Returns `true` if this value is less than or equal to x, `false` otherwise.
*/
- def <=(x: Long): Boolean = sys.error("stub")
+ def <=(x: Long): Boolean
/**
* Returns `true` if this value is less than or equal to x, `false` otherwise.
*/
- def <=(x: Float): Boolean = sys.error("stub")
+ def <=(x: Float): Boolean
/**
* Returns `true` if this value is less than or equal to x, `false` otherwise.
*/
- def <=(x: Double): Boolean = sys.error("stub")
+ def <=(x: Double): Boolean
/**
* Returns `true` if this value is greater than x, `false` otherwise.
*/
- def >(x: Byte): Boolean = sys.error("stub")
+ def >(x: Byte): Boolean
/**
* Returns `true` if this value is greater than x, `false` otherwise.
*/
- def >(x: Short): Boolean = sys.error("stub")
+ def >(x: Short): Boolean
/**
* Returns `true` if this value is greater than x, `false` otherwise.
*/
- def >(x: Char): Boolean = sys.error("stub")
+ def >(x: Char): Boolean
/**
* Returns `true` if this value is greater than x, `false` otherwise.
*/
- def >(x: Int): Boolean = sys.error("stub")
+ def >(x: Int): Boolean
/**
* Returns `true` if this value is greater than x, `false` otherwise.
*/
- def >(x: Long): Boolean = sys.error("stub")
+ def >(x: Long): Boolean
/**
* Returns `true` if this value is greater than x, `false` otherwise.
*/
- def >(x: Float): Boolean = sys.error("stub")
+ def >(x: Float): Boolean
/**
* Returns `true` if this value is greater than x, `false` otherwise.
*/
- def >(x: Double): Boolean = sys.error("stub")
+ def >(x: Double): Boolean
/**
* Returns `true` if this value is greater than or equal to x, `false` otherwise.
*/
- def >=(x: Byte): Boolean = sys.error("stub")
+ def >=(x: Byte): Boolean
/**
* Returns `true` if this value is greater than or equal to x, `false` otherwise.
*/
- def >=(x: Short): Boolean = sys.error("stub")
+ def >=(x: Short): Boolean
/**
* Returns `true` if this value is greater than or equal to x, `false` otherwise.
*/
- def >=(x: Char): Boolean = sys.error("stub")
+ def >=(x: Char): Boolean
/**
* Returns `true` if this value is greater than or equal to x, `false` otherwise.
*/
- def >=(x: Int): Boolean = sys.error("stub")
+ def >=(x: Int): Boolean
/**
* Returns `true` if this value is greater than or equal to x, `false` otherwise.
*/
- def >=(x: Long): Boolean = sys.error("stub")
+ def >=(x: Long): Boolean
/**
* Returns `true` if this value is greater than or equal to x, `false` otherwise.
*/
- def >=(x: Float): Boolean = sys.error("stub")
+ def >=(x: Float): Boolean
/**
* Returns `true` if this value is greater than or equal to x, `false` otherwise.
*/
- def >=(x: Double): Boolean = sys.error("stub")
+ def >=(x: Double): Boolean
/**
* Returns the sum of this value and `x`.
*/
- def +(x: Byte): Double = sys.error("stub")
+ def +(x: Byte): Double
/**
* Returns the sum of this value and `x`.
*/
- def +(x: Short): Double = sys.error("stub")
+ def +(x: Short): Double
/**
* Returns the sum of this value and `x`.
*/
- def +(x: Char): Double = sys.error("stub")
+ def +(x: Char): Double
/**
* Returns the sum of this value and `x`.
*/
- def +(x: Int): Double = sys.error("stub")
+ def +(x: Int): Double
/**
* Returns the sum of this value and `x`.
*/
- def +(x: Long): Double = sys.error("stub")
+ def +(x: Long): Double
/**
* Returns the sum of this value and `x`.
*/
- def +(x: Float): Double = sys.error("stub")
+ def +(x: Float): Double
/**
* Returns the sum of this value and `x`.
*/
- def +(x: Double): Double = sys.error("stub")
+ def +(x: Double): Double
/**
* Returns the difference of this value and `x`.
*/
- def -(x: Byte): Double = sys.error("stub")
+ def -(x: Byte): Double
/**
* Returns the difference of this value and `x`.
*/
- def -(x: Short): Double = sys.error("stub")
+ def -(x: Short): Double
/**
* Returns the difference of this value and `x`.
*/
- def -(x: Char): Double = sys.error("stub")
+ def -(x: Char): Double
/**
* Returns the difference of this value and `x`.
*/
- def -(x: Int): Double = sys.error("stub")
+ def -(x: Int): Double
/**
* Returns the difference of this value and `x`.
*/
- def -(x: Long): Double = sys.error("stub")
+ def -(x: Long): Double
/**
* Returns the difference of this value and `x`.
*/
- def -(x: Float): Double = sys.error("stub")
+ def -(x: Float): Double
/**
* Returns the difference of this value and `x`.
*/
- def -(x: Double): Double = sys.error("stub")
+ def -(x: Double): Double
/**
* Returns the product of this value and `x`.
*/
- def *(x: Byte): Double = sys.error("stub")
+ def *(x: Byte): Double
/**
* Returns the product of this value and `x`.
*/
- def *(x: Short): Double = sys.error("stub")
+ def *(x: Short): Double
/**
* Returns the product of this value and `x`.
*/
- def *(x: Char): Double = sys.error("stub")
+ def *(x: Char): Double
/**
* Returns the product of this value and `x`.
*/
- def *(x: Int): Double = sys.error("stub")
+ def *(x: Int): Double
/**
* Returns the product of this value and `x`.
*/
- def *(x: Long): Double = sys.error("stub")
+ def *(x: Long): Double
/**
* Returns the product of this value and `x`.
*/
- def *(x: Float): Double = sys.error("stub")
+ def *(x: Float): Double
/**
* Returns the product of this value and `x`.
*/
- def *(x: Double): Double = sys.error("stub")
+ def *(x: Double): Double
/**
* Returns the quotient of this value and `x`.
*/
- def /(x: Byte): Double = sys.error("stub")
+ def /(x: Byte): Double
/**
* Returns the quotient of this value and `x`.
*/
- def /(x: Short): Double = sys.error("stub")
+ def /(x: Short): Double
/**
* Returns the quotient of this value and `x`.
*/
- def /(x: Char): Double = sys.error("stub")
+ def /(x: Char): Double
/**
* Returns the quotient of this value and `x`.
*/
- def /(x: Int): Double = sys.error("stub")
+ def /(x: Int): Double
/**
* Returns the quotient of this value and `x`.
*/
- def /(x: Long): Double = sys.error("stub")
+ def /(x: Long): Double
/**
* Returns the quotient of this value and `x`.
*/
- def /(x: Float): Double = sys.error("stub")
+ def /(x: Float): Double
/**
* Returns the quotient of this value and `x`.
*/
- def /(x: Double): Double = sys.error("stub")
+ def /(x: Double): Double
/**
* Returns the remainder of the division of this value by `x`.
*/
- def %(x: Byte): Double = sys.error("stub")
+ def %(x: Byte): Double
/**
* Returns the remainder of the division of this value by `x`.
*/
- def %(x: Short): Double = sys.error("stub")
+ def %(x: Short): Double
/**
* Returns the remainder of the division of this value by `x`.
*/
- def %(x: Char): Double = sys.error("stub")
+ def %(x: Char): Double
/**
* Returns the remainder of the division of this value by `x`.
*/
- def %(x: Int): Double = sys.error("stub")
+ def %(x: Int): Double
/**
* Returns the remainder of the division of this value by `x`.
*/
- def %(x: Long): Double = sys.error("stub")
+ def %(x: Long): Double
/**
* Returns the remainder of the division of this value by `x`.
*/
- def %(x: Float): Double = sys.error("stub")
+ def %(x: Float): Double
/**
* Returns the remainder of the division of this value by `x`.
*/
- def %(x: Double): Double = sys.error("stub")
+ def %(x: Double): Double
- override def getClass(): Class[Double] = sys.error("stub")
+ override def getClass(): Class[Double] = null
}
-object Double extends AnyValCompanion {
+object Double extends AnyValCompanion {
/** The smallest positive value greater than 0.0d which is
* representable as a Double.
*/
diff --git a/src/library/scala/Float.scala b/src/library/scala/Float.scala
index bb03581062..bd7a07fece 100644
--- a/src/library/scala/Float.scala
+++ b/src/library/scala/Float.scala
@@ -10,6 +10,8 @@
package scala
+import language.implicitConversions
+
/** `Float`, a 32-bit IEEE-754 floating point number (equivalent to Java's `float` primitive type) is a
* subtype of [[scala.AnyVal]]. Instances of `Float` are not
* represented by an object in the underlying runtime system.
@@ -17,349 +19,349 @@ package scala
* There is an implicit conversion from [[scala.Float]] => [[scala.runtime.RichFloat]]
* which provides useful non-primitive operations.
*/
-final class Float private extends AnyVal {
- def toByte: Byte = sys.error("stub")
- def toShort: Short = sys.error("stub")
- def toChar: Char = sys.error("stub")
- def toInt: Int = sys.error("stub")
- def toLong: Long = sys.error("stub")
- def toFloat: Float = sys.error("stub")
- def toDouble: Double = sys.error("stub")
+final abstract class Float private extends AnyVal {
+ def toByte: Byte
+ def toShort: Short
+ def toChar: Char
+ def toInt: Int
+ def toLong: Long
+ def toFloat: Float
+ def toDouble: Double
/**
* Returns this value, unmodified.
*/
- def unary_+ : Float = sys.error("stub")
+ def unary_+ : Float
/**
* Returns the negation of this value.
*/
- def unary_- : Float = sys.error("stub")
+ def unary_- : Float
- def +(x: String): String = sys.error("stub")
+ def +(x: String): String
/**
* Returns `true` if this value is equal to x, `false` otherwise.
*/
- def ==(x: Byte): Boolean = sys.error("stub")
+ def ==(x: Byte): Boolean
/**
* Returns `true` if this value is equal to x, `false` otherwise.
*/
- def ==(x: Short): Boolean = sys.error("stub")
+ def ==(x: Short): Boolean
/**
* Returns `true` if this value is equal to x, `false` otherwise.
*/
- def ==(x: Char): Boolean = sys.error("stub")
+ def ==(x: Char): Boolean
/**
* Returns `true` if this value is equal to x, `false` otherwise.
*/
- def ==(x: Int): Boolean = sys.error("stub")
+ def ==(x: Int): Boolean
/**
* Returns `true` if this value is equal to x, `false` otherwise.
*/
- def ==(x: Long): Boolean = sys.error("stub")
+ def ==(x: Long): Boolean
/**
* Returns `true` if this value is equal to x, `false` otherwise.
*/
- def ==(x: Float): Boolean = sys.error("stub")
+ def ==(x: Float): Boolean
/**
* Returns `true` if this value is equal to x, `false` otherwise.
*/
- def ==(x: Double): Boolean = sys.error("stub")
+ def ==(x: Double): Boolean
/**
* Returns `true` if this value is not equal to x, `false` otherwise.
*/
- def !=(x: Byte): Boolean = sys.error("stub")
+ def !=(x: Byte): Boolean
/**
* Returns `true` if this value is not equal to x, `false` otherwise.
*/
- def !=(x: Short): Boolean = sys.error("stub")
+ def !=(x: Short): Boolean
/**
* Returns `true` if this value is not equal to x, `false` otherwise.
*/
- def !=(x: Char): Boolean = sys.error("stub")
+ def !=(x: Char): Boolean
/**
* Returns `true` if this value is not equal to x, `false` otherwise.
*/
- def !=(x: Int): Boolean = sys.error("stub")
+ def !=(x: Int): Boolean
/**
* Returns `true` if this value is not equal to x, `false` otherwise.
*/
- def !=(x: Long): Boolean = sys.error("stub")
+ def !=(x: Long): Boolean
/**
* Returns `true` if this value is not equal to x, `false` otherwise.
*/
- def !=(x: Float): Boolean = sys.error("stub")
+ def !=(x: Float): Boolean
/**
* Returns `true` if this value is not equal to x, `false` otherwise.
*/
- def !=(x: Double): Boolean = sys.error("stub")
+ def !=(x: Double): Boolean
/**
* Returns `true` if this value is less than x, `false` otherwise.
*/
- def <(x: Byte): Boolean = sys.error("stub")
+ def <(x: Byte): Boolean
/**
* Returns `true` if this value is less than x, `false` otherwise.
*/
- def <(x: Short): Boolean = sys.error("stub")
+ def <(x: Short): Boolean
/**
* Returns `true` if this value is less than x, `false` otherwise.
*/
- def <(x: Char): Boolean = sys.error("stub")
+ def <(x: Char): Boolean
/**
* Returns `true` if this value is less than x, `false` otherwise.
*/
- def <(x: Int): Boolean = sys.error("stub")
+ def <(x: Int): Boolean
/**
* Returns `true` if this value is less than x, `false` otherwise.
*/
- def <(x: Long): Boolean = sys.error("stub")
+ def <(x: Long): Boolean
/**
* Returns `true` if this value is less than x, `false` otherwise.
*/
- def <(x: Float): Boolean = sys.error("stub")
+ def <(x: Float): Boolean
/**
* Returns `true` if this value is less than x, `false` otherwise.
*/
- def <(x: Double): Boolean = sys.error("stub")
+ def <(x: Double): Boolean
/**
* Returns `true` if this value is less than or equal to x, `false` otherwise.
*/
- def <=(x: Byte): Boolean = sys.error("stub")
+ def <=(x: Byte): Boolean
/**
* Returns `true` if this value is less than or equal to x, `false` otherwise.
*/
- def <=(x: Short): Boolean = sys.error("stub")
+ def <=(x: Short): Boolean
/**
* Returns `true` if this value is less than or equal to x, `false` otherwise.
*/
- def <=(x: Char): Boolean = sys.error("stub")
+ def <=(x: Char): Boolean
/**
* Returns `true` if this value is less than or equal to x, `false` otherwise.
*/
- def <=(x: Int): Boolean = sys.error("stub")
+ def <=(x: Int): Boolean
/**
* Returns `true` if this value is less than or equal to x, `false` otherwise.
*/
- def <=(x: Long): Boolean = sys.error("stub")
+ def <=(x: Long): Boolean
/**
* Returns `true` if this value is less than or equal to x, `false` otherwise.
*/
- def <=(x: Float): Boolean = sys.error("stub")
+ def <=(x: Float): Boolean
/**
* Returns `true` if this value is less than or equal to x, `false` otherwise.
*/
- def <=(x: Double): Boolean = sys.error("stub")
+ def <=(x: Double): Boolean
/**
* Returns `true` if this value is greater than x, `false` otherwise.
*/
- def >(x: Byte): Boolean = sys.error("stub")
+ def >(x: Byte): Boolean
/**
* Returns `true` if this value is greater than x, `false` otherwise.
*/
- def >(x: Short): Boolean = sys.error("stub")
+ def >(x: Short): Boolean
/**
* Returns `true` if this value is greater than x, `false` otherwise.
*/
- def >(x: Char): Boolean = sys.error("stub")
+ def >(x: Char): Boolean
/**
* Returns `true` if this value is greater than x, `false` otherwise.
*/
- def >(x: Int): Boolean = sys.error("stub")
+ def >(x: Int): Boolean
/**
* Returns `true` if this value is greater than x, `false` otherwise.
*/
- def >(x: Long): Boolean = sys.error("stub")
+ def >(x: Long): Boolean
/**
* Returns `true` if this value is greater than x, `false` otherwise.
*/
- def >(x: Float): Boolean = sys.error("stub")
+ def >(x: Float): Boolean
/**
* Returns `true` if this value is greater than x, `false` otherwise.
*/
- def >(x: Double): Boolean = sys.error("stub")
+ def >(x: Double): Boolean
/**
* Returns `true` if this value is greater than or equal to x, `false` otherwise.
*/
- def >=(x: Byte): Boolean = sys.error("stub")
+ def >=(x: Byte): Boolean
/**
* Returns `true` if this value is greater than or equal to x, `false` otherwise.
*/
- def >=(x: Short): Boolean = sys.error("stub")
+ def >=(x: Short): Boolean
/**
* Returns `true` if this value is greater than or equal to x, `false` otherwise.
*/
- def >=(x: Char): Boolean = sys.error("stub")
+ def >=(x: Char): Boolean
/**
* Returns `true` if this value is greater than or equal to x, `false` otherwise.
*/
- def >=(x: Int): Boolean = sys.error("stub")
+ def >=(x: Int): Boolean
/**
* Returns `true` if this value is greater than or equal to x, `false` otherwise.
*/
- def >=(x: Long): Boolean = sys.error("stub")
+ def >=(x: Long): Boolean
/**
* Returns `true` if this value is greater than or equal to x, `false` otherwise.
*/
- def >=(x: Float): Boolean = sys.error("stub")
+ def >=(x: Float): Boolean
/**
* Returns `true` if this value is greater than or equal to x, `false` otherwise.
*/
- def >=(x: Double): Boolean = sys.error("stub")
+ def >=(x: Double): Boolean
/**
* Returns the sum of this value and `x`.
*/
- def +(x: Byte): Float = sys.error("stub")
+ def +(x: Byte): Float
/**
* Returns the sum of this value and `x`.
*/
- def +(x: Short): Float = sys.error("stub")
+ def +(x: Short): Float
/**
* Returns the sum of this value and `x`.
*/
- def +(x: Char): Float = sys.error("stub")
+ def +(x: Char): Float
/**
* Returns the sum of this value and `x`.
*/
- def +(x: Int): Float = sys.error("stub")
+ def +(x: Int): Float
/**
* Returns the sum of this value and `x`.
*/
- def +(x: Long): Float = sys.error("stub")
+ def +(x: Long): Float
/**
* Returns the sum of this value and `x`.
*/
- def +(x: Float): Float = sys.error("stub")
+ def +(x: Float): Float
/**
* Returns the sum of this value and `x`.
*/
- def +(x: Double): Double = sys.error("stub")
+ def +(x: Double): Double
/**
* Returns the difference of this value and `x`.
*/
- def -(x: Byte): Float = sys.error("stub")
+ def -(x: Byte): Float
/**
* Returns the difference of this value and `x`.
*/
- def -(x: Short): Float = sys.error("stub")
+ def -(x: Short): Float
/**
* Returns the difference of this value and `x`.
*/
- def -(x: Char): Float = sys.error("stub")
+ def -(x: Char): Float
/**
* Returns the difference of this value and `x`.
*/
- def -(x: Int): Float = sys.error("stub")
+ def -(x: Int): Float
/**
* Returns the difference of this value and `x`.
*/
- def -(x: Long): Float = sys.error("stub")
+ def -(x: Long): Float
/**
* Returns the difference of this value and `x`.
*/
- def -(x: Float): Float = sys.error("stub")
+ def -(x: Float): Float
/**
* Returns the difference of this value and `x`.
*/
- def -(x: Double): Double = sys.error("stub")
+ def -(x: Double): Double
/**
* Returns the product of this value and `x`.
*/
- def *(x: Byte): Float = sys.error("stub")
+ def *(x: Byte): Float
/**
* Returns the product of this value and `x`.
*/
- def *(x: Short): Float = sys.error("stub")
+ def *(x: Short): Float
/**
* Returns the product of this value and `x`.
*/
- def *(x: Char): Float = sys.error("stub")
+ def *(x: Char): Float
/**
* Returns the product of this value and `x`.
*/
- def *(x: Int): Float = sys.error("stub")
+ def *(x: Int): Float
/**
* Returns the product of this value and `x`.
*/
- def *(x: Long): Float = sys.error("stub")
+ def *(x: Long): Float
/**
* Returns the product of this value and `x`.
*/
- def *(x: Float): Float = sys.error("stub")
+ def *(x: Float): Float
/**
* Returns the product of this value and `x`.
*/
- def *(x: Double): Double = sys.error("stub")
+ def *(x: Double): Double
/**
* Returns the quotient of this value and `x`.
*/
- def /(x: Byte): Float = sys.error("stub")
+ def /(x: Byte): Float
/**
* Returns the quotient of this value and `x`.
*/
- def /(x: Short): Float = sys.error("stub")
+ def /(x: Short): Float
/**
* Returns the quotient of this value and `x`.
*/
- def /(x: Char): Float = sys.error("stub")
+ def /(x: Char): Float
/**
* Returns the quotient of this value and `x`.
*/
- def /(x: Int): Float = sys.error("stub")
+ def /(x: Int): Float
/**
* Returns the quotient of this value and `x`.
*/
- def /(x: Long): Float = sys.error("stub")
+ def /(x: Long): Float
/**
* Returns the quotient of this value and `x`.
*/
- def /(x: Float): Float = sys.error("stub")
+ def /(x: Float): Float
/**
* Returns the quotient of this value and `x`.
*/
- def /(x: Double): Double = sys.error("stub")
+ def /(x: Double): Double
/**
* Returns the remainder of the division of this value by `x`.
*/
- def %(x: Byte): Float = sys.error("stub")
+ def %(x: Byte): Float
/**
* Returns the remainder of the division of this value by `x`.
*/
- def %(x: Short): Float = sys.error("stub")
+ def %(x: Short): Float
/**
* Returns the remainder of the division of this value by `x`.
*/
- def %(x: Char): Float = sys.error("stub")
+ def %(x: Char): Float
/**
* Returns the remainder of the division of this value by `x`.
*/
- def %(x: Int): Float = sys.error("stub")
+ def %(x: Int): Float
/**
* Returns the remainder of the division of this value by `x`.
*/
- def %(x: Long): Float = sys.error("stub")
+ def %(x: Long): Float
/**
* Returns the remainder of the division of this value by `x`.
*/
- def %(x: Float): Float = sys.error("stub")
+ def %(x: Float): Float
/**
* Returns the remainder of the division of this value by `x`.
*/
- def %(x: Double): Double = sys.error("stub")
+ def %(x: Double): Double
- override def getClass(): Class[Float] = sys.error("stub")
+ override def getClass(): Class[Float] = null
}
-object Float extends AnyValCompanion {
+object Float extends AnyValCompanion {
/** The smallest positive value greater than 0.0f which is
* representable as a Float.
*/
@@ -401,6 +403,9 @@ object Float extends AnyValCompanion {
/** The String representation of the scala.Float companion object.
*/
override def toString = "object scala.Float"
+
+ /** Language mandated coercions from Float to "wider" types.
+ */
implicit def float2double(x: Float): Double = x.toDouble
}
diff --git a/src/library/scala/Int.scala b/src/library/scala/Int.scala
index d5d7ef011d..b2a4f93253 100644
--- a/src/library/scala/Int.scala
+++ b/src/library/scala/Int.scala
@@ -10,6 +10,8 @@
package scala
+import language.implicitConversions
+
/** `Int`, a 32-bit signed integer (equivalent to Java's `int` primitive type) is a
* subtype of [[scala.AnyVal]]. Instances of `Int` are not
* represented by an object in the underlying runtime system.
@@ -17,14 +19,14 @@ package scala
* There is an implicit conversion from [[scala.Int]] => [[scala.runtime.RichInt]]
* which provides useful non-primitive operations.
*/
-final class Int private extends AnyVal {
- def toByte: Byte = sys.error("stub")
- def toShort: Short = sys.error("stub")
- def toChar: Char = sys.error("stub")
- def toInt: Int = sys.error("stub")
- def toLong: Long = sys.error("stub")
- def toFloat: Float = sys.error("stub")
- def toDouble: Double = sys.error("stub")
+final abstract class Int private extends AnyVal {
+ def toByte: Byte
+ def toShort: Short
+ def toChar: Char
+ def toInt: Int
+ def toLong: Long
+ def toFloat: Float
+ def toDouble: Double
/**
* Returns the bitwise negation of this value.
@@ -34,30 +36,30 @@ final class Int private extends AnyVal {
* // 11111010
* }}}
*/
- def unary_~ : Int = sys.error("stub")
+ def unary_~ : Int
/**
* Returns this value, unmodified.
*/
- def unary_+ : Int = sys.error("stub")
+ def unary_+ : Int
/**
* Returns the negation of this value.
*/
- def unary_- : Int = sys.error("stub")
+ def unary_- : Int
- def +(x: String): String = sys.error("stub")
+ def +(x: String): String
/**
* Returns this value bit-shifted left by the specified number of bits,
* filling in the new right bits with zeroes.
* @example {{{ 6 << 3 == 48 // in binary: 0110 << 3 == 0110000 }}}
*/
- def <<(x: Int): Int = sys.error("stub")
+ def <<(x: Int): Int
/**
* Returns this value bit-shifted left by the specified number of bits,
* filling in the new right bits with zeroes.
* @example {{{ 6 << 3 == 48 // in binary: 0110 << 3 == 0110000 }}}
*/
- def <<(x: Long): Int = sys.error("stub")
+ def <<(x: Long): Int
/**
* Returns this value bit-shifted right by the specified number of bits,
* filling the new left bits with zeroes.
@@ -68,7 +70,7 @@ final class Int private extends AnyVal {
* // 00011111 11111111 11111111 11111101
* }}}
*/
- def >>>(x: Int): Int = sys.error("stub")
+ def >>>(x: Int): Int
/**
* Returns this value bit-shifted right by the specified number of bits,
* filling the new left bits with zeroes.
@@ -79,7 +81,7 @@ final class Int private extends AnyVal {
* // 00011111 11111111 11111111 11111101
* }}}
*/
- def >>>(x: Long): Int = sys.error("stub")
+ def >>>(x: Long): Int
/**
* Returns this value bit-shifted left by the specified number of bits,
* filling in the right bits with the same value as the left-most bit of this.
@@ -90,7 +92,7 @@ final class Int private extends AnyVal {
* // 11111111 11111111 11111111 11111101
* }}}
*/
- def >>(x: Int): Int = sys.error("stub")
+ def >>(x: Int): Int
/**
* Returns this value bit-shifted left by the specified number of bits,
* filling in the right bits with the same value as the left-most bit of this.
@@ -101,181 +103,181 @@ final class Int private extends AnyVal {
* // 11111111 11111111 11111111 11111101
* }}}
*/
- def >>(x: Long): Int = sys.error("stub")
+ def >>(x: Long): Int
/**
* Returns `true` if this value is equal to x, `false` otherwise.
*/
- def ==(x: Byte): Boolean = sys.error("stub")
+ def ==(x: Byte): Boolean
/**
* Returns `true` if this value is equal to x, `false` otherwise.
*/
- def ==(x: Short): Boolean = sys.error("stub")
+ def ==(x: Short): Boolean
/**
* Returns `true` if this value is equal to x, `false` otherwise.
*/
- def ==(x: Char): Boolean = sys.error("stub")
+ def ==(x: Char): Boolean
/**
* Returns `true` if this value is equal to x, `false` otherwise.
*/
- def ==(x: Int): Boolean = sys.error("stub")
+ def ==(x: Int): Boolean
/**
* Returns `true` if this value is equal to x, `false` otherwise.
*/
- def ==(x: Long): Boolean = sys.error("stub")
+ def ==(x: Long): Boolean
/**
* Returns `true` if this value is equal to x, `false` otherwise.
*/
- def ==(x: Float): Boolean = sys.error("stub")
+ def ==(x: Float): Boolean
/**
* Returns `true` if this value is equal to x, `false` otherwise.
*/
- def ==(x: Double): Boolean = sys.error("stub")
+ def ==(x: Double): Boolean
/**
* Returns `true` if this value is not equal to x, `false` otherwise.
*/
- def !=(x: Byte): Boolean = sys.error("stub")
+ def !=(x: Byte): Boolean
/**
* Returns `true` if this value is not equal to x, `false` otherwise.
*/
- def !=(x: Short): Boolean = sys.error("stub")
+ def !=(x: Short): Boolean
/**
* Returns `true` if this value is not equal to x, `false` otherwise.
*/
- def !=(x: Char): Boolean = sys.error("stub")
+ def !=(x: Char): Boolean
/**
* Returns `true` if this value is not equal to x, `false` otherwise.
*/
- def !=(x: Int): Boolean = sys.error("stub")
+ def !=(x: Int): Boolean
/**
* Returns `true` if this value is not equal to x, `false` otherwise.
*/
- def !=(x: Long): Boolean = sys.error("stub")
+ def !=(x: Long): Boolean
/**
* Returns `true` if this value is not equal to x, `false` otherwise.
*/
- def !=(x: Float): Boolean = sys.error("stub")
+ def !=(x: Float): Boolean
/**
* Returns `true` if this value is not equal to x, `false` otherwise.
*/
- def !=(x: Double): Boolean = sys.error("stub")
+ def !=(x: Double): Boolean
/**
* Returns `true` if this value is less than x, `false` otherwise.
*/
- def <(x: Byte): Boolean = sys.error("stub")
+ def <(x: Byte): Boolean
/**
* Returns `true` if this value is less than x, `false` otherwise.
*/
- def <(x: Short): Boolean = sys.error("stub")
+ def <(x: Short): Boolean
/**
* Returns `true` if this value is less than x, `false` otherwise.
*/
- def <(x: Char): Boolean = sys.error("stub")
+ def <(x: Char): Boolean
/**
* Returns `true` if this value is less than x, `false` otherwise.
*/
- def <(x: Int): Boolean = sys.error("stub")
+ def <(x: Int): Boolean
/**
* Returns `true` if this value is less than x, `false` otherwise.
*/
- def <(x: Long): Boolean = sys.error("stub")
+ def <(x: Long): Boolean
/**
* Returns `true` if this value is less than x, `false` otherwise.
*/
- def <(x: Float): Boolean = sys.error("stub")
+ def <(x: Float): Boolean
/**
* Returns `true` if this value is less than x, `false` otherwise.
*/
- def <(x: Double): Boolean = sys.error("stub")
+ def <(x: Double): Boolean
/**
* Returns `true` if this value is less than or equal to x, `false` otherwise.
*/
- def <=(x: Byte): Boolean = sys.error("stub")
+ def <=(x: Byte): Boolean
/**
* Returns `true` if this value is less than or equal to x, `false` otherwise.
*/
- def <=(x: Short): Boolean = sys.error("stub")
+ def <=(x: Short): Boolean
/**
* Returns `true` if this value is less than or equal to x, `false` otherwise.
*/
- def <=(x: Char): Boolean = sys.error("stub")
+ def <=(x: Char): Boolean
/**
* Returns `true` if this value is less than or equal to x, `false` otherwise.
*/
- def <=(x: Int): Boolean = sys.error("stub")
+ def <=(x: Int): Boolean
/**
* Returns `true` if this value is less than or equal to x, `false` otherwise.
*/
- def <=(x: Long): Boolean = sys.error("stub")
+ def <=(x: Long): Boolean
/**
* Returns `true` if this value is less than or equal to x, `false` otherwise.
*/
- def <=(x: Float): Boolean = sys.error("stub")
+ def <=(x: Float): Boolean
/**
* Returns `true` if this value is less than or equal to x, `false` otherwise.
*/
- def <=(x: Double): Boolean = sys.error("stub")
+ def <=(x: Double): Boolean
/**
* Returns `true` if this value is greater than x, `false` otherwise.
*/
- def >(x: Byte): Boolean = sys.error("stub")
+ def >(x: Byte): Boolean
/**
* Returns `true` if this value is greater than x, `false` otherwise.
*/
- def >(x: Short): Boolean = sys.error("stub")
+ def >(x: Short): Boolean
/**
* Returns `true` if this value is greater than x, `false` otherwise.
*/
- def >(x: Char): Boolean = sys.error("stub")
+ def >(x: Char): Boolean
/**
* Returns `true` if this value is greater than x, `false` otherwise.
*/
- def >(x: Int): Boolean = sys.error("stub")
+ def >(x: Int): Boolean
/**
* Returns `true` if this value is greater than x, `false` otherwise.
*/
- def >(x: Long): Boolean = sys.error("stub")
+ def >(x: Long): Boolean
/**
* Returns `true` if this value is greater than x, `false` otherwise.
*/
- def >(x: Float): Boolean = sys.error("stub")
+ def >(x: Float): Boolean
/**
* Returns `true` if this value is greater than x, `false` otherwise.
*/
- def >(x: Double): Boolean = sys.error("stub")
+ def >(x: Double): Boolean
/**
* Returns `true` if this value is greater than or equal to x, `false` otherwise.
*/
- def >=(x: Byte): Boolean = sys.error("stub")
+ def >=(x: Byte): Boolean
/**
* Returns `true` if this value is greater than or equal to x, `false` otherwise.
*/
- def >=(x: Short): Boolean = sys.error("stub")
+ def >=(x: Short): Boolean
/**
* Returns `true` if this value is greater than or equal to x, `false` otherwise.
*/
- def >=(x: Char): Boolean = sys.error("stub")
+ def >=(x: Char): Boolean
/**
* Returns `true` if this value is greater than or equal to x, `false` otherwise.
*/
- def >=(x: Int): Boolean = sys.error("stub")
+ def >=(x: Int): Boolean
/**
* Returns `true` if this value is greater than or equal to x, `false` otherwise.
*/
- def >=(x: Long): Boolean = sys.error("stub")
+ def >=(x: Long): Boolean
/**
* Returns `true` if this value is greater than or equal to x, `false` otherwise.
*/
- def >=(x: Float): Boolean = sys.error("stub")
+ def >=(x: Float): Boolean
/**
* Returns `true` if this value is greater than or equal to x, `false` otherwise.
*/
- def >=(x: Double): Boolean = sys.error("stub")
+ def >=(x: Double): Boolean
/**
* Returns the bitwise OR of this value and `x`.
@@ -287,7 +289,7 @@ final class Int private extends AnyVal {
* // 11111010
* }}}
*/
- def |(x: Byte): Int = sys.error("stub")
+ def |(x: Byte): Int
/**
* Returns the bitwise OR of this value and `x`.
* @example {{{
@@ -298,7 +300,7 @@ final class Int private extends AnyVal {
* // 11111010
* }}}
*/
- def |(x: Short): Int = sys.error("stub")
+ def |(x: Short): Int
/**
* Returns the bitwise OR of this value and `x`.
* @example {{{
@@ -309,7 +311,7 @@ final class Int private extends AnyVal {
* // 11111010
* }}}
*/
- def |(x: Char): Int = sys.error("stub")
+ def |(x: Char): Int
/**
* Returns the bitwise OR of this value and `x`.
* @example {{{
@@ -320,7 +322,7 @@ final class Int private extends AnyVal {
* // 11111010
* }}}
*/
- def |(x: Int): Int = sys.error("stub")
+ def |(x: Int): Int
/**
* Returns the bitwise OR of this value and `x`.
* @example {{{
@@ -331,7 +333,7 @@ final class Int private extends AnyVal {
* // 11111010
* }}}
*/
- def |(x: Long): Long = sys.error("stub")
+ def |(x: Long): Long
/**
* Returns the bitwise AND of this value and `x`.
@@ -343,7 +345,7 @@ final class Int private extends AnyVal {
* // 10100000
* }}}
*/
- def &(x: Byte): Int = sys.error("stub")
+ def &(x: Byte): Int
/**
* Returns the bitwise AND of this value and `x`.
* @example {{{
@@ -354,7 +356,7 @@ final class Int private extends AnyVal {
* // 10100000
* }}}
*/
- def &(x: Short): Int = sys.error("stub")
+ def &(x: Short): Int
/**
* Returns the bitwise AND of this value and `x`.
* @example {{{
@@ -365,7 +367,7 @@ final class Int private extends AnyVal {
* // 10100000
* }}}
*/
- def &(x: Char): Int = sys.error("stub")
+ def &(x: Char): Int
/**
* Returns the bitwise AND of this value and `x`.
* @example {{{
@@ -376,7 +378,7 @@ final class Int private extends AnyVal {
* // 10100000
* }}}
*/
- def &(x: Int): Int = sys.error("stub")
+ def &(x: Int): Int
/**
* Returns the bitwise AND of this value and `x`.
* @example {{{
@@ -387,7 +389,7 @@ final class Int private extends AnyVal {
* // 10100000
* }}}
*/
- def &(x: Long): Long = sys.error("stub")
+ def &(x: Long): Long
/**
* Returns the bitwise XOR of this value and `x`.
@@ -399,7 +401,7 @@ final class Int private extends AnyVal {
* // 01011010
* }}}
*/
- def ^(x: Byte): Int = sys.error("stub")
+ def ^(x: Byte): Int
/**
* Returns the bitwise XOR of this value and `x`.
* @example {{{
@@ -410,7 +412,7 @@ final class Int private extends AnyVal {
* // 01011010
* }}}
*/
- def ^(x: Short): Int = sys.error("stub")
+ def ^(x: Short): Int
/**
* Returns the bitwise XOR of this value and `x`.
* @example {{{
@@ -421,7 +423,7 @@ final class Int private extends AnyVal {
* // 01011010
* }}}
*/
- def ^(x: Char): Int = sys.error("stub")
+ def ^(x: Char): Int
/**
* Returns the bitwise XOR of this value and `x`.
* @example {{{
@@ -432,7 +434,7 @@ final class Int private extends AnyVal {
* // 01011010
* }}}
*/
- def ^(x: Int): Int = sys.error("stub")
+ def ^(x: Int): Int
/**
* Returns the bitwise XOR of this value and `x`.
* @example {{{
@@ -443,157 +445,157 @@ final class Int private extends AnyVal {
* // 01011010
* }}}
*/
- def ^(x: Long): Long = sys.error("stub")
+ def ^(x: Long): Long
/**
* Returns the sum of this value and `x`.
*/
- def +(x: Byte): Int = sys.error("stub")
+ def +(x: Byte): Int
/**
* Returns the sum of this value and `x`.
*/
- def +(x: Short): Int = sys.error("stub")
+ def +(x: Short): Int
/**
* Returns the sum of this value and `x`.
*/
- def +(x: Char): Int = sys.error("stub")
+ def +(x: Char): Int
/**
* Returns the sum of this value and `x`.
*/
- def +(x: Int): Int = sys.error("stub")
+ def +(x: Int): Int
/**
* Returns the sum of this value and `x`.
*/
- def +(x: Long): Long = sys.error("stub")
+ def +(x: Long): Long
/**
* Returns the sum of this value and `x`.
*/
- def +(x: Float): Float = sys.error("stub")
+ def +(x: Float): Float
/**
* Returns the sum of this value and `x`.
*/
- def +(x: Double): Double = sys.error("stub")
+ def +(x: Double): Double
/**
* Returns the difference of this value and `x`.
*/
- def -(x: Byte): Int = sys.error("stub")
+ def -(x: Byte): Int
/**
* Returns the difference of this value and `x`.
*/
- def -(x: Short): Int = sys.error("stub")
+ def -(x: Short): Int
/**
* Returns the difference of this value and `x`.
*/
- def -(x: Char): Int = sys.error("stub")
+ def -(x: Char): Int
/**
* Returns the difference of this value and `x`.
*/
- def -(x: Int): Int = sys.error("stub")
+ def -(x: Int): Int
/**
* Returns the difference of this value and `x`.
*/
- def -(x: Long): Long = sys.error("stub")
+ def -(x: Long): Long
/**
* Returns the difference of this value and `x`.
*/
- def -(x: Float): Float = sys.error("stub")
+ def -(x: Float): Float
/**
* Returns the difference of this value and `x`.
*/
- def -(x: Double): Double = sys.error("stub")
+ def -(x: Double): Double
/**
* Returns the product of this value and `x`.
*/
- def *(x: Byte): Int = sys.error("stub")
+ def *(x: Byte): Int
/**
* Returns the product of this value and `x`.
*/
- def *(x: Short): Int = sys.error("stub")
+ def *(x: Short): Int
/**
* Returns the product of this value and `x`.
*/
- def *(x: Char): Int = sys.error("stub")
+ def *(x: Char): Int
/**
* Returns the product of this value and `x`.
*/
- def *(x: Int): Int = sys.error("stub")
+ def *(x: Int): Int
/**
* Returns the product of this value and `x`.
*/
- def *(x: Long): Long = sys.error("stub")
+ def *(x: Long): Long
/**
* Returns the product of this value and `x`.
*/
- def *(x: Float): Float = sys.error("stub")
+ def *(x: Float): Float
/**
* Returns the product of this value and `x`.
*/
- def *(x: Double): Double = sys.error("stub")
+ def *(x: Double): Double
/**
* Returns the quotient of this value and `x`.
*/
- def /(x: Byte): Int = sys.error("stub")
+ def /(x: Byte): Int
/**
* Returns the quotient of this value and `x`.
*/
- def /(x: Short): Int = sys.error("stub")
+ def /(x: Short): Int
/**
* Returns the quotient of this value and `x`.
*/
- def /(x: Char): Int = sys.error("stub")
+ def /(x: Char): Int
/**
* Returns the quotient of this value and `x`.
*/
- def /(x: Int): Int = sys.error("stub")
+ def /(x: Int): Int
/**
* Returns the quotient of this value and `x`.
*/
- def /(x: Long): Long = sys.error("stub")
+ def /(x: Long): Long
/**
* Returns the quotient of this value and `x`.
*/
- def /(x: Float): Float = sys.error("stub")
+ def /(x: Float): Float
/**
* Returns the quotient of this value and `x`.
*/
- def /(x: Double): Double = sys.error("stub")
+ def /(x: Double): Double
/**
* Returns the remainder of the division of this value by `x`.
*/
- def %(x: Byte): Int = sys.error("stub")
+ def %(x: Byte): Int
/**
* Returns the remainder of the division of this value by `x`.
*/
- def %(x: Short): Int = sys.error("stub")
+ def %(x: Short): Int
/**
* Returns the remainder of the division of this value by `x`.
*/
- def %(x: Char): Int = sys.error("stub")
+ def %(x: Char): Int
/**
* Returns the remainder of the division of this value by `x`.
*/
- def %(x: Int): Int = sys.error("stub")
+ def %(x: Int): Int
/**
* Returns the remainder of the division of this value by `x`.
*/
- def %(x: Long): Long = sys.error("stub")
+ def %(x: Long): Long
/**
* Returns the remainder of the division of this value by `x`.
*/
- def %(x: Float): Float = sys.error("stub")
+ def %(x: Float): Float
/**
* Returns the remainder of the division of this value by `x`.
*/
- def %(x: Double): Double = sys.error("stub")
+ def %(x: Double): Double
- override def getClass(): Class[Int] = sys.error("stub")
+ override def getClass(): Class[Int] = null
}
-object Int extends AnyValCompanion {
+object Int extends AnyValCompanion {
/** The smallest value representable as a Int.
*/
final val MinValue = java.lang.Integer.MIN_VALUE
@@ -622,6 +624,9 @@ object Int extends AnyValCompanion {
/** The String representation of the scala.Int companion object.
*/
override def toString = "object scala.Int"
+
+ /** Language mandated coercions from Int to "wider" types.
+ */
implicit def int2long(x: Int): Long = x.toLong
implicit def int2float(x: Int): Float = x.toFloat
implicit def int2double(x: Int): Double = x.toDouble
diff --git a/src/library/scala/Long.scala b/src/library/scala/Long.scala
index 85131b4f54..40932a65a7 100644
--- a/src/library/scala/Long.scala
+++ b/src/library/scala/Long.scala
@@ -10,6 +10,8 @@
package scala
+import language.implicitConversions
+
/** `Long`, a 64-bit signed integer (equivalent to Java's `long` primitive type) is a
* subtype of [[scala.AnyVal]]. Instances of `Long` are not
* represented by an object in the underlying runtime system.
@@ -17,14 +19,14 @@ package scala
* There is an implicit conversion from [[scala.Long]] => [[scala.runtime.RichLong]]
* which provides useful non-primitive operations.
*/
-final class Long private extends AnyVal {
- def toByte: Byte = sys.error("stub")
- def toShort: Short = sys.error("stub")
- def toChar: Char = sys.error("stub")
- def toInt: Int = sys.error("stub")
- def toLong: Long = sys.error("stub")
- def toFloat: Float = sys.error("stub")
- def toDouble: Double = sys.error("stub")
+final abstract class Long private extends AnyVal {
+ def toByte: Byte
+ def toShort: Short
+ def toChar: Char
+ def toInt: Int
+ def toLong: Long
+ def toFloat: Float
+ def toDouble: Double
/**
* Returns the bitwise negation of this value.
@@ -34,30 +36,30 @@ final class Long private extends AnyVal {
* // 11111010
* }}}
*/
- def unary_~ : Long = sys.error("stub")
+ def unary_~ : Long
/**
* Returns this value, unmodified.
*/
- def unary_+ : Long = sys.error("stub")
+ def unary_+ : Long
/**
* Returns the negation of this value.
*/
- def unary_- : Long = sys.error("stub")
+ def unary_- : Long
- def +(x: String): String = sys.error("stub")
+ def +(x: String): String
/**
* Returns this value bit-shifted left by the specified number of bits,
* filling in the new right bits with zeroes.
* @example {{{ 6 << 3 == 48 // in binary: 0110 << 3 == 0110000 }}}
*/
- def <<(x: Int): Long = sys.error("stub")
+ def <<(x: Int): Long
/**
* Returns this value bit-shifted left by the specified number of bits,
* filling in the new right bits with zeroes.
* @example {{{ 6 << 3 == 48 // in binary: 0110 << 3 == 0110000 }}}
*/
- def <<(x: Long): Long = sys.error("stub")
+ def <<(x: Long): Long
/**
* Returns this value bit-shifted right by the specified number of bits,
* filling the new left bits with zeroes.
@@ -68,7 +70,7 @@ final class Long private extends AnyVal {
* // 00011111 11111111 11111111 11111101
* }}}
*/
- def >>>(x: Int): Long = sys.error("stub")
+ def >>>(x: Int): Long
/**
* Returns this value bit-shifted right by the specified number of bits,
* filling the new left bits with zeroes.
@@ -79,7 +81,7 @@ final class Long private extends AnyVal {
* // 00011111 11111111 11111111 11111101
* }}}
*/
- def >>>(x: Long): Long = sys.error("stub")
+ def >>>(x: Long): Long
/**
* Returns this value bit-shifted left by the specified number of bits,
* filling in the right bits with the same value as the left-most bit of this.
@@ -90,7 +92,7 @@ final class Long private extends AnyVal {
* // 11111111 11111111 11111111 11111101
* }}}
*/
- def >>(x: Int): Long = sys.error("stub")
+ def >>(x: Int): Long
/**
* Returns this value bit-shifted left by the specified number of bits,
* filling in the right bits with the same value as the left-most bit of this.
@@ -101,181 +103,181 @@ final class Long private extends AnyVal {
* // 11111111 11111111 11111111 11111101
* }}}
*/
- def >>(x: Long): Long = sys.error("stub")
+ def >>(x: Long): Long
/**
* Returns `true` if this value is equal to x, `false` otherwise.
*/
- def ==(x: Byte): Boolean = sys.error("stub")
+ def ==(x: Byte): Boolean
/**
* Returns `true` if this value is equal to x, `false` otherwise.
*/
- def ==(x: Short): Boolean = sys.error("stub")
+ def ==(x: Short): Boolean
/**
* Returns `true` if this value is equal to x, `false` otherwise.
*/
- def ==(x: Char): Boolean = sys.error("stub")
+ def ==(x: Char): Boolean
/**
* Returns `true` if this value is equal to x, `false` otherwise.
*/
- def ==(x: Int): Boolean = sys.error("stub")
+ def ==(x: Int): Boolean
/**
* Returns `true` if this value is equal to x, `false` otherwise.
*/
- def ==(x: Long): Boolean = sys.error("stub")
+ def ==(x: Long): Boolean
/**
* Returns `true` if this value is equal to x, `false` otherwise.
*/
- def ==(x: Float): Boolean = sys.error("stub")
+ def ==(x: Float): Boolean
/**
* Returns `true` if this value is equal to x, `false` otherwise.
*/
- def ==(x: Double): Boolean = sys.error("stub")
+ def ==(x: Double): Boolean
/**
* Returns `true` if this value is not equal to x, `false` otherwise.
*/
- def !=(x: Byte): Boolean = sys.error("stub")
+ def !=(x: Byte): Boolean
/**
* Returns `true` if this value is not equal to x, `false` otherwise.
*/
- def !=(x: Short): Boolean = sys.error("stub")
+ def !=(x: Short): Boolean
/**
* Returns `true` if this value is not equal to x, `false` otherwise.
*/
- def !=(x: Char): Boolean = sys.error("stub")
+ def !=(x: Char): Boolean
/**
* Returns `true` if this value is not equal to x, `false` otherwise.
*/
- def !=(x: Int): Boolean = sys.error("stub")
+ def !=(x: Int): Boolean
/**
* Returns `true` if this value is not equal to x, `false` otherwise.
*/
- def !=(x: Long): Boolean = sys.error("stub")
+ def !=(x: Long): Boolean
/**
* Returns `true` if this value is not equal to x, `false` otherwise.
*/
- def !=(x: Float): Boolean = sys.error("stub")
+ def !=(x: Float): Boolean
/**
* Returns `true` if this value is not equal to x, `false` otherwise.
*/
- def !=(x: Double): Boolean = sys.error("stub")
+ def !=(x: Double): Boolean
/**
* Returns `true` if this value is less than x, `false` otherwise.
*/
- def <(x: Byte): Boolean = sys.error("stub")
+ def <(x: Byte): Boolean
/**
* Returns `true` if this value is less than x, `false` otherwise.
*/
- def <(x: Short): Boolean = sys.error("stub")
+ def <(x: Short): Boolean
/**
* Returns `true` if this value is less than x, `false` otherwise.
*/
- def <(x: Char): Boolean = sys.error("stub")
+ def <(x: Char): Boolean
/**
* Returns `true` if this value is less than x, `false` otherwise.
*/
- def <(x: Int): Boolean = sys.error("stub")
+ def <(x: Int): Boolean
/**
* Returns `true` if this value is less than x, `false` otherwise.
*/
- def <(x: Long): Boolean = sys.error("stub")
+ def <(x: Long): Boolean
/**
* Returns `true` if this value is less than x, `false` otherwise.
*/
- def <(x: Float): Boolean = sys.error("stub")
+ def <(x: Float): Boolean
/**
* Returns `true` if this value is less than x, `false` otherwise.
*/
- def <(x: Double): Boolean = sys.error("stub")
+ def <(x: Double): Boolean
/**
* Returns `true` if this value is less than or equal to x, `false` otherwise.
*/
- def <=(x: Byte): Boolean = sys.error("stub")
+ def <=(x: Byte): Boolean
/**
* Returns `true` if this value is less than or equal to x, `false` otherwise.
*/
- def <=(x: Short): Boolean = sys.error("stub")
+ def <=(x: Short): Boolean
/**
* Returns `true` if this value is less than or equal to x, `false` otherwise.
*/
- def <=(x: Char): Boolean = sys.error("stub")
+ def <=(x: Char): Boolean
/**
* Returns `true` if this value is less than or equal to x, `false` otherwise.
*/
- def <=(x: Int): Boolean = sys.error("stub")
+ def <=(x: Int): Boolean
/**
* Returns `true` if this value is less than or equal to x, `false` otherwise.
*/
- def <=(x: Long): Boolean = sys.error("stub")
+ def <=(x: Long): Boolean
/**
* Returns `true` if this value is less than or equal to x, `false` otherwise.
*/
- def <=(x: Float): Boolean = sys.error("stub")
+ def <=(x: Float): Boolean
/**
* Returns `true` if this value is less than or equal to x, `false` otherwise.
*/
- def <=(x: Double): Boolean = sys.error("stub")
+ def <=(x: Double): Boolean
/**
* Returns `true` if this value is greater than x, `false` otherwise.
*/
- def >(x: Byte): Boolean = sys.error("stub")
+ def >(x: Byte): Boolean
/**
* Returns `true` if this value is greater than x, `false` otherwise.
*/
- def >(x: Short): Boolean = sys.error("stub")
+ def >(x: Short): Boolean
/**
* Returns `true` if this value is greater than x, `false` otherwise.
*/
- def >(x: Char): Boolean = sys.error("stub")
+ def >(x: Char): Boolean
/**
* Returns `true` if this value is greater than x, `false` otherwise.
*/
- def >(x: Int): Boolean = sys.error("stub")
+ def >(x: Int): Boolean
/**
* Returns `true` if this value is greater than x, `false` otherwise.
*/
- def >(x: Long): Boolean = sys.error("stub")
+ def >(x: Long): Boolean
/**
* Returns `true` if this value is greater than x, `false` otherwise.
*/
- def >(x: Float): Boolean = sys.error("stub")
+ def >(x: Float): Boolean
/**
* Returns `true` if this value is greater than x, `false` otherwise.
*/
- def >(x: Double): Boolean = sys.error("stub")
+ def >(x: Double): Boolean
/**
* Returns `true` if this value is greater than or equal to x, `false` otherwise.
*/
- def >=(x: Byte): Boolean = sys.error("stub")
+ def >=(x: Byte): Boolean
/**
* Returns `true` if this value is greater than or equal to x, `false` otherwise.
*/
- def >=(x: Short): Boolean = sys.error("stub")
+ def >=(x: Short): Boolean
/**
* Returns `true` if this value is greater than or equal to x, `false` otherwise.
*/
- def >=(x: Char): Boolean = sys.error("stub")
+ def >=(x: Char): Boolean
/**
* Returns `true` if this value is greater than or equal to x, `false` otherwise.
*/
- def >=(x: Int): Boolean = sys.error("stub")
+ def >=(x: Int): Boolean
/**
* Returns `true` if this value is greater than or equal to x, `false` otherwise.
*/
- def >=(x: Long): Boolean = sys.error("stub")
+ def >=(x: Long): Boolean
/**
* Returns `true` if this value is greater than or equal to x, `false` otherwise.
*/
- def >=(x: Float): Boolean = sys.error("stub")
+ def >=(x: Float): Boolean
/**
* Returns `true` if this value is greater than or equal to x, `false` otherwise.
*/
- def >=(x: Double): Boolean = sys.error("stub")
+ def >=(x: Double): Boolean
/**
* Returns the bitwise OR of this value and `x`.
@@ -287,7 +289,7 @@ final class Long private extends AnyVal {
* // 11111010
* }}}
*/
- def |(x: Byte): Long = sys.error("stub")
+ def |(x: Byte): Long
/**
* Returns the bitwise OR of this value and `x`.
* @example {{{
@@ -298,7 +300,7 @@ final class Long private extends AnyVal {
* // 11111010
* }}}
*/
- def |(x: Short): Long = sys.error("stub")
+ def |(x: Short): Long
/**
* Returns the bitwise OR of this value and `x`.
* @example {{{
@@ -309,7 +311,7 @@ final class Long private extends AnyVal {
* // 11111010
* }}}
*/
- def |(x: Char): Long = sys.error("stub")
+ def |(x: Char): Long
/**
* Returns the bitwise OR of this value and `x`.
* @example {{{
@@ -320,7 +322,7 @@ final class Long private extends AnyVal {
* // 11111010
* }}}
*/
- def |(x: Int): Long = sys.error("stub")
+ def |(x: Int): Long
/**
* Returns the bitwise OR of this value and `x`.
* @example {{{
@@ -331,7 +333,7 @@ final class Long private extends AnyVal {
* // 11111010
* }}}
*/
- def |(x: Long): Long = sys.error("stub")
+ def |(x: Long): Long
/**
* Returns the bitwise AND of this value and `x`.
@@ -343,7 +345,7 @@ final class Long private extends AnyVal {
* // 10100000
* }}}
*/
- def &(x: Byte): Long = sys.error("stub")
+ def &(x: Byte): Long
/**
* Returns the bitwise AND of this value and `x`.
* @example {{{
@@ -354,7 +356,7 @@ final class Long private extends AnyVal {
* // 10100000
* }}}
*/
- def &(x: Short): Long = sys.error("stub")
+ def &(x: Short): Long
/**
* Returns the bitwise AND of this value and `x`.
* @example {{{
@@ -365,7 +367,7 @@ final class Long private extends AnyVal {
* // 10100000
* }}}
*/
- def &(x: Char): Long = sys.error("stub")
+ def &(x: Char): Long
/**
* Returns the bitwise AND of this value and `x`.
* @example {{{
@@ -376,7 +378,7 @@ final class Long private extends AnyVal {
* // 10100000
* }}}
*/
- def &(x: Int): Long = sys.error("stub")
+ def &(x: Int): Long
/**
* Returns the bitwise AND of this value and `x`.
* @example {{{
@@ -387,7 +389,7 @@ final class Long private extends AnyVal {
* // 10100000
* }}}
*/
- def &(x: Long): Long = sys.error("stub")
+ def &(x: Long): Long
/**
* Returns the bitwise XOR of this value and `x`.
@@ -399,7 +401,7 @@ final class Long private extends AnyVal {
* // 01011010
* }}}
*/
- def ^(x: Byte): Long = sys.error("stub")
+ def ^(x: Byte): Long
/**
* Returns the bitwise XOR of this value and `x`.
* @example {{{
@@ -410,7 +412,7 @@ final class Long private extends AnyVal {
* // 01011010
* }}}
*/
- def ^(x: Short): Long = sys.error("stub")
+ def ^(x: Short): Long
/**
* Returns the bitwise XOR of this value and `x`.
* @example {{{
@@ -421,7 +423,7 @@ final class Long private extends AnyVal {
* // 01011010
* }}}
*/
- def ^(x: Char): Long = sys.error("stub")
+ def ^(x: Char): Long
/**
* Returns the bitwise XOR of this value and `x`.
* @example {{{
@@ -432,7 +434,7 @@ final class Long private extends AnyVal {
* // 01011010
* }}}
*/
- def ^(x: Int): Long = sys.error("stub")
+ def ^(x: Int): Long
/**
* Returns the bitwise XOR of this value and `x`.
* @example {{{
@@ -443,157 +445,157 @@ final class Long private extends AnyVal {
* // 01011010
* }}}
*/
- def ^(x: Long): Long = sys.error("stub")
+ def ^(x: Long): Long
/**
* Returns the sum of this value and `x`.
*/
- def +(x: Byte): Long = sys.error("stub")
+ def +(x: Byte): Long
/**
* Returns the sum of this value and `x`.
*/
- def +(x: Short): Long = sys.error("stub")
+ def +(x: Short): Long
/**
* Returns the sum of this value and `x`.
*/
- def +(x: Char): Long = sys.error("stub")
+ def +(x: Char): Long
/**
* Returns the sum of this value and `x`.
*/
- def +(x: Int): Long = sys.error("stub")
+ def +(x: Int): Long
/**
* Returns the sum of this value and `x`.
*/
- def +(x: Long): Long = sys.error("stub")
+ def +(x: Long): Long
/**
* Returns the sum of this value and `x`.
*/
- def +(x: Float): Float = sys.error("stub")
+ def +(x: Float): Float
/**
* Returns the sum of this value and `x`.
*/
- def +(x: Double): Double = sys.error("stub")
+ def +(x: Double): Double
/**
* Returns the difference of this value and `x`.
*/
- def -(x: Byte): Long = sys.error("stub")
+ def -(x: Byte): Long
/**
* Returns the difference of this value and `x`.
*/
- def -(x: Short): Long = sys.error("stub")
+ def -(x: Short): Long
/**
* Returns the difference of this value and `x`.
*/
- def -(x: Char): Long = sys.error("stub")
+ def -(x: Char): Long
/**
* Returns the difference of this value and `x`.
*/
- def -(x: Int): Long = sys.error("stub")
+ def -(x: Int): Long
/**
* Returns the difference of this value and `x`.
*/
- def -(x: Long): Long = sys.error("stub")
+ def -(x: Long): Long
/**
* Returns the difference of this value and `x`.
*/
- def -(x: Float): Float = sys.error("stub")
+ def -(x: Float): Float
/**
* Returns the difference of this value and `x`.
*/
- def -(x: Double): Double = sys.error("stub")
+ def -(x: Double): Double
/**
* Returns the product of this value and `x`.
*/
- def *(x: Byte): Long = sys.error("stub")
+ def *(x: Byte): Long
/**
* Returns the product of this value and `x`.
*/
- def *(x: Short): Long = sys.error("stub")
+ def *(x: Short): Long
/**
* Returns the product of this value and `x`.
*/
- def *(x: Char): Long = sys.error("stub")
+ def *(x: Char): Long
/**
* Returns the product of this value and `x`.
*/
- def *(x: Int): Long = sys.error("stub")
+ def *(x: Int): Long
/**
* Returns the product of this value and `x`.
*/
- def *(x: Long): Long = sys.error("stub")
+ def *(x: Long): Long
/**
* Returns the product of this value and `x`.
*/
- def *(x: Float): Float = sys.error("stub")
+ def *(x: Float): Float
/**
* Returns the product of this value and `x`.
*/
- def *(x: Double): Double = sys.error("stub")
+ def *(x: Double): Double
/**
* Returns the quotient of this value and `x`.
*/
- def /(x: Byte): Long = sys.error("stub")
+ def /(x: Byte): Long
/**
* Returns the quotient of this value and `x`.
*/
- def /(x: Short): Long = sys.error("stub")
+ def /(x: Short): Long
/**
* Returns the quotient of this value and `x`.
*/
- def /(x: Char): Long = sys.error("stub")
+ def /(x: Char): Long
/**
* Returns the quotient of this value and `x`.
*/
- def /(x: Int): Long = sys.error("stub")
+ def /(x: Int): Long
/**
* Returns the quotient of this value and `x`.
*/
- def /(x: Long): Long = sys.error("stub")
+ def /(x: Long): Long
/**
* Returns the quotient of this value and `x`.
*/
- def /(x: Float): Float = sys.error("stub")
+ def /(x: Float): Float
/**
* Returns the quotient of this value and `x`.
*/
- def /(x: Double): Double = sys.error("stub")
+ def /(x: Double): Double
/**
* Returns the remainder of the division of this value by `x`.
*/
- def %(x: Byte): Long = sys.error("stub")
+ def %(x: Byte): Long
/**
* Returns the remainder of the division of this value by `x`.
*/
- def %(x: Short): Long = sys.error("stub")
+ def %(x: Short): Long
/**
* Returns the remainder of the division of this value by `x`.
*/
- def %(x: Char): Long = sys.error("stub")
+ def %(x: Char): Long
/**
* Returns the remainder of the division of this value by `x`.
*/
- def %(x: Int): Long = sys.error("stub")
+ def %(x: Int): Long
/**
* Returns the remainder of the division of this value by `x`.
*/
- def %(x: Long): Long = sys.error("stub")
+ def %(x: Long): Long
/**
* Returns the remainder of the division of this value by `x`.
*/
- def %(x: Float): Float = sys.error("stub")
+ def %(x: Float): Float
/**
* Returns the remainder of the division of this value by `x`.
*/
- def %(x: Double): Double = sys.error("stub")
+ def %(x: Double): Double
- override def getClass(): Class[Long] = sys.error("stub")
+ override def getClass(): Class[Long] = null
}
-object Long extends AnyValCompanion {
+object Long extends AnyValCompanion {
/** The smallest value representable as a Long.
*/
final val MinValue = java.lang.Long.MIN_VALUE
@@ -622,6 +624,9 @@ object Long extends AnyValCompanion {
/** The String representation of the scala.Long companion object.
*/
override def toString = "object scala.Long"
+
+ /** Language mandated coercions from Long to "wider" types.
+ */
implicit def long2float(x: Long): Float = x.toFloat
implicit def long2double(x: Long): Double = x.toDouble
}
diff --git a/src/library/scala/Short.scala b/src/library/scala/Short.scala
index 1060a9db16..687b198a11 100644
--- a/src/library/scala/Short.scala
+++ b/src/library/scala/Short.scala
@@ -10,6 +10,8 @@
package scala
+import language.implicitConversions
+
/** `Short`, a 16-bit signed integer (equivalent to Java's `short` primitive type) is a
* subtype of [[scala.AnyVal]]. Instances of `Short` are not
* represented by an object in the underlying runtime system.
@@ -17,14 +19,14 @@ package scala
* There is an implicit conversion from [[scala.Short]] => [[scala.runtime.RichShort]]
* which provides useful non-primitive operations.
*/
-final class Short private extends AnyVal {
- def toByte: Byte = sys.error("stub")
- def toShort: Short = sys.error("stub")
- def toChar: Char = sys.error("stub")
- def toInt: Int = sys.error("stub")
- def toLong: Long = sys.error("stub")
- def toFloat: Float = sys.error("stub")
- def toDouble: Double = sys.error("stub")
+final abstract class Short private extends AnyVal {
+ def toByte: Byte
+ def toShort: Short
+ def toChar: Char
+ def toInt: Int
+ def toLong: Long
+ def toFloat: Float
+ def toDouble: Double
/**
* Returns the bitwise negation of this value.
@@ -34,30 +36,30 @@ final class Short private extends AnyVal {
* // 11111010
* }}}
*/
- def unary_~ : Int = sys.error("stub")
+ def unary_~ : Int
/**
* Returns this value, unmodified.
*/
- def unary_+ : Int = sys.error("stub")
+ def unary_+ : Int
/**
* Returns the negation of this value.
*/
- def unary_- : Int = sys.error("stub")
+ def unary_- : Int
- def +(x: String): String = sys.error("stub")
+ def +(x: String): String
/**
* Returns this value bit-shifted left by the specified number of bits,
* filling in the new right bits with zeroes.
* @example {{{ 6 << 3 == 48 // in binary: 0110 << 3 == 0110000 }}}
*/
- def <<(x: Int): Int = sys.error("stub")
+ def <<(x: Int): Int
/**
* Returns this value bit-shifted left by the specified number of bits,
* filling in the new right bits with zeroes.
* @example {{{ 6 << 3 == 48 // in binary: 0110 << 3 == 0110000 }}}
*/
- def <<(x: Long): Int = sys.error("stub")
+ def <<(x: Long): Int
/**
* Returns this value bit-shifted right by the specified number of bits,
* filling the new left bits with zeroes.
@@ -68,7 +70,7 @@ final class Short private extends AnyVal {
* // 00011111 11111111 11111111 11111101
* }}}
*/
- def >>>(x: Int): Int = sys.error("stub")
+ def >>>(x: Int): Int
/**
* Returns this value bit-shifted right by the specified number of bits,
* filling the new left bits with zeroes.
@@ -79,7 +81,7 @@ final class Short private extends AnyVal {
* // 00011111 11111111 11111111 11111101
* }}}
*/
- def >>>(x: Long): Int = sys.error("stub")
+ def >>>(x: Long): Int
/**
* Returns this value bit-shifted left by the specified number of bits,
* filling in the right bits with the same value as the left-most bit of this.
@@ -90,7 +92,7 @@ final class Short private extends AnyVal {
* // 11111111 11111111 11111111 11111101
* }}}
*/
- def >>(x: Int): Int = sys.error("stub")
+ def >>(x: Int): Int
/**
* Returns this value bit-shifted left by the specified number of bits,
* filling in the right bits with the same value as the left-most bit of this.
@@ -101,181 +103,181 @@ final class Short private extends AnyVal {
* // 11111111 11111111 11111111 11111101
* }}}
*/
- def >>(x: Long): Int = sys.error("stub")
+ def >>(x: Long): Int
/**
* Returns `true` if this value is equal to x, `false` otherwise.
*/
- def ==(x: Byte): Boolean = sys.error("stub")
+ def ==(x: Byte): Boolean
/**
* Returns `true` if this value is equal to x, `false` otherwise.
*/
- def ==(x: Short): Boolean = sys.error("stub")
+ def ==(x: Short): Boolean
/**
* Returns `true` if this value is equal to x, `false` otherwise.
*/
- def ==(x: Char): Boolean = sys.error("stub")
+ def ==(x: Char): Boolean
/**
* Returns `true` if this value is equal to x, `false` otherwise.
*/
- def ==(x: Int): Boolean = sys.error("stub")
+ def ==(x: Int): Boolean
/**
* Returns `true` if this value is equal to x, `false` otherwise.
*/
- def ==(x: Long): Boolean = sys.error("stub")
+ def ==(x: Long): Boolean
/**
* Returns `true` if this value is equal to x, `false` otherwise.
*/
- def ==(x: Float): Boolean = sys.error("stub")
+ def ==(x: Float): Boolean
/**
* Returns `true` if this value is equal to x, `false` otherwise.
*/
- def ==(x: Double): Boolean = sys.error("stub")
+ def ==(x: Double): Boolean
/**
* Returns `true` if this value is not equal to x, `false` otherwise.
*/
- def !=(x: Byte): Boolean = sys.error("stub")
+ def !=(x: Byte): Boolean
/**
* Returns `true` if this value is not equal to x, `false` otherwise.
*/
- def !=(x: Short): Boolean = sys.error("stub")
+ def !=(x: Short): Boolean
/**
* Returns `true` if this value is not equal to x, `false` otherwise.
*/
- def !=(x: Char): Boolean = sys.error("stub")
+ def !=(x: Char): Boolean
/**
* Returns `true` if this value is not equal to x, `false` otherwise.
*/
- def !=(x: Int): Boolean = sys.error("stub")
+ def !=(x: Int): Boolean
/**
* Returns `true` if this value is not equal to x, `false` otherwise.
*/
- def !=(x: Long): Boolean = sys.error("stub")
+ def !=(x: Long): Boolean
/**
* Returns `true` if this value is not equal to x, `false` otherwise.
*/
- def !=(x: Float): Boolean = sys.error("stub")
+ def !=(x: Float): Boolean
/**
* Returns `true` if this value is not equal to x, `false` otherwise.
*/
- def !=(x: Double): Boolean = sys.error("stub")
+ def !=(x: Double): Boolean
/**
* Returns `true` if this value is less than x, `false` otherwise.
*/
- def <(x: Byte): Boolean = sys.error("stub")
+ def <(x: Byte): Boolean
/**
* Returns `true` if this value is less than x, `false` otherwise.
*/
- def <(x: Short): Boolean = sys.error("stub")
+ def <(x: Short): Boolean
/**
* Returns `true` if this value is less than x, `false` otherwise.
*/
- def <(x: Char): Boolean = sys.error("stub")
+ def <(x: Char): Boolean
/**
* Returns `true` if this value is less than x, `false` otherwise.
*/
- def <(x: Int): Boolean = sys.error("stub")
+ def <(x: Int): Boolean
/**
* Returns `true` if this value is less than x, `false` otherwise.
*/
- def <(x: Long): Boolean = sys.error("stub")
+ def <(x: Long): Boolean
/**
* Returns `true` if this value is less than x, `false` otherwise.
*/
- def <(x: Float): Boolean = sys.error("stub")
+ def <(x: Float): Boolean
/**
* Returns `true` if this value is less than x, `false` otherwise.
*/
- def <(x: Double): Boolean = sys.error("stub")
+ def <(x: Double): Boolean
/**
* Returns `true` if this value is less than or equal to x, `false` otherwise.
*/
- def <=(x: Byte): Boolean = sys.error("stub")
+ def <=(x: Byte): Boolean
/**
* Returns `true` if this value is less than or equal to x, `false` otherwise.
*/
- def <=(x: Short): Boolean = sys.error("stub")
+ def <=(x: Short): Boolean
/**
* Returns `true` if this value is less than or equal to x, `false` otherwise.
*/
- def <=(x: Char): Boolean = sys.error("stub")
+ def <=(x: Char): Boolean
/**
* Returns `true` if this value is less than or equal to x, `false` otherwise.
*/
- def <=(x: Int): Boolean = sys.error("stub")
+ def <=(x: Int): Boolean
/**
* Returns `true` if this value is less than or equal to x, `false` otherwise.
*/
- def <=(x: Long): Boolean = sys.error("stub")
+ def <=(x: Long): Boolean
/**
* Returns `true` if this value is less than or equal to x, `false` otherwise.
*/
- def <=(x: Float): Boolean = sys.error("stub")
+ def <=(x: Float): Boolean
/**
* Returns `true` if this value is less than or equal to x, `false` otherwise.
*/
- def <=(x: Double): Boolean = sys.error("stub")
+ def <=(x: Double): Boolean
/**
* Returns `true` if this value is greater than x, `false` otherwise.
*/
- def >(x: Byte): Boolean = sys.error("stub")
+ def >(x: Byte): Boolean
/**
* Returns `true` if this value is greater than x, `false` otherwise.
*/
- def >(x: Short): Boolean = sys.error("stub")
+ def >(x: Short): Boolean
/**
* Returns `true` if this value is greater than x, `false` otherwise.
*/
- def >(x: Char): Boolean = sys.error("stub")
+ def >(x: Char): Boolean
/**
* Returns `true` if this value is greater than x, `false` otherwise.
*/
- def >(x: Int): Boolean = sys.error("stub")
+ def >(x: Int): Boolean
/**
* Returns `true` if this value is greater than x, `false` otherwise.
*/
- def >(x: Long): Boolean = sys.error("stub")
+ def >(x: Long): Boolean
/**
* Returns `true` if this value is greater than x, `false` otherwise.
*/
- def >(x: Float): Boolean = sys.error("stub")
+ def >(x: Float): Boolean
/**
* Returns `true` if this value is greater than x, `false` otherwise.
*/
- def >(x: Double): Boolean = sys.error("stub")
+ def >(x: Double): Boolean
/**
* Returns `true` if this value is greater than or equal to x, `false` otherwise.
*/
- def >=(x: Byte): Boolean = sys.error("stub")
+ def >=(x: Byte): Boolean
/**
* Returns `true` if this value is greater than or equal to x, `false` otherwise.
*/
- def >=(x: Short): Boolean = sys.error("stub")
+ def >=(x: Short): Boolean
/**
* Returns `true` if this value is greater than or equal to x, `false` otherwise.
*/
- def >=(x: Char): Boolean = sys.error("stub")
+ def >=(x: Char): Boolean
/**
* Returns `true` if this value is greater than or equal to x, `false` otherwise.
*/
- def >=(x: Int): Boolean = sys.error("stub")
+ def >=(x: Int): Boolean
/**
* Returns `true` if this value is greater than or equal to x, `false` otherwise.
*/
- def >=(x: Long): Boolean = sys.error("stub")
+ def >=(x: Long): Boolean
/**
* Returns `true` if this value is greater than or equal to x, `false` otherwise.
*/
- def >=(x: Float): Boolean = sys.error("stub")
+ def >=(x: Float): Boolean
/**
* Returns `true` if this value is greater than or equal to x, `false` otherwise.
*/
- def >=(x: Double): Boolean = sys.error("stub")
+ def >=(x: Double): Boolean
/**
* Returns the bitwise OR of this value and `x`.
@@ -287,7 +289,7 @@ final class Short private extends AnyVal {
* // 11111010
* }}}
*/
- def |(x: Byte): Int = sys.error("stub")
+ def |(x: Byte): Int
/**
* Returns the bitwise OR of this value and `x`.
* @example {{{
@@ -298,7 +300,7 @@ final class Short private extends AnyVal {
* // 11111010
* }}}
*/
- def |(x: Short): Int = sys.error("stub")
+ def |(x: Short): Int
/**
* Returns the bitwise OR of this value and `x`.
* @example {{{
@@ -309,7 +311,7 @@ final class Short private extends AnyVal {
* // 11111010
* }}}
*/
- def |(x: Char): Int = sys.error("stub")
+ def |(x: Char): Int
/**
* Returns the bitwise OR of this value and `x`.
* @example {{{
@@ -320,7 +322,7 @@ final class Short private extends AnyVal {
* // 11111010
* }}}
*/
- def |(x: Int): Int = sys.error("stub")
+ def |(x: Int): Int
/**
* Returns the bitwise OR of this value and `x`.
* @example {{{
@@ -331,7 +333,7 @@ final class Short private extends AnyVal {
* // 11111010
* }}}
*/
- def |(x: Long): Long = sys.error("stub")
+ def |(x: Long): Long
/**
* Returns the bitwise AND of this value and `x`.
@@ -343,7 +345,7 @@ final class Short private extends AnyVal {
* // 10100000
* }}}
*/
- def &(x: Byte): Int = sys.error("stub")
+ def &(x: Byte): Int
/**
* Returns the bitwise AND of this value and `x`.
* @example {{{
@@ -354,7 +356,7 @@ final class Short private extends AnyVal {
* // 10100000
* }}}
*/
- def &(x: Short): Int = sys.error("stub")
+ def &(x: Short): Int
/**
* Returns the bitwise AND of this value and `x`.
* @example {{{
@@ -365,7 +367,7 @@ final class Short private extends AnyVal {
* // 10100000
* }}}
*/
- def &(x: Char): Int = sys.error("stub")
+ def &(x: Char): Int
/**
* Returns the bitwise AND of this value and `x`.
* @example {{{
@@ -376,7 +378,7 @@ final class Short private extends AnyVal {
* // 10100000
* }}}
*/
- def &(x: Int): Int = sys.error("stub")
+ def &(x: Int): Int
/**
* Returns the bitwise AND of this value and `x`.
* @example {{{
@@ -387,7 +389,7 @@ final class Short private extends AnyVal {
* // 10100000
* }}}
*/
- def &(x: Long): Long = sys.error("stub")
+ def &(x: Long): Long
/**
* Returns the bitwise XOR of this value and `x`.
@@ -399,7 +401,7 @@ final class Short private extends AnyVal {
* // 01011010
* }}}
*/
- def ^(x: Byte): Int = sys.error("stub")
+ def ^(x: Byte): Int
/**
* Returns the bitwise XOR of this value and `x`.
* @example {{{
@@ -410,7 +412,7 @@ final class Short private extends AnyVal {
* // 01011010
* }}}
*/
- def ^(x: Short): Int = sys.error("stub")
+ def ^(x: Short): Int
/**
* Returns the bitwise XOR of this value and `x`.
* @example {{{
@@ -421,7 +423,7 @@ final class Short private extends AnyVal {
* // 01011010
* }}}
*/
- def ^(x: Char): Int = sys.error("stub")
+ def ^(x: Char): Int
/**
* Returns the bitwise XOR of this value and `x`.
* @example {{{
@@ -432,7 +434,7 @@ final class Short private extends AnyVal {
* // 01011010
* }}}
*/
- def ^(x: Int): Int = sys.error("stub")
+ def ^(x: Int): Int
/**
* Returns the bitwise XOR of this value and `x`.
* @example {{{
@@ -443,157 +445,157 @@ final class Short private extends AnyVal {
* // 01011010
* }}}
*/
- def ^(x: Long): Long = sys.error("stub")
+ def ^(x: Long): Long
/**
* Returns the sum of this value and `x`.
*/
- def +(x: Byte): Int = sys.error("stub")
+ def +(x: Byte): Int
/**
* Returns the sum of this value and `x`.
*/
- def +(x: Short): Int = sys.error("stub")
+ def +(x: Short): Int
/**
* Returns the sum of this value and `x`.
*/
- def +(x: Char): Int = sys.error("stub")
+ def +(x: Char): Int
/**
* Returns the sum of this value and `x`.
*/
- def +(x: Int): Int = sys.error("stub")
+ def +(x: Int): Int
/**
* Returns the sum of this value and `x`.
*/
- def +(x: Long): Long = sys.error("stub")
+ def +(x: Long): Long
/**
* Returns the sum of this value and `x`.
*/
- def +(x: Float): Float = sys.error("stub")
+ def +(x: Float): Float
/**
* Returns the sum of this value and `x`.
*/
- def +(x: Double): Double = sys.error("stub")
+ def +(x: Double): Double
/**
* Returns the difference of this value and `x`.
*/
- def -(x: Byte): Int = sys.error("stub")
+ def -(x: Byte): Int
/**
* Returns the difference of this value and `x`.
*/
- def -(x: Short): Int = sys.error("stub")
+ def -(x: Short): Int
/**
* Returns the difference of this value and `x`.
*/
- def -(x: Char): Int = sys.error("stub")
+ def -(x: Char): Int
/**
* Returns the difference of this value and `x`.
*/
- def -(x: Int): Int = sys.error("stub")
+ def -(x: Int): Int
/**
* Returns the difference of this value and `x`.
*/
- def -(x: Long): Long = sys.error("stub")
+ def -(x: Long): Long
/**
* Returns the difference of this value and `x`.
*/
- def -(x: Float): Float = sys.error("stub")
+ def -(x: Float): Float
/**
* Returns the difference of this value and `x`.
*/
- def -(x: Double): Double = sys.error("stub")
+ def -(x: Double): Double
/**
* Returns the product of this value and `x`.
*/
- def *(x: Byte): Int = sys.error("stub")
+ def *(x: Byte): Int
/**
* Returns the product of this value and `x`.
*/
- def *(x: Short): Int = sys.error("stub")
+ def *(x: Short): Int
/**
* Returns the product of this value and `x`.
*/
- def *(x: Char): Int = sys.error("stub")
+ def *(x: Char): Int
/**
* Returns the product of this value and `x`.
*/
- def *(x: Int): Int = sys.error("stub")
+ def *(x: Int): Int
/**
* Returns the product of this value and `x`.
*/
- def *(x: Long): Long = sys.error("stub")
+ def *(x: Long): Long
/**
* Returns the product of this value and `x`.
*/
- def *(x: Float): Float = sys.error("stub")
+ def *(x: Float): Float
/**
* Returns the product of this value and `x`.
*/
- def *(x: Double): Double = sys.error("stub")
+ def *(x: Double): Double
/**
* Returns the quotient of this value and `x`.
*/
- def /(x: Byte): Int = sys.error("stub")
+ def /(x: Byte): Int
/**
* Returns the quotient of this value and `x`.
*/
- def /(x: Short): Int = sys.error("stub")
+ def /(x: Short): Int
/**
* Returns the quotient of this value and `x`.
*/
- def /(x: Char): Int = sys.error("stub")
+ def /(x: Char): Int
/**
* Returns the quotient of this value and `x`.
*/
- def /(x: Int): Int = sys.error("stub")
+ def /(x: Int): Int
/**
* Returns the quotient of this value and `x`.
*/
- def /(x: Long): Long = sys.error("stub")
+ def /(x: Long): Long
/**
* Returns the quotient of this value and `x`.
*/
- def /(x: Float): Float = sys.error("stub")
+ def /(x: Float): Float
/**
* Returns the quotient of this value and `x`.
*/
- def /(x: Double): Double = sys.error("stub")
+ def /(x: Double): Double
/**
* Returns the remainder of the division of this value by `x`.
*/
- def %(x: Byte): Int = sys.error("stub")
+ def %(x: Byte): Int
/**
* Returns the remainder of the division of this value by `x`.
*/
- def %(x: Short): Int = sys.error("stub")
+ def %(x: Short): Int
/**
* Returns the remainder of the division of this value by `x`.
*/
- def %(x: Char): Int = sys.error("stub")
+ def %(x: Char): Int
/**
* Returns the remainder of the division of this value by `x`.
*/
- def %(x: Int): Int = sys.error("stub")
+ def %(x: Int): Int
/**
* Returns the remainder of the division of this value by `x`.
*/
- def %(x: Long): Long = sys.error("stub")
+ def %(x: Long): Long
/**
* Returns the remainder of the division of this value by `x`.
*/
- def %(x: Float): Float = sys.error("stub")
+ def %(x: Float): Float
/**
* Returns the remainder of the division of this value by `x`.
*/
- def %(x: Double): Double = sys.error("stub")
+ def %(x: Double): Double
- override def getClass(): Class[Short] = sys.error("stub")
+ override def getClass(): Class[Short] = null
}
-object Short extends AnyValCompanion {
+object Short extends AnyValCompanion {
/** The smallest value representable as a Short.
*/
final val MinValue = java.lang.Short.MIN_VALUE
@@ -622,6 +624,9 @@ object Short extends AnyValCompanion {
/** The String representation of the scala.Short companion object.
*/
override def toString = "object scala.Short"
+
+ /** Language mandated coercions from Short to "wider" types.
+ */
implicit def short2int(x: Short): Int = x.toInt
implicit def short2long(x: Short): Long = x.toLong
implicit def short2float(x: Short): Float = x.toFloat
diff --git a/src/library/scala/Unit.scala b/src/library/scala/Unit.scala
index 3da5c083d4..4156071f29 100644
--- a/src/library/scala/Unit.scala
+++ b/src/library/scala/Unit.scala
@@ -10,17 +10,19 @@
package scala
+import language.implicitConversions
+
/** `Unit` is a subtype of [[scala.AnyVal]]. There is only one value of type
* `Unit`, `()`, and it is not represented by any object in the underlying
* runtime system. A method with return type `Unit` is analogous to a Java
* method which is declared `void`.
*/
-final class Unit private extends AnyVal {
- override def getClass(): Class[Unit] = sys.error("stub")
+final abstract class Unit private extends AnyVal {
+ override def getClass(): Class[Unit] = null
}
-object Unit extends AnyValCompanion {
+object Unit extends AnyValCompanion {
/** Transform a value type into a boxed reference type.
*
diff --git a/src/library/scala/collection/GenMapLike.scala b/src/library/scala/collection/GenMapLike.scala
index 4dd2a4fe37..b6c90d4d2a 100644
--- a/src/library/scala/collection/GenMapLike.scala
+++ b/src/library/scala/collection/GenMapLike.scala
@@ -31,7 +31,7 @@ trait GenMapLike[A, +B, +Repr] extends GenIterableLike[(A, B), Repr] with Equals
// This hash code must be symmetric in the contents but ought not
// collide trivially.
- override def hashCode() = util.MurmurHash3.mapHash(seq)
+ override def hashCode() = util.hashing.MurmurHash3.mapHash(seq)
/** Returns the value associated with a key, or a default value if the key is not contained in the map.
* @param key the key.
diff --git a/src/library/scala/collection/GenSeqLike.scala b/src/library/scala/collection/GenSeqLike.scala
index cfa0ca101e..a77cb05960 100644
--- a/src/library/scala/collection/GenSeqLike.scala
+++ b/src/library/scala/collection/GenSeqLike.scala
@@ -465,7 +465,7 @@ trait GenSeqLike[+A, +Repr] extends Any with GenIterableLike[A, Repr] with Equal
/** Hashcodes for $Coll produce a value from the hashcodes of all the
* elements of the $coll.
*/
- override def hashCode() = util.MurmurHash3.seqHash(seq)
+ override def hashCode() = util.hashing.MurmurHash3.seqHash(seq)
/** The equals method for arbitrary sequences. Compares this sequence to
* some other object.
diff --git a/src/library/scala/collection/GenSetLike.scala b/src/library/scala/collection/GenSetLike.scala
index 219374abc6..18eb31da03 100644
--- a/src/library/scala/collection/GenSetLike.scala
+++ b/src/library/scala/collection/GenSetLike.scala
@@ -127,5 +127,5 @@ extends GenIterableLike[A, Repr]
// Calling map on a set drops duplicates: any hashcode collisions would
// then be dropped before they can be added.
// Hash should be symmetric in set entries, but without trivial collisions.
- override def hashCode() = util.MurmurHash3.setHash(seq)
+ override def hashCode() = util.hashing.MurmurHash3.setHash(seq)
}
diff --git a/src/library/scala/collection/IndexedSeqLike.scala b/src/library/scala/collection/IndexedSeqLike.scala
index 11f481e425..f79a9d2c66 100644
--- a/src/library/scala/collection/IndexedSeqLike.scala
+++ b/src/library/scala/collection/IndexedSeqLike.scala
@@ -41,7 +41,7 @@ trait IndexedSeqLike[+A, +Repr] extends Any with SeqLike[A, Repr] {
self =>
def seq: IndexedSeq[A]
- override def hashCode() = util.MurmurHash3.seqHash(seq) // TODO - can we get faster via "indexedSeqHash" ?
+ override def hashCode() = util.hashing.MurmurHash3.seqHash(seq) // TODO - can we get faster via "indexedSeqHash" ?
override protected[this] def thisCollection: IndexedSeq[A] = this.asInstanceOf[IndexedSeq[A]]
override protected[this] def toCollection(repr: Repr): IndexedSeq[A] = repr.asInstanceOf[IndexedSeq[A]]
diff --git a/src/library/scala/collection/LinearSeqLike.scala b/src/library/scala/collection/LinearSeqLike.scala
index ceb980ff80..bfe27ef94a 100644
--- a/src/library/scala/collection/LinearSeqLike.scala
+++ b/src/library/scala/collection/LinearSeqLike.scala
@@ -50,7 +50,7 @@ trait LinearSeqLike[+A, +Repr <: LinearSeqLike[A, Repr]] extends SeqLike[A, Repr
def seq: LinearSeq[A]
- override def hashCode() = util.MurmurHash3.seqHash(seq) // TODO - can we get faster via "linearSeqHash" ?
+ override def hashCode() = util.hashing.MurmurHash3.seqHash(seq) // TODO - can we get faster via "linearSeqHash" ?
override /*IterableLike*/
def iterator: Iterator[A] = new AbstractIterator[A] {
diff --git a/src/library/scala/collection/concurrent/TrieMap.scala b/src/library/scala/collection/concurrent/TrieMap.scala
index 2a908aebb1..08e9125bd8 100644
--- a/src/library/scala/collection/concurrent/TrieMap.scala
+++ b/src/library/scala/collection/concurrent/TrieMap.scala
@@ -14,6 +14,7 @@ package concurrent
import java.util.concurrent.atomic._
import collection.immutable.{ ListMap => ImmutableListMap }
import collection.parallel.mutable.ParTrieMap
+import util.hashing.Hashing
import generic._
import annotation.tailrec
import annotation.switch
@@ -80,6 +81,9 @@ private[collection] final class INode[K, V](bn: MainNode[K, V], g: Gen) extends
} else false
}
+ @inline
+ private def equal(k1: K, k2: K, ct: TrieMap[K, V]) = ct.equality.equiv(k1, k2)
+
@inline private def inode(cn: MainNode[K, V]) = {
val nin = new INode[K, V](gen)
nin.WRITE(cn)
@@ -117,7 +121,7 @@ private[collection] final class INode[K, V](bn: MainNode[K, V], g: Gen) extends
else false
}
case sn: SNode[K, V] =>
- if (sn.hc == hc && sn.k == k) GCAS(cn, cn.updatedAt(pos, new SNode(k, v, hc), gen), ct)
+ if (sn.hc == hc && equal(sn.k, k, ct)) GCAS(cn, cn.updatedAt(pos, new SNode(k, v, hc), gen), ct)
else {
val rn = if (cn.gen eq gen) cn else cn.renewed(gen, ct)
val nn = rn.updatedAt(pos, inode(CNode.dual(sn, sn.hc, new SNode(k, v, hc), hc, lev + 5, gen)), gen)
@@ -164,7 +168,7 @@ private[collection] final class INode[K, V](bn: MainNode[K, V], g: Gen) extends
}
case sn: SNode[K, V] => cond match {
case null =>
- if (sn.hc == hc && sn.k == k) {
+ if (sn.hc == hc && equal(sn.k, k, ct)) {
if (GCAS(cn, cn.updatedAt(pos, new SNode(k, v, hc), gen), ct)) Some(sn.v) else null
} else {
val rn = if (cn.gen eq gen) cn else cn.renewed(gen, ct)
@@ -173,7 +177,7 @@ private[collection] final class INode[K, V](bn: MainNode[K, V], g: Gen) extends
else null
}
case INode.KEY_ABSENT =>
- if (sn.hc == hc && sn.k == k) Some(sn.v)
+ if (sn.hc == hc && equal(sn.k, k, ct)) Some(sn.v)
else {
val rn = if (cn.gen eq gen) cn else cn.renewed(gen, ct)
val nn = rn.updatedAt(pos, inode(CNode.dual(sn, sn.hc, new SNode(k, v, hc), hc, lev + 5, gen)), gen)
@@ -181,11 +185,11 @@ private[collection] final class INode[K, V](bn: MainNode[K, V], g: Gen) extends
else null
}
case INode.KEY_PRESENT =>
- if (sn.hc == hc && sn.k == k) {
+ if (sn.hc == hc && equal(sn.k, k, ct)) {
if (GCAS(cn, cn.updatedAt(pos, new SNode(k, v, hc), gen), ct)) Some(sn.v) else null
} else None
case otherv: V =>
- if (sn.hc == hc && sn.k == k && sn.v == otherv) {
+ if (sn.hc == hc && equal(sn.k, k, ct) && sn.v == otherv) {
if (GCAS(cn, cn.updatedAt(pos, new SNode(k, v, hc), gen), ct)) Some(sn.v) else null
} else None
}
@@ -253,7 +257,7 @@ private[collection] final class INode[K, V](bn: MainNode[K, V], g: Gen) extends
else return RESTART // used to be throw RestartException
}
case sn: SNode[K, V] => // 2) singleton node
- if (sn.hc == hc && sn.k == k) sn.v.asInstanceOf[AnyRef]
+ if (sn.hc == hc && equal(sn.k, k, ct)) sn.v.asInstanceOf[AnyRef]
else null
}
}
@@ -296,7 +300,7 @@ private[collection] final class INode[K, V](bn: MainNode[K, V], g: Gen) extends
else null
}
case sn: SNode[K, V] =>
- if (sn.hc == hc && sn.k == k && (v == null || sn.v == v)) {
+ if (sn.hc == hc && equal(sn.k, k, ct) && (v == null || sn.v == v)) {
val ncn = cn.removedAt(pos, flag, gen).toContracted(lev)
if (GCAS(cn, ncn, ct)) Some(sn.v) else null
} else None
@@ -341,11 +345,11 @@ private[collection] final class INode[K, V](bn: MainNode[K, V], g: Gen) extends
case ln: LNode[K, V] =>
if (v == null) {
val optv = ln.get(k)
- val nn = ln.removed(k)
+ val nn = ln.removed(k, ct)
if (GCAS(ln, nn, ct)) optv else null
} else ln.get(k) match {
case optv @ Some(v0) if v0 == v =>
- val nn = ln.removed(k)
+ val nn = ln.removed(k, ct)
if (GCAS(ln, nn, ct)) optv else null
case _ => None
}
@@ -433,12 +437,12 @@ extends MainNode[K, V] {
def this(k: K, v: V) = this(ImmutableListMap(k -> v))
def this(k1: K, v1: V, k2: K, v2: V) = this(ImmutableListMap(k1 -> v1, k2 -> v2))
def inserted(k: K, v: V) = new LNode(listmap + ((k, v)))
- def removed(k: K): MainNode[K, V] = {
+ def removed(k: K, ct: TrieMap[K, V]): MainNode[K, V] = {
val updmap = listmap - k
if (updmap.size > 1) new LNode(updmap)
else {
val (k, v) = updmap.iterator.next
- new TNode(k, v, TrieMap.computeHash(k)) // create it tombed so that it gets compressed on subsequent accesses
+ new TNode(k, v, ct.computeHash(k)) // create it tombed so that it gets compressed on subsequent accesses
}
}
def get(k: K) = listmap.get(k)
@@ -627,25 +631,34 @@ private[concurrent] case class RDCSS_Descriptor[K, V](old: INode[K, V], expected
* @since 2.10
*/
@SerialVersionUID(0L - 6402774413839597105L)
-final class TrieMap[K, V] private (r: AnyRef, rtupd: AtomicReferenceFieldUpdater[TrieMap[K, V], AnyRef])
+final class TrieMap[K, V] private (r: AnyRef, rtupd: AtomicReferenceFieldUpdater[TrieMap[K, V], AnyRef], hashf: Hashing[K], ef: Equiv[K])
extends scala.collection.concurrent.Map[K, V]
with scala.collection.mutable.MapLike[K, V, TrieMap[K, V]]
with CustomParallelizable[(K, V), ParTrieMap[K, V]]
with Serializable
{
- import TrieMap.computeHash
-
+ private var hashingobj = if (hashf.isInstanceOf[Hashing.Default[_]]) new TrieMap.MangledHashing[K] else hashf
+ private var equalityobj = ef
private var rootupdater = rtupd
+ def hashing = hashingobj
+ def equality = equalityobj
@volatile var root = r
-
- def this() = this(
+
+ def this(hashf: Hashing[K], ef: Equiv[K]) = this(
INode.newRootNode,
- AtomicReferenceFieldUpdater.newUpdater(classOf[TrieMap[K, V]], classOf[AnyRef], "root")
+ AtomicReferenceFieldUpdater.newUpdater(classOf[TrieMap[K, V]], classOf[AnyRef], "root"),
+ hashf,
+ ef
)
-
+
+ def this() = this(Hashing.default, Equiv.universal)
+
/* internal methods */
private def writeObject(out: java.io.ObjectOutputStream) {
+ out.writeObject(hashf)
+ out.writeObject(ef)
+
val it = iterator
while (it.hasNext) {
val (k, v) = it.next()
@@ -659,6 +672,9 @@ extends scala.collection.concurrent.Map[K, V]
root = INode.newRootNode
rootupdater = AtomicReferenceFieldUpdater.newUpdater(classOf[TrieMap[K, V]], classOf[AnyRef], "root")
+ hashingobj = in.readObject().asInstanceOf[Hashing[K]]
+ equalityobj = in.readObject().asInstanceOf[Equiv[K]]
+
var obj: AnyRef = null
do {
obj = in.readObject()
@@ -780,7 +796,7 @@ extends scala.collection.concurrent.Map[K, V]
@tailrec final def snapshot(): TrieMap[K, V] = {
val r = RDCSS_READ_ROOT()
val expmain = r.gcasRead(this)
- if (RDCSS_ROOT(r, expmain, r.copyToGen(new Gen, this))) new TrieMap(r.copyToGen(new Gen, this), rootupdater)
+ if (RDCSS_ROOT(r, expmain, r.copyToGen(new Gen, this))) new TrieMap(r.copyToGen(new Gen, this), rootupdater, hashing, equality)
else snapshot()
}
@@ -799,7 +815,7 @@ extends scala.collection.concurrent.Map[K, V]
@tailrec final def readOnlySnapshot(): collection.Map[K, V] = {
val r = RDCSS_READ_ROOT()
val expmain = r.gcasRead(this)
- if (RDCSS_ROOT(r, expmain, r.copyToGen(new Gen, this))) new TrieMap(r, null)
+ if (RDCSS_ROOT(r, expmain, r.copyToGen(new Gen, this))) new TrieMap(r, null, hashing, equality)
else readOnlySnapshot()
}
@@ -807,7 +823,10 @@ extends scala.collection.concurrent.Map[K, V]
val r = RDCSS_READ_ROOT()
if (!RDCSS_ROOT(r, r.gcasRead(this), INode.newRootNode[K, V])) clear()
}
-
+
+ @inline
+ def computeHash(k: K) = hashingobj.hash(k)
+
final def lookup(k: K): V = {
val hc = computeHash(k)
lookuphc(k, hc).asInstanceOf[V]
@@ -894,14 +913,11 @@ object TrieMap extends MutableMapFactory[TrieMap] {
implicit def canBuildFrom[K, V]: CanBuildFrom[Coll, (K, V), TrieMap[K, V]] = new MapCanBuildFrom[K, V]
def empty[K, V]: TrieMap[K, V] = new TrieMap[K, V]
-
- @inline final def computeHash[K](k: K): Int = {
- var hcode = k.hashCode
- hcode = hcode * 0x9e3775cd
- hcode = java.lang.Integer.reverseBytes(hcode)
- hcode * 0x9e3775cd
+
+ class MangledHashing[K] extends Hashing[K] {
+ def hash(k: K) = util.hashing.byteswap32(k.##)
}
-
+
}
diff --git a/src/library/scala/collection/convert/Wrappers.scala b/src/library/scala/collection/convert/Wrappers.scala
index b1b48b760f..8c603dc91b 100644
--- a/src/library/scala/collection/convert/Wrappers.scala
+++ b/src/library/scala/collection/convert/Wrappers.scala
@@ -171,15 +171,16 @@ private[collection] trait Wrappers {
var prev : Option[A] = None
def hasNext = ui.hasNext
-
+
def next() = {
val (k, v) = ui.next
prev = Some(k)
new ju.Map.Entry[A, B] {
+ import util.hashing.byteswap32
def getKey = k
def getValue = v
def setValue(v1 : B) = self.put(k, v1)
- override def hashCode = k.hashCode + v.hashCode
+ override def hashCode = byteswap32(k.hashCode) + (byteswap32(v.hashCode) << 16)
override def equals(other: Any) = other match {
case e: ju.Map.Entry[_, _] => k == e.getKey && v == e.getValue
case _ => false
diff --git a/src/library/scala/collection/immutable/HashMap.scala b/src/library/scala/collection/immutable/HashMap.scala
index 13a0febfee..05529761d3 100644
--- a/src/library/scala/collection/immutable/HashMap.scala
+++ b/src/library/scala/collection/immutable/HashMap.scala
@@ -74,11 +74,22 @@ class HashMap[A, +B] extends AbstractMap[A, B]
private[collection] def computeHash(key: A) = improve(elemHashCode(key))
- protected type Merger[B1] = ((A, B1), (A, B1)) => (A, B1)
+ protected type MergeFunction[A1, B1] = ((A1, B1), (A1, B1)) => (A1, B1);
+
+ import HashMap.Merger
+
+ protected def liftMerger[A1, B1](mergef: MergeFunction[A1, B1]): Merger[A1, B1] = if (mergef == null) null else new Merger[A1, B1] {
+ self =>
+ def apply(kv1: (A1, B1), kv2: (A1, B1)): (A1, B1) = mergef(kv1, kv2)
+ val invert: Merger[A1, B1] = new Merger[A1, B1] {
+ def apply(kv1: (A1, B1), kv2: (A1, B1)): (A1, B1) = mergef(kv2, kv1)
+ def invert: Merger[A1, B1] = self
+ }
+ }
private[collection] def get0(key: A, hash: Int, level: Int): Option[B] = None
- private[collection] def updated0[B1 >: B](key: A, hash: Int, level: Int, value: B1, kv: (A, B1), merger: Merger[B1]): HashMap[A, B1] =
+ private[collection] def updated0[B1 >: B](key: A, hash: Int, level: Int, value: B1, kv: (A, B1), merger: Merger[A, B1]): HashMap[A, B1] =
new HashMap.HashMap1(key, hash, value, kv)
protected def removed0(key: A, hash: Int, level: Int): HashMap[A, B] = this
@@ -87,9 +98,25 @@ class HashMap[A, +B] extends AbstractMap[A, B]
def split: Seq[HashMap[A, B]] = Seq(this)
- def merge[B1 >: B](that: HashMap[A, B1], merger: Merger[B1] = null): HashMap[A, B1] = merge0(that, 0, merger)
-
- protected def merge0[B1 >: B](that: HashMap[A, B1], level: Int, merger: Merger[B1]): HashMap[A, B1] = that
+ @deprecated("Use the `merged` method instead.", "2.10.0")
+ def merge[B1 >: B](that: HashMap[A, B1], mergef: MergeFunction[A, B1] = null): HashMap[A, B1] = merge0(that, 0, liftMerger(mergef))
+
+ /** Creates a new map which is the merge of this and the argument hash map.
+ *
+ * Uses the specified collision resolution function if two keys are the same.
+ * The collision resolution function will always take the first argument from
+ * `this` hash map and the second from `that`.
+ *
+ * The `merged` method is on average more performant than doing a traversal and reconstructing a
+ * new immutable hash map from scratch, or `++`.
+ *
+ * @tparam B1 the value type of the other hash map
+ * @param that the other hash map
+ * @param mergef the merge function or null if the first key-value pair is to be picked
+ */
+ def merged[B1 >: B](that: HashMap[A, B1])(mergef: MergeFunction[A, B1]): HashMap[A, B1] = merge0(that, 0, liftMerger(mergef))
+
+ protected def merge0[B1 >: B](that: HashMap[A, B1], level: Int, merger: Merger[A, B1]): HashMap[A, B1] = that
override def par = ParHashMap.fromTrie(this)
@@ -103,6 +130,13 @@ class HashMap[A, +B] extends AbstractMap[A, B]
* @since 2.3
*/
object HashMap extends ImmutableMapFactory[HashMap] with BitOperations.Int {
+
+ private[immutable] abstract class Merger[A, B] {
+ def apply(kv1: (A, B), kv2: (A, B)): (A, B)
+ def invert: Merger[A, B]
+ }
+
+
/** $mapCanBuildFromInfo */
implicit def canBuildFrom[A, B]: CanBuildFrom[Coll, (A, B), HashMap[A, B]] = new MapCanBuildFrom[A, B]
def empty[A, B]: HashMap[A, B] = EmptyHashMap.asInstanceOf[HashMap[A, B]]
@@ -136,12 +170,15 @@ object HashMap extends ImmutableMapFactory[HashMap] with BitOperations.Int {
// }
// }
- override def updated0[B1 >: B](key: A, hash: Int, level: Int, value: B1, kv: (A, B1), merger: Merger[B1]): HashMap[A, B1] =
+ override def updated0[B1 >: B](key: A, hash: Int, level: Int, value: B1, kv: (A, B1), merger: Merger[A, B1]): HashMap[A, B1] =
if (hash == this.hash && key == this.key ) {
if (merger eq null) {
- if(this.value.asInstanceOf[AnyRef] eq value.asInstanceOf[AnyRef]) this
+ if (this.value.asInstanceOf[AnyRef] eq value.asInstanceOf[AnyRef]) this
else new HashMap1(key, hash, value, kv)
- } else new HashMap1(key, hash, value, merger(this.kv, kv))
+ } else {
+ val nkv = merger(this.kv, kv)
+ new HashMap1(nkv._1, hash, nkv._2, nkv)
+ }
} else {
var thatindex = (hash >>> level) & 0x1f
var thisindex = (this.hash >>> level) & 0x1f
@@ -180,8 +217,8 @@ object HashMap extends ImmutableMapFactory[HashMap] with BitOperations.Int {
override def foreach[U](f: ((A, B)) => U): Unit = f(ensurePair)
// this method may be called multiple times in a multithreaded environment, but that's ok
private[HashMap] def ensurePair: (A,B) = if (kv ne null) kv else { kv = (key, value); kv }
- protected override def merge0[B1 >: B](that: HashMap[A, B1], level: Int, merger: Merger[B1]): HashMap[A, B1] = {
- that.updated0(key, hash, level, value, kv, merger)
+ protected override def merge0[B1 >: B](that: HashMap[A, B1], level: Int, merger: Merger[A, B1]): HashMap[A, B1] = {
+ that.updated0(key, hash, level, value, kv, if (merger ne null) merger.invert else null)
}
}
@@ -193,7 +230,7 @@ object HashMap extends ImmutableMapFactory[HashMap] with BitOperations.Int {
override def get0(key: A, hash: Int, level: Int): Option[B] =
if (hash == this.hash) kvs.get(key) else None
- override def updated0[B1 >: B](key: A, hash: Int, level: Int, value: B1, kv: (A, B1), merger: Merger[B1]): HashMap[A, B1] =
+ override def updated0[B1 >: B](key: A, hash: Int, level: Int, value: B1, kv: (A, B1), merger: Merger[A, B1]): HashMap[A, B1] =
if (hash == this.hash) {
if ((merger eq null) || !kvs.contains(key)) new HashMapCollision1(hash, kvs.updated(key, value))
else new HashMapCollision1(hash, kvs + merger((key, kvs(key)), kv))
@@ -221,7 +258,7 @@ object HashMap extends ImmutableMapFactory[HashMap] with BitOperations.Int {
def newhm(lm: ListMap[A, B @uV]) = new HashMapCollision1(hash, lm)
List(newhm(x), newhm(y))
}
- protected override def merge0[B1 >: B](that: HashMap[A, B1], level: Int, merger: Merger[B1]): HashMap[A, B1] = {
+ protected override def merge0[B1 >: B](that: HashMap[A, B1], level: Int, merger: Merger[A, B1]): HashMap[A, B1] = {
// this can be made more efficient by passing the entire ListMap at once
var m = that
for (p <- kvs) m = m.updated0(p._1, this.hash, level, p._2, p, merger)
@@ -268,7 +305,7 @@ object HashMap extends ImmutableMapFactory[HashMap] with BitOperations.Int {
None
}
- override def updated0[B1 >: B](key: A, hash: Int, level: Int, value: B1, kv: (A, B1), merger: Merger[B1]): HashMap[A, B1] = {
+ override def updated0[B1 >: B](key: A, hash: Int, level: Int, value: B1, kv: (A, B1), merger: Merger[A, B1]): HashMap[A, B1] = {
val index = (hash >>> level) & 0x1f
val mask = (1 << index)
val offset = Integer.bitCount(bitmap & (mask-1))
@@ -380,7 +417,7 @@ time { mNew.iterator.foreach( p => ()) }
} else elems(0).split
}
- protected override def merge0[B1 >: B](that: HashMap[A, B1], level: Int, merger: Merger[B1]): HashMap[A, B1] = that match {
+ protected override def merge0[B1 >: B](that: HashMap[A, B1], level: Int, merger: Merger[A, B1]): HashMap[A, B1] = that match {
case hm: HashMap1[_, _] =>
this.updated0(hm.key, hm.hash, level, hm.value.asInstanceOf[B1], hm.kv, merger)
case hm: HashTrieMap[_, _] =>
@@ -440,7 +477,7 @@ time { mNew.iterator.foreach( p => ()) }
}
new HashTrieMap[A, B1](this.bitmap | that.bitmap, merged, totalelems)
- case hm: HashMapCollision1[_, _] => that.merge0(this, level, merger)
+ case hm: HashMapCollision1[_, _] => that.merge0(this, level, if (merger ne null) merger.invert else null)
case hm: HashMap[_, _] => this
case _ => sys.error("section supposed to be unreachable.")
}
diff --git a/src/library/scala/collection/mutable/FlatHashTable.scala b/src/library/scala/collection/mutable/FlatHashTable.scala
index 4070174902..f6d4cc31b6 100644
--- a/src/library/scala/collection/mutable/FlatHashTable.scala
+++ b/src/library/scala/collection/mutable/FlatHashTable.scala
@@ -397,9 +397,7 @@ private[collection] object FlatHashTable {
//h = h + (h << 4)
//h ^ (h >>> 10)
- var i = hcode * 0x9e3775cd
- i = java.lang.Integer.reverseBytes(i)
- val improved = i * 0x9e3775cd
+ val improved = util.hashing.byteswap32(hcode)
// for the remainder, see SI-5293
// to ensure that different bits are used for different hash tables, we have to rotate based on the seed
diff --git a/src/library/scala/collection/mutable/HashTable.scala b/src/library/scala/collection/mutable/HashTable.scala
index c307e6dcab..97e794f06e 100644
--- a/src/library/scala/collection/mutable/HashTable.scala
+++ b/src/library/scala/collection/mutable/HashTable.scala
@@ -401,12 +401,7 @@ private[collection] object HashTable {
*
* For performance reasons, we avoid this improvement.
* */
- var i = hcode * 0x9e3775cd
- i = java.lang.Integer.reverseBytes(i)
- i = i * 0x9e3775cd
- // a slower alternative for byte reversal:
- // i = (i << 16) | (i >> 16)
- // i = ((i >> 8) & 0x00ff00ff) | ((i << 8) & 0xff00ff00)
+ val i = util.hashing.byteswap32(hcode)
/* Jenkins hash
* for range 0-10000, output has the msb set to zero */
diff --git a/src/library/scala/collection/mutable/UnrolledBuffer.scala b/src/library/scala/collection/mutable/UnrolledBuffer.scala
index cd76c7de4e..0c2e6e1cae 100644
--- a/src/library/scala/collection/mutable/UnrolledBuffer.scala
+++ b/src/library/scala/collection/mutable/UnrolledBuffer.scala
@@ -179,6 +179,8 @@ extends collection.mutable.AbstractBuffer[T]
}
}
+ override def clone(): UnrolledBuffer[T] = new UnrolledBuffer[T] ++= this
+
override def stringPrefix = "UnrolledBuffer"
}
diff --git a/src/library/scala/concurrent/impl/ExecutionContextImpl.scala b/src/library/scala/concurrent/impl/ExecutionContextImpl.scala
index 1083a93439..7549bf8314 100644
--- a/src/library/scala/concurrent/impl/ExecutionContextImpl.scala
+++ b/src/library/scala/concurrent/impl/ExecutionContextImpl.scala
@@ -43,17 +43,31 @@ private[scala] class ExecutionContextImpl private[impl] (es: Executor, reporter:
}
}
}
-
- def createExecutorService: ExecutorService = try { new ForkJoinPool(
- Runtime.getRuntime.availableProcessors(), //FIXME from config
- forkJoinPoolThreadFactory,
- null, //FIXME we should have an UncaughtExceptionHandler, see what Akka does
- true) //FIXME I really think this should be async...
+
+ def createExecutorService: ExecutorService = try {
+ def getInt(name: String, f: String => Int): Int =
+ try f(System.getProperty(name)) catch { case e: Exception => Runtime.getRuntime.availableProcessors }
+ def range(floor: Int, desired: Int, ceiling: Int): Int =
+ if (ceiling < floor) range(ceiling, desired, floor) else scala.math.min(scala.math.max(desired, floor), ceiling)
+
+ new ForkJoinPool(
+ range(
+ getInt("scala.concurrent.ec.minThreads", _.toInt),
+ getInt("scala.concurrent.ec.numThreads", {
+ case null | "" => Runtime.getRuntime.availableProcessors
+ case s if s.charAt(0) == 'x' => (Runtime.getRuntime.availableProcessors * s.substring(1).toDouble).ceil.toInt
+ case other => other.toInt
+ }),
+ getInt("scala.concurrent.ec.maxThreads", _.toInt)
+ ),
+ forkJoinPoolThreadFactory,
+ null, //FIXME we should have an UncaughtExceptionHandler, see what Akka does
+ true) //FIXME I really think this should be async...
} catch {
case NonFatal(t) =>
System.err.println("Failed to create ForkJoinPool for the default ExecutionContext, falling back to Executors.newCachedThreadPool")
t.printStackTrace(System.err)
- Executors.newCachedThreadPool(executorsThreadFactory)
+ Executors.newCachedThreadPool(executorsThreadFactory) //FIXME use the same desired parallelism here too?
}
def execute(runnable: Runnable): Unit = executor match {
diff --git a/src/library/scala/math/Equiv.scala b/src/library/scala/math/Equiv.scala
index bd8414a18d..a8ba0aa40c 100644
--- a/src/library/scala/math/Equiv.scala
+++ b/src/library/scala/math/Equiv.scala
@@ -29,7 +29,7 @@ import java.util.Comparator
* @since 2.7
*/
-trait Equiv[T] extends Any {
+trait Equiv[T] extends Any with Serializable {
/** Returns `true` iff `x` is equivalent to `y`.
*/
def equiv(x: T, y: T): Boolean
diff --git a/src/library/scala/math/Ordered.scala b/src/library/scala/math/Ordered.scala
index 80addea7f3..a5efa41b80 100644
--- a/src/library/scala/math/Ordered.scala
+++ b/src/library/scala/math/Ordered.scala
@@ -15,7 +15,7 @@ import language.implicitConversions
* more information about whether to use [[scala.math.Ordering]] instead.
*
* Classes that implement this trait can be sorted with
- * [[scala.utils.Sorting]] and can be compared with standard comparison operators
+ * [[scala.util.Sorting]] and can be compared with standard comparison operators
* (e.g. > and <).
*
* Ordered should be used for data with a single, natural ordering (like
@@ -27,14 +27,15 @@ import language.implicitConversions
*
* [[scala.math.PartiallyOrdered]] is an alternative to this trait for partially ordered data.
*
- * For example, to create a simple class that implements Ordered and then sort it with [[scala.utils.Sorting]]:
+ * For example, create a simple class that implements `Ordered` and then sort it with [[scala.util.Sorting]]:
* {{{
- * class OrderedClass(n:Int) extends Ordered[OrderedClass] {
+ * case class OrderedClass(n:Int) extends Ordered[OrderedClass] {
* def compare(that: OrderedClass) = this.n - that.n
* }
*
- * val x = List(new MyClass(1), new MyClass(5), new MyClass(3))
- * val result = scala.utils.Sorting.quickSort(x)
+ * val x = Array(OrderedClass(1), OrderedClass(5), OrderedClass(3))
+ * scala.util.Sorting.quickSort(x)
+ * x
* }}}
*
* It is important that the `equals` method for an instance of `Ordered[A]` be consistent with the
diff --git a/src/library/scala/runtime/ScalaRunTime.scala b/src/library/scala/runtime/ScalaRunTime.scala
index 4c5e0e408b..5cd301a0fe 100644
--- a/src/library/scala/runtime/ScalaRunTime.scala
+++ b/src/library/scala/runtime/ScalaRunTime.scala
@@ -199,7 +199,7 @@ object ScalaRunTime {
def _toString(x: Product): String =
x.productIterator.mkString(x.productPrefix + "(", ",", ")")
- def _hashCode(x: Product): Int = scala.util.MurmurHash3.productHash(x)
+ def _hashCode(x: Product): Int = scala.util.hashing.MurmurHash3.productHash(x)
/** A helper for case classes. */
def typedProductIterator[T](x: Product): Iterator[T] = {
diff --git a/src/library/scala/util/hashing/ByteswapHashing.scala b/src/library/scala/util/hashing/ByteswapHashing.scala
new file mode 100644
index 0000000000..fc8a33a486
--- /dev/null
+++ b/src/library/scala/util/hashing/ByteswapHashing.scala
@@ -0,0 +1,35 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2006-2011, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | http://www.scala-lang.org/ **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+package scala.util.hashing
+
+
+
+
+
+
+/** A fast multiplicative hash by Phil Bagwell.
+ */
+final class ByteswapHashing[T] extends Hashing[T] {
+
+ def hash(v: T) = byteswap32(v.##)
+
+}
+
+
+object ByteswapHashing {
+
+ private class Chained[T](h: Hashing[T]) extends Hashing[T] {
+ def hash(v: T) = byteswap32(h.hash(v))
+ }
+
+ /** Composes another `Hashing` with the Byteswap hash.
+ */
+ def chain[T](h: Hashing[T]): Hashing[T] = new Chained(h)
+
+}
diff --git a/src/library/scala/util/hashing/Hashing.scala b/src/library/scala/util/hashing/Hashing.scala
new file mode 100644
index 0000000000..84b549f35e
--- /dev/null
+++ b/src/library/scala/util/hashing/Hashing.scala
@@ -0,0 +1,42 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2011, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+package scala.util.hashing
+
+/** `Hashing` is a trait whose instances each represent a strategy for hashing
+ * instances of a type.
+ *
+ * `Hashing`'s companion object defines a default hashing strategy for all
+ * objects - it calls their `##` method.
+ *
+ * Note: when using a custom `Hashing`, make sure to use it with the `Equiv`
+ * such that if any two objects are equal, then their hash codes must be equal.
+ *
+ * @since 2.10
+ */
+@annotation.implicitNotFound(msg = "No implicit Hashing defined for ${T}.")
+trait Hashing[T] extends Serializable {
+
+ def hash(x: T): Int
+
+}
+
+
+object Hashing {
+
+ final class Default[T] extends Hashing[T] {
+ def hash(x: T) = x.##
+ }
+
+ implicit def default[T] = new Default[T]
+
+ def fromFunction[T](f: T => Int) = new Hashing[T] {
+ def hash(x: T) = f(x)
+ }
+
+}
diff --git a/src/library/scala/util/MurmurHash3.scala b/src/library/scala/util/hashing/MurmurHash3.scala
index fbb67116dd..3efd5b5e72 100644
--- a/src/library/scala/util/MurmurHash3.scala
+++ b/src/library/scala/util/hashing/MurmurHash3.scala
@@ -1,27 +1,16 @@
-package scala.util
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2012, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+package scala.util.hashing
import java.lang.Integer.{ rotateLeft => rotl }
-/**
- * An implementation of Austin Appleby's MurmurHash 3 algorithm
- * (MurmurHash3_x86_32).
- *
- * An algorithm designed to generate well-distributed non-cryptographic
- * hashes. It is designed to hash data in 32 bit chunks (ints).
- *
- * The mix method needs to be called at each step to update the intermediate
- * hash value. For the last chunk to incorporate into the hash mixLast may
- * be used instead, which is slightly faster. Finally finalizeHash needs to
- * be called to compute the final hash value.
- *
- * This is based on the earlier MurmurHash3 code by Rex Kerr, but the
- * MurmurHash3 algorithm was since changed by its creator Austin Appleby
- * to remedy some weaknesses and improve performance. This represents the
- * latest and supposedly final version of the algortihm (revision 136).
- *
- * @see [[http://code.google.com/p/smhasher]]
- */
-class MurmurHash3 {
+private[hashing] class MurmurHash3 {
/** Mix in a block of data into an intermediate hash value. */
final def mix(hash: Int, data: Int): Int = {
var h = mixLast(hash, data)
@@ -171,8 +160,25 @@ class MurmurHash3 {
}
/**
- * An instance of MurmurHash3 with predefined seeds for various
- * classes. Used by all the scala collections and case classes.
+ * An implementation of Austin Appleby's MurmurHash 3 algorithm
+ * (MurmurHash3_x86_32). This object contains methods that hash
+ * values of various types as well as means to construct `Hashing`
+ * objects.
+ *
+ * This algorithm is designed to generate well-distributed non-cryptographic
+ * hashes. It is designed to hash data in 32 bit chunks (ints).
+ *
+ * The mix method needs to be called at each step to update the intermediate
+ * hash value. For the last chunk to incorporate into the hash mixLast may
+ * be used instead, which is slightly faster. Finally finalizeHash needs to
+ * be called to compute the final hash value.
+ *
+ * This is based on the earlier MurmurHash3 code by Rex Kerr, but the
+ * MurmurHash3 algorithm was since changed by its creator Austin Appleby
+ * to remedy some weaknesses and improve performance. This represents the
+ * latest and supposedly final version of the algortihm (revision 136).
+ *
+ * @see [[http://code.google.com/p/smhasher]]
*/
object MurmurHash3 extends MurmurHash3 {
final val arraySeed = 0x3c074a61
@@ -197,6 +203,32 @@ object MurmurHash3 extends MurmurHash3 {
def mapHash(xs: collection.Map[_, _]): Int = unorderedHash(xs, mapSeed)
def setHash(xs: collection.Set[_]): Int = unorderedHash(xs, setSeed)
+ class ArrayHashing[@specialized T] extends Hashing[Array[T]] {
+ def hash(a: Array[T]) = arrayHash(a)
+ }
+
+ def arrayHashing[@specialized T] = new ArrayHashing[T]
+
+ def bytesHashing = new Hashing[Array[Byte]] {
+ def hash(data: Array[Byte]) = bytesHash(data)
+ }
+
+ def orderedHashing = new Hashing[TraversableOnce[Any]] {
+ def hash(xs: TraversableOnce[Any]) = orderedHash(xs)
+ }
+
+ def productHashing = new Hashing[Product] {
+ def hash(x: Product) = productHash(x)
+ }
+
+ def stringHashing = new Hashing[String] {
+ def hash(x: String) = stringHash(x)
+ }
+
+ def unorderedHashing = new Hashing[TraversableOnce[Any]] {
+ def hash(xs: TraversableOnce[Any]) = unorderedHash(xs)
+ }
+
/** All this trouble and foreach still appears faster.
* Leaving in place in case someone would like to investigate further.
*/
diff --git a/src/library/scala/util/hashing/package.scala b/src/library/scala/util/hashing/package.scala
new file mode 100644
index 0000000000..becfa4911e
--- /dev/null
+++ b/src/library/scala/util/hashing/package.scala
@@ -0,0 +1,35 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2006-2011, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | http://www.scala-lang.org/ **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+package scala.util
+
+
+
+
+
+
+package object hashing {
+
+ /** Fast multiplicative hash with a nice distribution.
+ */
+ def byteswap32(v: Int): Int = {
+ var hc = v * 0x9e3775cd
+ hc = java.lang.Integer.reverseBytes(hc)
+ hc * 0x9e3775cd
+ }
+
+ /** Fast multiplicative hash with a nice distribution
+ * for 64-bit values.
+ */
+ def byteswap64(v: Long): Long = {
+ var hc = v * 0x9e3775cd9e3775cdL
+ hc = java.lang.Long.reverseBytes(hc)
+ hc * 0x9e3775cd9e3775cdL
+ }
+
+}
diff --git a/src/library/scala/xml/Utility.scala b/src/library/scala/xml/Utility.scala
index 17c91fa52c..bae529c85c 100755
--- a/src/library/scala/xml/Utility.scala
+++ b/src/library/scala/xml/Utility.scala
@@ -268,7 +268,7 @@ object Utility extends AnyRef with parsing.TokenTests {
* Returns a hashcode for the given constituents of a node
*/
def hashCode(pre: String, label: String, attribHashCode: Int, scpeHash: Int, children: Seq[Node]) =
- scala.util.MurmurHash3.orderedHash(label +: attribHashCode +: scpeHash +: children, pre.##)
+ scala.util.hashing.MurmurHash3.orderedHash(label +: attribHashCode +: scpeHash +: children, pre.##)
def appendQuoted(s: String): String = sbToString(appendQuoted(s, _))