summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/scala-compiler.jar.desired.sha12
-rw-r--r--lib/scala-library-src.jar.desired.sha12
-rw-r--r--lib/scala-library.jar.desired.sha12
-rw-r--r--src/compiler/scala/tools/nsc/Global.scala4
-rw-r--r--src/compiler/scala/tools/nsc/ast/TreeDSL.scala4
-rw-r--r--src/compiler/scala/tools/nsc/ast/TreeGen.scala11
-rw-r--r--src/compiler/scala/tools/nsc/ast/TreeInfo.scala6
-rw-r--r--src/compiler/scala/tools/nsc/backend/icode/GenICode.scala3
-rw-r--r--src/compiler/scala/tools/nsc/doc/ModelToXML.scala2
-rwxr-xr-xsrc/compiler/scala/tools/nsc/javac/JavaParsers.scala2
-rw-r--r--src/compiler/scala/tools/nsc/symtab/Definitions.scala21
-rw-r--r--src/compiler/scala/tools/nsc/symtab/StdNames.scala2
-rw-r--r--src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala5
-rw-r--r--src/compiler/scala/tools/nsc/transform/CleanUp.scala1
-rw-r--r--src/compiler/scala/tools/nsc/transform/Erasure.scala50
-rw-r--r--src/compiler/scala/tools/nsc/transform/UnCurry.scala61
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/EtaExpansion.scala1
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Implicits.scala2
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Infer.scala5
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/RefChecks.scala3
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala2
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala4
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Typers.scala31
-rw-r--r--src/library/scala/LowPriorityImplicits.scala42
-rw-r--r--src/library/scala/Predef.scala42
25 files changed, 184 insertions, 126 deletions
diff --git a/lib/scala-compiler.jar.desired.sha1 b/lib/scala-compiler.jar.desired.sha1
index 13a72e5f9f..a7e7d593fd 100644
--- a/lib/scala-compiler.jar.desired.sha1
+++ b/lib/scala-compiler.jar.desired.sha1
@@ -1 +1 @@
-3f8d0fbb2d15b154e8e641b4c03d79106b0d89b7 ?scala-compiler.jar
+8608495b398625d39e3faa238afc7edfb132540c ?scala-compiler.jar
diff --git a/lib/scala-library-src.jar.desired.sha1 b/lib/scala-library-src.jar.desired.sha1
index b2af0fdf1c..80b523e331 100644
--- a/lib/scala-library-src.jar.desired.sha1
+++ b/lib/scala-library-src.jar.desired.sha1
@@ -1 +1 @@
-67fe1519ca98e01470162ee94b42d518a35b4dc9 ?scala-library-src.jar
+0953276f0024b9ad628c5aa734f4001dd056e31c ?scala-library-src.jar
diff --git a/lib/scala-library.jar.desired.sha1 b/lib/scala-library.jar.desired.sha1
index 89affa9b86..5e3da114b7 100644
--- a/lib/scala-library.jar.desired.sha1
+++ b/lib/scala-library.jar.desired.sha1
@@ -1 +1 @@
-f6b603d86dad2ad3ef83f1116cd00c45863e6ecf ?scala-library.jar
+c9d3f1fd8ad5d5e209cbd6f6d3cdff82707052e8 ?scala-library.jar
diff --git a/src/compiler/scala/tools/nsc/Global.scala b/src/compiler/scala/tools/nsc/Global.scala
index 56b8253fa7..a27169503e 100644
--- a/src/compiler/scala/tools/nsc/Global.scala
+++ b/src/compiler/scala/tools/nsc/Global.scala
@@ -655,6 +655,10 @@ class Global(var settings: Settings, var reporter: Reporter) extends SymbolTable
*/
class Run {
+// settings.newArrays.value = true
+// settings.print.value = List("era")
+ if (settings.verbose.value) println("compiling with newArrays = "+settings.newArrays.value)
+
var isDefined = false
private val firstPhase = {
diff --git a/src/compiler/scala/tools/nsc/ast/TreeDSL.scala b/src/compiler/scala/tools/nsc/ast/TreeDSL.scala
index c4f0be7cf5..3922e3fd40 100644
--- a/src/compiler/scala/tools/nsc/ast/TreeDSL.scala
+++ b/src/compiler/scala/tools/nsc/ast/TreeDSL.scala
@@ -119,6 +119,10 @@ trait TreeDSL {
def ===(rhs: Tree) = Assign(target, rhs)
/** Methods for sequences **/
+ //[Martin] I don't understand why the toSequence call is needed.
+ //It seems redundant. If you want a widening, a Typed (xxx: Sequence)
+ //would be more efficient. If you want to also deal with arrays,
+ //it's won't work like this, because arrays will lack the toSequence method.
def DROP(count: Int): Tree =
if (count == 0) target
else (target DOT nme.drop)(LIT(count)) DOT nme.toSequence
diff --git a/src/compiler/scala/tools/nsc/ast/TreeGen.scala b/src/compiler/scala/tools/nsc/ast/TreeGen.scala
index edfca57be6..233a3368bd 100644
--- a/src/compiler/scala/tools/nsc/ast/TreeGen.scala
+++ b/src/compiler/scala/tools/nsc/ast/TreeGen.scala
@@ -273,8 +273,15 @@ abstract class TreeGen
def mkModuleAccessDcl(accessor: Symbol) =
DefDef(accessor setFlag lateDEFERRED, EmptyTree)
- def mkRuntimeCall(meth: Name, args: List[Tree]): Tree =
+ def mkRuntimeCall(meth: Name, args: List[Tree]): Tree = {
+ assert(!settings.newArrays.value || meth.toString != "boxArray")
Apply(Select(mkAttributedRef(ScalaRunTimeModule), meth), args)
+ }
+
+ // !!! todo: remove
+ def mkPredefCall(meth: Name, args: List[Tree]): Tree = {
+ Apply(Select(mkAttributedRef(PredefModule), meth), args)
+ }
/** Make a synchronized block on 'monitor'. */
def mkSynchronized(monitor: Tree, body: Tree): Tree =
@@ -285,7 +292,7 @@ abstract class TreeGen
def paramToArg(vparam: Symbol) = {
val arg = Ident(vparam)
- if (vparam.tpe.typeSymbol == RepeatedParamClass) wildcardStar(arg)
+ if (isRepeatedParamType(vparam.tpe)) wildcardStar(arg)
else arg
}
diff --git a/src/compiler/scala/tools/nsc/ast/TreeInfo.scala b/src/compiler/scala/tools/nsc/ast/TreeInfo.scala
index 5e1a36dc72..a4f585b196 100644
--- a/src/compiler/scala/tools/nsc/ast/TreeInfo.scala
+++ b/src/compiler/scala/tools/nsc/ast/TreeInfo.scala
@@ -170,8 +170,10 @@ abstract class TreeInfo {
/** Is type a of the form T* ? */
def isRepeatedParamType(tpt: Tree) = tpt match {
- case AppliedTypeTree(Select(_, rp), _) => rp == nme.REPEATED_PARAM_CLASS_NAME.toTypeName
- case TypeTree() => tpt.tpe.typeSymbol == definitions.RepeatedParamClass
+ case AppliedTypeTree(Select(_, rp), _) =>
+ rp == nme.REPEATED_PARAM_CLASS_NAME.toTypeName ||
+ rp == nme.JAVA_REPEATED_PARAM_CLASS_NAME.toTypeName
+ case TypeTree() => definitions.isRepeatedParamType(tpt.tpe)
case _ => false
}
diff --git a/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala b/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala
index 580331a3a7..2f8d6ae9f6 100644
--- a/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala
+++ b/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala
@@ -865,7 +865,8 @@ abstract class GenICode extends SubComponent {
} else {
ctx.bb.emit(THIS(ctx.clazz.symbol), tree.pos)
if (tree.symbol == definitions.ArrayClass)
- generatedType = REFERENCE(definitions.BoxedAnyArrayClass)
+ generatedType = REFERENCE(
+ if (settings.newArrays.value) definitions.ObjectClass else definitions.BoxedAnyArrayClass)
else
generatedType = REFERENCE(ctx.clazz.symbol)
}
diff --git a/src/compiler/scala/tools/nsc/doc/ModelToXML.scala b/src/compiler/scala/tools/nsc/doc/ModelToXML.scala
index d5a2704857..8e9f062fa7 100644
--- a/src/compiler/scala/tools/nsc/doc/ModelToXML.scala
+++ b/src/compiler/scala/tools/nsc/doc/ModelToXML.scala
@@ -57,7 +57,7 @@ trait ModelToXML extends ModelExtractor {
if (definitions.isFunctionType(tpe)) {
val (args,r) = tpe.normalize.typeArgs.splitAt(tpe.normalize.typeArgs.length - 1);
args.mkXML("(", ", ", ")")(link) ++ Text(" => ") ++ link(r.head);
- } else if (tpe.typeSymbol == definitions.RepeatedParamClass) {
+ } else if (definitions.isRepeatedParamType(tpe)) {
assert(tpe.typeArgs.length == 1)
link(tpe.typeArgs(0)) ++ Text("*")
} else if (tpe.typeSymbol == definitions.ByNameParamClass) {
diff --git a/src/compiler/scala/tools/nsc/javac/JavaParsers.scala b/src/compiler/scala/tools/nsc/javac/JavaParsers.scala
index 450ace6124..4d36816853 100755
--- a/src/compiler/scala/tools/nsc/javac/JavaParsers.scala
+++ b/src/compiler/scala/tools/nsc/javac/JavaParsers.scala
@@ -480,7 +480,7 @@ trait JavaParsers extends JavaScanners {
if (in.token == DOTDOTDOT) {
in.nextToken
t = atPos(t.pos) {
- AppliedTypeTree(scalaDot(nme.REPEATED_PARAM_CLASS_NAME.toTypeName), List(t))
+ AppliedTypeTree(scalaDot(nme.JAVA_REPEATED_PARAM_CLASS_NAME.toTypeName), List(t))
}
}
varDecl(in.currentPos, Modifiers(Flags.JAVA | Flags.PARAM), t, ident())
diff --git a/src/compiler/scala/tools/nsc/symtab/Definitions.scala b/src/compiler/scala/tools/nsc/symtab/Definitions.scala
index 1880707c70..7d624d8289 100644
--- a/src/compiler/scala/tools/nsc/symtab/Definitions.scala
+++ b/src/compiler/scala/tools/nsc/symtab/Definitions.scala
@@ -133,6 +133,16 @@ trait Definitions {
nme.REPEATED_PARAM_CLASS_NAME,
tparam => seqType(tparam.typeConstructor)
)
+
+ lazy val JavaRepeatedParamClass = newCovariantPolyClass(
+ ScalaPackageClass,
+ nme.JAVA_REPEATED_PARAM_CLASS_NAME,
+ tparam => arrayType(tparam.typeConstructor)
+ )
+
+ def isRepeatedParamType(tp: Type) =
+ tp.typeSymbol == RepeatedParamClass || tp.typeSymbol == JavaRepeatedParamClass
+
lazy val ByNameParamClass = newCovariantPolyClass(
ScalaPackageClass,
nme.BYNAME_PARAM_CLASS_NAME,
@@ -282,6 +292,7 @@ trait Definitions {
}
def seqType(arg: Type) = typeRef(SeqClass.typeConstructor.prefix, SeqClass, List(arg))
+ def arrayType(arg: Type) = typeRef(ArrayClass.typeConstructor.prefix, ArrayClass, List(arg))
//
// .NET backend
@@ -666,12 +677,13 @@ trait Definitions {
def isNumericValueClass(sym: Symbol): Boolean =
(sym ne BooleanClass) && (boxedClass contains sym)
+ // !!! todo comment & rename!
def isValueType(sym: Symbol) =
isValueClass(sym) || unboxMethod.contains(sym)
/** Is symbol a value or array class? */
def isUnboxedClass(sym: Symbol): Boolean =
- isValueType(sym) || sym == ArrayClass
+ isValueType(sym) || !settings.newArrays.value && sym == ArrayClass
def signature(tp: Type): String = {
def erasure(tp: Type): Type = tp match {
@@ -740,8 +752,8 @@ trait Definitions {
StringClass, "+", anyparam, StringClass.typeConstructor) setFlag FINAL
// #2264
- val tmp = AnnotationDefaultAttr
-
+ var tmp = AnnotationDefaultAttr
+ tmp = RepeatedParamClass // force initalization
if (forMSIL) {
val intType = IntClass.typeConstructor
val intParam = List(intType)
@@ -781,8 +793,7 @@ trait Definitions {
newMethod(StringClass, "trim", List(), stringType)
newMethod(StringClass, "intern", List(), stringType)
newMethod(StringClass, "replace", List(charType, charType), stringType)
- newMethod(StringClass, "toCharArray", List(),
- appliedType(ArrayClass.typeConstructor, List(charType)))
+ newMethod(StringClass, "toCharArray", List(), arrayType(charType))
}
} //init
diff --git a/src/compiler/scala/tools/nsc/symtab/StdNames.scala b/src/compiler/scala/tools/nsc/symtab/StdNames.scala
index 410cc75b67..94fc787e76 100644
--- a/src/compiler/scala/tools/nsc/symtab/StdNames.scala
+++ b/src/compiler/scala/tools/nsc/symtab/StdNames.scala
@@ -197,6 +197,7 @@ trait StdNames {
val ROOT = newTermName("<root>")
val ROOTPKG = newTermName("_root_")
val REPEATED_PARAM_CLASS_NAME = newTermName("<repeated>")
+ val JAVA_REPEATED_PARAM_CLASS_NAME = newTermName("<repeated...>")
val BYNAME_PARAM_CLASS_NAME = newTermName("<byname>")
val EQUALS_PATTERN_NAME = newTermName("<equals>")
val SELF = newTermName("$this")
@@ -312,6 +313,7 @@ trait StdNames {
val map = newTermName("map")
val Mutable = newTypeName("Mutable")
val ne = newTermName("ne")
+ val newArray = newTermName("newArray")
val next = newTermName("next")
val notify_ = newTermName("notify")
val notifyAll_ = newTermName("notifyAll")
diff --git a/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala b/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala
index 3816b89e59..ab7dd877c7 100644
--- a/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala
+++ b/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala
@@ -536,7 +536,8 @@ abstract class ClassfileParser {
}
}
- /** Convert repeated parameters to arrays if they occur as part of a Java method
+ /** Convert array parameters denoting a repeated parameter of a Java method
+ * to JavaRepeatedParamClass types.
*/
private def arrayToRepeated(tp: Type): Type = tp match {
case MethodType(params, rtpe) =>
@@ -544,7 +545,7 @@ abstract class ClassfileParser {
assert(formals.last.typeSymbol == definitions.ArrayClass)
val method = params.last.owner
val newParams = method.newSyntheticValueParams(formals.init :::
- List(appliedType(definitions.RepeatedParamClass.typeConstructor, List(formals.last.typeArgs.head))))
+ List(appliedType(definitions.JavaRepeatedParamClass.typeConstructor, List(formals.last.typeArgs.head))))
MethodType(newParams, rtpe)
case PolyType(tparams, rtpe) =>
PolyType(tparams, arrayToRepeated(rtpe))
diff --git a/src/compiler/scala/tools/nsc/transform/CleanUp.scala b/src/compiler/scala/tools/nsc/transform/CleanUp.scala
index 47e62a05fe..45acc4f763 100644
--- a/src/compiler/scala/tools/nsc/transform/CleanUp.scala
+++ b/src/compiler/scala/tools/nsc/transform/CleanUp.scala
@@ -338,6 +338,7 @@ abstract class CleanUp extends Transform with ast.TreeDSL {
}
def boxArray(t: Tree) = {
+ assert(!settings.newArrays.value)
val sym = currentOwner.newValue(ad.pos, mkTerm()) setInfo ObjectClass.tpe
BLOCK(
VAL(sym) === t,
diff --git a/src/compiler/scala/tools/nsc/transform/Erasure.scala b/src/compiler/scala/tools/nsc/transform/Erasure.scala
index d443cbdc70..0efd87a0ac 100644
--- a/src/compiler/scala/tools/nsc/transform/Erasure.scala
+++ b/src/compiler/scala/tools/nsc/transform/Erasure.scala
@@ -51,6 +51,8 @@ abstract class Erasure extends AddInterfaces with typechecker.Analyzer with ast.
0
}
+ def isTopLevelGenericArray(tp: Type): Boolean = genericArrayLevel(tp) == 1
+
/** <p>
* The erasure <code>|T|</code> of a type <code>T</code>. This is:
* </p>
@@ -103,7 +105,7 @@ abstract class Erasure extends AddInterfaces with typechecker.Analyzer with ast.
}
if (sym == ArrayClass)
if (!settings.newArrays.value && isGeneric(tp)) erasedTypeRef(BoxedArrayClass)
- else if (settings.newArrays.value && genericArrayLevel(tp) == 1) ObjectClass.tpe
+ else if (settings.newArrays.value && isTopLevelGenericArray(tp)) ObjectClass.tpe
else typeRef(apply(pre), sym, args map this)
else if (sym == AnyClass || sym == AnyValClass || sym == SingletonClass) erasedTypeRef(ObjectClass)
else if (sym == UnitClass) erasedTypeRef(BoxedUnitClass)
@@ -603,8 +605,9 @@ abstract class Erasure extends AddInterfaces with typechecker.Analyzer with ast.
atPos(tree.pos)(Apply(Select(qual1, "to" + targClass.name), List()))
else
*/
- if (isValueType(targClass) ||
- (targClass == ArrayClass && (qualClass isNonBottomSubClass BoxedArrayClass))) {
+ if (isValueType(targClass)) {
+ unbox(qual1, targ.tpe)
+ } else if (targClass == ArrayClass && (qualClass isNonBottomSubClass BoxedArrayClass)) {
assert(!settings.newArrays.value)
unbox(qual1, targ.tpe)
} else if (!settings.newArrays.value && targClass == ArrayClass && qualClass == ObjectClass || isSeqClass(targClass)) {
@@ -623,28 +626,24 @@ abstract class Erasure extends AddInterfaces with typechecker.Analyzer with ast.
adaptMember(atPos(tree.pos)(Select(qual, getMember(ObjectClass, name))))
else {
var qual1 = typedQualifier(qual);
- if (tree.symbol.owner == ArrayClass && qual1.tpe.typeSymbol == AnyRefClass && settings.newArrays.value) {
- typedPos(tree.pos) { gen.mkRuntimeCall("array_"+name, List(qual)) }
- } else {
- if ((isValueType(qual1.tpe.typeSymbol) && !isUnboxedValueMember(tree.symbol)) ||
- (qual1.tpe.typeSymbol == ArrayClass && !isUnboxedArrayMember(tree.symbol) && !settings.newArrays.value))
- qual1 = box(qual1);
- else if (!isValueType(qual1.tpe.typeSymbol) && isUnboxedValueMember(tree.symbol))
- qual1 = unbox(qual1, tree.symbol.owner.tpe)
- else if (tree.symbol.owner == ArrayClass && (BoxedArrayClass isSubClass qual1.tpe.typeSymbol) && !settings.newArrays.value)
- qual1 = cast(qual1, BoxedArrayClass.tpe)
+ if ((isValueType(qual1.tpe.typeSymbol) && !isUnboxedValueMember(tree.symbol)) ||
+ (qual1.tpe.typeSymbol == ArrayClass && !isUnboxedArrayMember(tree.symbol) && !settings.newArrays.value))
+ qual1 = box(qual1);
+ else if (!isValueType(qual1.tpe.typeSymbol) && isUnboxedValueMember(tree.symbol))
+ qual1 = unbox(qual1, tree.symbol.owner.tpe)
+ else if (tree.symbol.owner == ArrayClass && (BoxedArrayClass isSubClass qual1.tpe.typeSymbol) && !settings.newArrays.value)
+ qual1 = cast(qual1, BoxedArrayClass.tpe)
- if (isUnboxedClass(tree.symbol.owner) && !isUnboxedClass(qual1.tpe.typeSymbol))
- tree.symbol = NoSymbol
- else if (qual1.tpe.isInstanceOf[MethodType] && qual1.tpe.paramTypes.isEmpty) {
- assert(qual1.symbol.isStable, qual1.symbol);
- qual1 = Apply(qual1, List()) setPos qual1.pos setType qual1.tpe.resultType
- } else if (!(qual1.isInstanceOf[Super] || (qual1.tpe.typeSymbol isSubClass tree.symbol.owner))) {
- // println("member cast "+tree.symbol+" "+tree.symbol.ownerChain+" "+qual1+" "+qual1.tpe)
- qual1 = cast(qual1, tree.symbol.owner.tpe)
- }
- treeCopy.Select(tree, qual1, name)
+ if (isUnboxedClass(tree.symbol.owner) && !isUnboxedClass(qual1.tpe.typeSymbol))
+ tree.symbol = NoSymbol
+ else if (qual1.tpe.isInstanceOf[MethodType] && qual1.tpe.paramTypes.isEmpty) {
+ assert(qual1.symbol.isStable, qual1.symbol);
+ qual1 = Apply(qual1, List()) setPos qual1.pos setType qual1.tpe.resultType
+ } else if (!(qual1.isInstanceOf[Super] || (qual1.tpe.typeSymbol isSubClass tree.symbol.owner))) {
+ // println("member cast "+tree.symbol+" "+tree.symbol.ownerChain+" "+qual1+" "+qual1.tpe)
+ qual1 = cast(qual1, tree.symbol.owner.tpe)
}
+ treeCopy.Select(tree, qual1, name)
}
case _ =>
tree
@@ -969,6 +968,11 @@ abstract class Erasure extends AddInterfaces with typechecker.Analyzer with ast.
fun.symbol != Object_isInstanceOf) =>
// leave all other type tests/type casts, remove all other type applications
fun
+ case Apply(fn @ Select(qual, name), args)
+ if (settings.newArrays.value && fn.symbol.owner == ArrayClass && isTopLevelGenericArray(qual.tpe.widen)) =>
+ // convert calls to apply/update/length on generic arrays to
+ // calls of ScalaRunTime.array_xxx method calls
+ typedPos(tree.pos) { gen.mkRuntimeCall("array_"+name, qual :: args) }
case Apply(fn, args) =>
if (!settings.newArrays.value) {
def isGenericArray(tpe: Type): Boolean = erasure(tpe).typeSymbol == BoxedArrayClass
diff --git a/src/compiler/scala/tools/nsc/transform/UnCurry.scala b/src/compiler/scala/tools/nsc/transform/UnCurry.scala
index 9f1897353e..e10a8d8365 100644
--- a/src/compiler/scala/tools/nsc/transform/UnCurry.scala
+++ b/src/compiler/scala/tools/nsc/transform/UnCurry.scala
@@ -22,7 +22,8 @@ import scala.tools.nsc.util.Position
* - for every argument to a def parameter `x: => T':
* if argument is not a reference to a def parameter:
* convert argument `e' to (expansion of) `() => e'
- * - for every repeated parameter `x: T*' --> x: Seq[T].
+ * - for every repeated Scala parameter `x: T*' --> x: Seq[T].
+ * - for every repeated Java parameter `x: T*' --> x: Array[T].
* - for every argument list that corresponds to a repeated parameter
* (a_1, ..., a_n) => (Seq(a_1, ..., a_n))
* - for every argument list that is an escaped sequence
@@ -67,6 +68,8 @@ abstract class UnCurry extends InfoTransform with TypingTransformers {
apply(functionType(List(), arg))
case TypeRef(pre, sym, args) if (sym == RepeatedParamClass) =>
apply(appliedType(SeqClass.typeConstructor, args))
+ case TypeRef(pre, sym, args) if (sym == JavaRepeatedParamClass) =>
+ apply(appliedType(ArrayClass.typeConstructor, args))
case _ =>
expandAlias(mapOver(tp))
}
@@ -89,31 +92,13 @@ abstract class UnCurry extends InfoTransform with TypingTransformers {
}
}
- /** Convert repeated parameters to arrays if they occur as part of a Java method
- */
- private def repeatedToArray(tp: Type): Type = tp match {
- case MethodType(params, rtpe)
- if (!params.isEmpty && params.last.tpe.typeSymbol == RepeatedParamClass) =>
- val arrayParam = params.last.owner.newSyntheticValueParams(List(
- appliedType(ArrayClass.typeConstructor, List(params.last.tpe.typeArgs.head))))
- MethodType(params.init ::: arrayParam, rtpe)
- case PolyType(tparams, rtpe) =>
- val rtpe1 = repeatedToArray(rtpe)
- if (rtpe1 eq rtpe) tp
- else PolyType(tparams, rtpe1)
- case _ =>
- tp
- }
-
/** - return symbol's transformed type,
* - if symbol is a def parameter with transformed type T, return () => T
*
* @MAT: starting with this phase, the info of every symbol will be normalized
*/
def transformInfo(sym: Symbol, tp: Type): Type =
- if (sym.isType) uncurryType(tp)
- else if (sym.isMethod && sym.hasFlag(JAVA)) uncurry(repeatedToArray(tp))
- else uncurry(tp)
+ if (sym.isType) uncurryType(tp) else uncurry(tp)
/** Traverse tree omitting local method definitions.
* If a `return' is encountered, set `returnFound' to true.
@@ -374,8 +359,10 @@ abstract class UnCurry extends InfoTransform with TypingTransformers {
def transformArgs(pos: Position, args: List[Tree], formals: List[Type], isJava: Boolean) = {
val args1 = formals.lastOption match {
- case Some(TypeRef(pre, sym, List(elempt))) if (sym == RepeatedParamClass) =>
+ case Some(lastFormal) if isRepeatedParamType(lastFormal) =>
+
def callMethod(tree: Tree, nme: Name): Tree = {
+ assert(!settings.newArrays.value)
val sym = tree.tpe member nme
assert(sym != NoSymbol)
val arguments =
@@ -389,17 +376,41 @@ abstract class UnCurry extends InfoTransform with TypingTransformers {
}
def mkArrayValue(ts: List[Tree]) = {
- val arr = ArrayValue(TypeTree(elempt), ts) setType formals.last
+ val elemTp = lastFormal.typeArgs.head
+ val arr = ArrayValue(TypeTree(elemTp), ts) setType arrayType(elemTp)
if (isJava || inPattern) arr
+ else if (settings.newArrays.value)
+ atPhase(phase.next) {
+ localTyper.typedPos(pos) {
+ val predef = gen.mkAttributedRef(PredefModule)
+ val meth =
+ if ((elemTp <:< AnyRefClass.tpe) || isValueClass(elemTp.typeSymbol))
+ Select(predef, "wrapArray")
+ else
+ TypeApply(Select(predef, "genericWrapArray"), List(TypeTree(elemTp)))
+ Apply(meth, List(arr))
+ }
+ }
else callMethod(arr, nme.toSequence) // println("need to callMethod("+arr+", nme.toSequence)"); arr }
- }
+ } setType formals.last
// when calling into java varargs, make sure it's an array - see bug #1360
def forceToArray(arg: Tree) = {
val Typed(tree, _) = arg
if (isJava && tree.tpe.typeSymbol != ArrayClass &&
- (tree.tpe.typeSymbol isSubClass TraversableClass)) callMethod(tree, nme.toArray)
- else tree
+ (tree.tpe.typeSymbol isSubClass TraversableClass)) {
+ if (settings.newArrays.value) {
+ val toArraySym = tree.tpe member nme.toArray
+ assert(toArraySym != NoSymbol)
+ atPhase(phase.next) {
+ localTyper.typedPos(pos) {
+ Apply(
+ gen.mkAttributedSelect(tree, toArraySym),
+ List(localTyper.getManifestTree(tree.pos, tree.tpe.typeArgs.head, false)))
+ }
+ }
+ } else callMethod(tree, nme.toArray)
+ } else tree
}
if (args.isEmpty)
diff --git a/src/compiler/scala/tools/nsc/typechecker/EtaExpansion.scala b/src/compiler/scala/tools/nsc/typechecker/EtaExpansion.scala
index 5f123ffa06..7d75994ef3 100644
--- a/src/compiler/scala/tools/nsc/typechecker/EtaExpansion.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/EtaExpansion.scala
@@ -76,6 +76,7 @@ trait EtaExpansion { self: Analyzer =>
if (treeInfo.isPureExpr(tree)) tree
else {
val vname: Name = freshName(tree.pos, 0)
+ // Problem with ticket #2351 here
defs += atPos(tree.pos) {
ValDef(Modifiers(SYNTHETIC), vname, TypeTree(), tree)
}
diff --git a/src/compiler/scala/tools/nsc/typechecker/Implicits.scala b/src/compiler/scala/tools/nsc/typechecker/Implicits.scala
index 96670ab131..dbc90e569b 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Implicits.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Implicits.scala
@@ -743,7 +743,7 @@ self: Analyzer =>
val timer3 = System.nanoTime()
if (result == SearchFailure) manifFail += timer3 - timer2 else manifSucceed += timer3 - timer2
if (result == SearchFailure && settings.debug.value)
- println("no implicits found for "+pt+" "+pt.typeSymbol.info.baseClasses+" "+parts(pt)+implicitsOfExpectedType)
+ log("no implicits found for "+pt+" "+pt.typeSymbol.info.baseClasses+" "+parts(pt)+implicitsOfExpectedType)
implicitTime += System.nanoTime() - start
result
}
diff --git a/src/compiler/scala/tools/nsc/typechecker/Infer.scala b/src/compiler/scala/tools/nsc/typechecker/Infer.scala
index a6c1cf744b..20f6a1ff45 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Infer.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Infer.scala
@@ -33,8 +33,7 @@ trait Infer {
private def assertNonCyclic(tvar: TypeVar) =
assert(tvar.constr.inst != tvar, tvar.origin)
- def isVarArgs(formals: List[Type]) =
- !formals.isEmpty && (formals.last.typeSymbol == RepeatedParamClass)
+ def isVarArgs(formals: List[Type]) = !formals.isEmpty && isRepeatedParamType(formals.last)
/** The formal parameter types corresponding to <code>formals</code>.
* If <code>formals</code> has a repeated last parameter, a list of
@@ -575,6 +574,8 @@ trait Infer {
tparam.tpe
} else if (targ.typeSymbol == RepeatedParamClass) {
targ.baseType(SeqClass)
+ } else if (targ.typeSymbol == JavaRepeatedParamClass) {
+ targ.baseType(ArrayClass)
} else {
targ.widen
}
diff --git a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala
index 3dec50e03d..7cca32a779 100644
--- a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala
@@ -832,8 +832,7 @@ abstract class RefChecks extends InfoTransform {
def isRepeatedParamArg(tree: Tree) = currentApplication match {
case Apply(fn, args) =>
!args.isEmpty && (args.last eq tree) &&
- fn.tpe.paramTypes.length == args.length &&
- fn.tpe.paramTypes.last.typeSymbol == RepeatedParamClass
+ fn.tpe.paramTypes.length == args.length && isRepeatedParamType(fn.tpe.paramTypes.last)
case _ =>
false
}
diff --git a/src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala b/src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala
index c5976a6f3f..5001f8b9bf 100644
--- a/src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala
@@ -336,7 +336,7 @@ abstract class SuperAccessors extends transform.Transform with transform.TypingT
if (sym.isSubClass(ownerClass)) true else false
case _ => false
}
- if (v.info.typeSymbol == definitions.RepeatedParamClass) {
+ if (definitions.isRepeatedParamType(v.info)) {
res = gen.wildcardStar(res)
log("adapted to wildcard star: " + res)
}
diff --git a/src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala b/src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala
index d1a746f222..a1c1a7b661 100644
--- a/src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala
@@ -172,8 +172,8 @@ trait SyntheticMethods extends ast.TreeDSL {
def makeTrees(acc: Symbol, cpt: Type): (Tree, Bind) = {
val varName = context.unit.fresh.newName(clazz.pos.focus, acc.name + "$")
val (eqMethod, binding) =
- if (cpt.isVarargs) (nme.sameElements, Star(WILD()))
- else (nme.EQ , WILD() )
+ if (isRepeatedParamType(cpt)) (nme.sameElements, Star(WILD()))
+ else (nme.EQ , WILD() )
((varName DOT eqMethod)(Ident(acc)), varName BIND binding)
}
diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
index d936941224..2d519f8da8 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
@@ -397,7 +397,7 @@ trait Typers { self: Analyzer =>
/*
if (formals.exists(_.typeSymbol == ByNameParamClass) && formals.length != 1)
error(pos, "methods with `=>'-parameter can be converted to function values only if they take no other parameters")
- if (formals exists (_.typeSymbol == RepeatedParamClass))
+ if (formals exists (isRepeatedParamType(_)))
error(pos, "methods with `*'-parameters cannot be converted to function values");
*/
if (restpe.isDependent)
@@ -913,7 +913,7 @@ trait Typers { self: Analyzer =>
case _ =>
false
}
- if (isStructuralType(pt) && tree.tpe.typeSymbol == ArrayClass) {
+ if (isStructuralType(pt) && tree.tpe.typeSymbol == ArrayClass && !settings.newArrays.value) {
// all Arrays used as structural refinement typed values must be boxed
// this does not solve the case where the type to be adapted to comes
// from a type variable that was bound by a strctural but is instantiated
@@ -1449,7 +1449,7 @@ trait Typers { self: Analyzer =>
case Apply(fn, args) =>
val (superConstr, args1) = decompose(fn)
val formals = fn.tpe.paramTypes
- val args2 = if (formals.isEmpty || formals.last.typeSymbol != RepeatedParamClass) args
+ val args2 = if (formals.isEmpty || !isRepeatedParamType(formals.last)) args
else args.take(formals.length - 1) ::: List(EmptyTree)
if (args2.length != formals.length)
assert(false, "mismatch " + clazz + " " + formals + " " + args2);//debug
@@ -1522,7 +1522,7 @@ trait Typers { self: Analyzer =>
val tparams1 = ddef.tparams mapConserve typedTypeDef
val vparamss1 = ddef.vparamss mapConserve (_ mapConserve typedValDef)
for (vparams1 <- vparamss1; if !vparams1.isEmpty; vparam1 <- vparams1.init) {
- if (vparam1.symbol.tpe.typeSymbol == RepeatedParamClass)
+ if (isRepeatedParamType(vparam1.symbol.tpe))
error(vparam1.pos, "*-parameter must come last")
}
var tpt1 = checkNoEscaping.privates(meth, typedType(ddef.tpt))
@@ -1577,10 +1577,7 @@ trait Typers { self: Analyzer =>
}
}
- if (meth.paramss.exists( ps => {
- ps.exists(_.hasFlag(DEFAULTPARAM)) &&
- (ps.last.tpe.typeSymbol == RepeatedParamClass)
- }))
+ if (meth.paramss.exists(ps => ps.exists(_.hasFlag(DEFAULTPARAM)) && isRepeatedParamType(ps.last.tpe)))
error(meth.pos, "a parameter section with a `*'-parameter is not allowed to have default arguments")
}
@@ -3660,7 +3657,18 @@ trait Typers { self: Analyzer =>
typed1(atPos(tree.pos)(Block(stats, Apply(expr, args))), mode, pt)
case Apply(fun, args) =>
- typedApply(fun, args)
+ typedApply(fun, args) match {
+ case Apply(Select(New(tpt), name), args)
+ if (settings.newArrays.value && tpt.tpe.typeSymbol == ArrayClass && args.length == 1 && erasure.isTopLevelGenericArray(tpt.tpe)) =>
+ // convert new Array[T](len) to evidence[ClassManifest[T]].newArray(len)
+ val newArrayApp = atPos(tree.pos) {
+ val manif = getManifestTree(tree.pos, tpt.tpe.typeArgs.head, false)
+ Apply(Select(manif, nme.newArray), args)
+ }
+ typed(newArrayApp, mode, pt)
+ case tree1 =>
+ tree1
+ }
case ApplyDynamic(qual, args) =>
val reflectiveCalls = !(settings.refinementMethodDispatch.value == "invoke-dynamic")
@@ -3884,16 +3892,17 @@ trait Typers { self: Analyzer =>
case None => typed(tree, pt)
}
- def findManifest(tp: Type, full: Boolean) =
+ def findManifest(tp: Type, full: Boolean) = atPhase(currentRun.typerPhase) {
inferImplicit(
EmptyTree,
appliedType((if (full) FullManifestClass else PartialManifestClass).typeConstructor, List(tp)),
true, false, context)
+ }
def getManifestTree(pos: Position, tp: Type, full: Boolean): Tree = {
val manifestOpt = findManifest(tp, false)
if (manifestOpt.tree.isEmpty) {
- error(pos, "cannot find "+(if (full) "" else "class ")+"manifest for element type of "+tp)
+ error(pos, "cannot find "+(if (full) "" else "class ")+"manifest for element type "+tp)
Literal(Constant(null))
} else {
manifestOpt.tree
diff --git a/src/library/scala/LowPriorityImplicits.scala b/src/library/scala/LowPriorityImplicits.scala
index afa3eaeb08..ea12c07d63 100644
--- a/src/library/scala/LowPriorityImplicits.scala
+++ b/src/library/scala/LowPriorityImplicits.scala
@@ -20,29 +20,29 @@ import collection.immutable.WrappedString
*/
class LowPriorityImplicits {
- implicit def genericArrayWrapper[T](xs: Array[T]): WrappedArray[T] = (xs: AnyRef) match { // !!! drop the AnyRef and get unreachable code errors!
- case x: Array[AnyRef] => arrayWrapper[AnyRef](x).asInstanceOf[WrappedArray[T]]
- case x: Array[Int] => arrayWrapper(x).asInstanceOf[WrappedArray[T]]
- case x: Array[Double] => arrayWrapper(x).asInstanceOf[WrappedArray[T]]
- case x: Array[Long] => arrayWrapper(x).asInstanceOf[WrappedArray[T]]
- case x: Array[Float] => arrayWrapper(x).asInstanceOf[WrappedArray[T]]
- case x: Array[Char] => arrayWrapper(x).asInstanceOf[WrappedArray[T]]
- case x: Array[Byte] => arrayWrapper(x).asInstanceOf[WrappedArray[T]]
- case x: Array[Short] => arrayWrapper(x).asInstanceOf[WrappedArray[T]]
- case x: Array[Boolean] => arrayWrapper(x).asInstanceOf[WrappedArray[T]]
- case x: Array[Unit] => arrayWrapper(x).asInstanceOf[WrappedArray[T]]
+ implicit def genericWapArray[T](xs: Array[T]): WrappedArray[T] = (xs: AnyRef) match { // !!! drop the AnyRef and get unreachable code errors!
+ case x: Array[AnyRef] => wrapArray[AnyRef](x).asInstanceOf[WrappedArray[T]]
+ case x: Array[Int] => wrapArray(x).asInstanceOf[WrappedArray[T]]
+ case x: Array[Double] => wrapArray(x).asInstanceOf[WrappedArray[T]]
+ case x: Array[Long] => wrapArray(x).asInstanceOf[WrappedArray[T]]
+ case x: Array[Float] => wrapArray(x).asInstanceOf[WrappedArray[T]]
+ case x: Array[Char] => wrapArray(x).asInstanceOf[WrappedArray[T]]
+ case x: Array[Byte] => wrapArray(x).asInstanceOf[WrappedArray[T]]
+ case x: Array[Short] => wrapArray(x).asInstanceOf[WrappedArray[T]]
+ case x: Array[Boolean] => wrapArray(x).asInstanceOf[WrappedArray[T]]
+ case x: Array[Unit] => wrapArray(x).asInstanceOf[WrappedArray[T]]
}
- implicit def arrayWrapper[T <: AnyRef](xs: Array[T]): WrappedArray[T] = new WrappedArray.ofRef[T](xs.asInstanceOf[Array[AnyRef]])
- implicit def arrayWrapper(xs: Array[Int]): WrappedArray[Int] = new WrappedArray.ofInt(xs)
- implicit def arrayWrapper(xs: Array[Double]): WrappedArray[Double] = new WrappedArray.ofDouble(xs)
- implicit def arrayWrapper(xs: Array[Long]): WrappedArray[Long] = new WrappedArray.ofLong(xs)
- implicit def arrayWrapper(xs: Array[Float]): WrappedArray[Float] = new WrappedArray.ofFloat(xs)
- implicit def arrayWrapper(xs: Array[Char]): WrappedArray[Char] = new WrappedArray.ofChar(xs)
- implicit def arrayWrapper(xs: Array[Byte]): WrappedArray[Byte] = new WrappedArray.ofByte(xs)
- implicit def arrayWrapper(xs: Array[Short]): WrappedArray[Short] = new WrappedArray.ofShort(xs)
- implicit def arrayWrapper(xs: Array[Boolean]): WrappedArray[Boolean] = new WrappedArray.ofBoolean(xs)
- implicit def arrayWrapper(xs: Array[Unit]): WrappedArray[Unit] = new WrappedArray.ofUnit(xs)
+ implicit def wrapArray[T <: AnyRef](xs: Array[T]): WrappedArray[T] = new WrappedArray.ofRef[T](xs.asInstanceOf[Array[AnyRef]])
+ implicit def wrapArray(xs: Array[Int]): WrappedArray[Int] = new WrappedArray.ofInt(xs)
+ implicit def wrapArray(xs: Array[Double]): WrappedArray[Double] = new WrappedArray.ofDouble(xs)
+ implicit def wrapArray(xs: Array[Long]): WrappedArray[Long] = new WrappedArray.ofLong(xs)
+ implicit def wrapArray(xs: Array[Float]): WrappedArray[Float] = new WrappedArray.ofFloat(xs)
+ implicit def wrapArray(xs: Array[Char]): WrappedArray[Char] = new WrappedArray.ofChar(xs)
+ implicit def wrapArray(xs: Array[Byte]): WrappedArray[Byte] = new WrappedArray.ofByte(xs)
+ implicit def wrapArray(xs: Array[Short]): WrappedArray[Short] = new WrappedArray.ofShort(xs)
+ implicit def wrapArray(xs: Array[Boolean]): WrappedArray[Boolean] = new WrappedArray.ofBoolean(xs)
+ implicit def wrapArray(xs: Array[Unit]): WrappedArray[Unit] = new WrappedArray.ofUnit(xs)
implicit def wrapString(s: String): WrappedString = new WrappedString(s)
implicit def unwrapString(ws: WrappedString): String = ws.self
diff --git a/src/library/scala/Predef.scala b/src/library/scala/Predef.scala
index 35c67e061c..1412fbc924 100644
--- a/src/library/scala/Predef.scala
+++ b/src/library/scala/Predef.scala
@@ -218,29 +218,29 @@ object Predef extends LowPriorityImplicits {
implicit def any2stringadd(x: Any) = new runtime.StringAdd(x)
- implicit def genericAugmentArray[T](xs: Array[T]): ArrayOps[T] = (xs: AnyRef) match { // !!! drop the AnyRef and get unreachable code errors!
- case x: Array[AnyRef] => augmentArray[AnyRef](x).asInstanceOf[ArrayOps[T]]
- case x: Array[Int] => augmentArray(x).asInstanceOf[ArrayOps[T]]
- case x: Array[Double] => augmentArray(x).asInstanceOf[ArrayOps[T]]
- case x: Array[Long] => augmentArray(x).asInstanceOf[ArrayOps[T]]
- case x: Array[Float] => augmentArray(x).asInstanceOf[ArrayOps[T]]
- case x: Array[Char] => augmentArray(x).asInstanceOf[ArrayOps[T]]
- case x: Array[Byte] => augmentArray(x).asInstanceOf[ArrayOps[T]]
- case x: Array[Short] => augmentArray(x).asInstanceOf[ArrayOps[T]]
- case x: Array[Boolean] => augmentArray(x).asInstanceOf[ArrayOps[T]]
- case x: Array[Unit] => augmentArray(x).asInstanceOf[ArrayOps[T]]
+ implicit def genericArrayOps[T](xs: Array[T]): ArrayOps[T] = (xs: AnyRef) match { // !!! drop the AnyRef and get unreachable code errors!
+ case x: Array[AnyRef] => arrayOps[AnyRef](x).asInstanceOf[ArrayOps[T]]
+ case x: Array[Int] => arrayOps(x).asInstanceOf[ArrayOps[T]]
+ case x: Array[Double] => arrayOps(x).asInstanceOf[ArrayOps[T]]
+ case x: Array[Long] => arrayOps(x).asInstanceOf[ArrayOps[T]]
+ case x: Array[Float] => arrayOps(x).asInstanceOf[ArrayOps[T]]
+ case x: Array[Char] => arrayOps(x).asInstanceOf[ArrayOps[T]]
+ case x: Array[Byte] => arrayOps(x).asInstanceOf[ArrayOps[T]]
+ case x: Array[Short] => arrayOps(x).asInstanceOf[ArrayOps[T]]
+ case x: Array[Boolean] => arrayOps(x).asInstanceOf[ArrayOps[T]]
+ case x: Array[Unit] => arrayOps(x).asInstanceOf[ArrayOps[T]]
}
- implicit def augmentArray[T <: AnyRef](xs: Array[T]): ArrayOps[T] = new ArrayOps.ofRef[T](xs.asInstanceOf[Array[AnyRef]])
- implicit def augmentArray(xs: Array[Int]): ArrayOps[Int] = new ArrayOps.ofInt(xs)
- implicit def augmentArray(xs: Array[Double]): ArrayOps[Double] = new ArrayOps.ofDouble(xs)
- implicit def augmentArray(xs: Array[Long]): ArrayOps[Long] = new ArrayOps.ofLong(xs)
- implicit def augmentArray(xs: Array[Float]): ArrayOps[Float] = new ArrayOps.ofFloat(xs)
- implicit def augmentArray(xs: Array[Char]): ArrayOps[Char] = new ArrayOps.ofChar(xs)
- implicit def augmentArray(xs: Array[Byte]): ArrayOps[Byte] = new ArrayOps.ofByte(xs)
- implicit def augmentArray(xs: Array[Short]): ArrayOps[Short] = new ArrayOps.ofShort(xs)
- implicit def augmentArray(xs: Array[Boolean]): ArrayOps[Boolean] = new ArrayOps.ofBoolean(xs)
- implicit def augmentArray(xs: Array[Unit]): ArrayOps[Unit] = new ArrayOps.ofUnit(xs)
+ implicit def arrayOps[T <: AnyRef](xs: Array[T]): ArrayOps[T] = new ArrayOps.ofRef[T](xs.asInstanceOf[Array[AnyRef]])
+ implicit def arrayOps(xs: Array[Int]): ArrayOps[Int] = new ArrayOps.ofInt(xs)
+ implicit def arrayOps(xs: Array[Double]): ArrayOps[Double] = new ArrayOps.ofDouble(xs)
+ implicit def arrayOps(xs: Array[Long]): ArrayOps[Long] = new ArrayOps.ofLong(xs)
+ implicit def arrayOps(xs: Array[Float]): ArrayOps[Float] = new ArrayOps.ofFloat(xs)
+ implicit def arrayOps(xs: Array[Char]): ArrayOps[Char] = new ArrayOps.ofChar(xs)
+ implicit def arrayOps(xs: Array[Byte]): ArrayOps[Byte] = new ArrayOps.ofByte(xs)
+ implicit def arrayOps(xs: Array[Short]): ArrayOps[Short] = new ArrayOps.ofShort(xs)
+ implicit def arrayOps(xs: Array[Boolean]): ArrayOps[Boolean] = new ArrayOps.ofBoolean(xs)
+ implicit def arrayOps(xs: Array[Unit]): ArrayOps[Unit] = new ArrayOps.ofUnit(xs)
implicit def exceptionWrapper(exc: Throwable) = new runtime.RichException(exc)