summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSeth Tisue <seth@tisue.net>2017-02-16 14:14:39 -0800
committerSeth Tisue <seth@tisue.net>2017-02-16 14:34:18 -0800
commit04c45e15f198c3e33b0e6709fb8ca5267f129fac (patch)
tree215307f083dba29d2c53c83ca3702c8d4a34d27f
parent6be69d6d5e710e2022772a326a48baf093a70508 (diff)
parent096502880900d8daa75d813c63ac88aa50c25ef0 (diff)
downloadscala-04c45e15f198c3e33b0e6709fb8ca5267f129fac.tar.gz
scala-04c45e15f198c3e33b0e6709fb8ca5267f129fac.tar.bz2
scala-04c45e15f198c3e33b0e6709fb8ca5267f129fac.zip
Merge commit '0965028809' into merge-2.11.x-to-2.12.x-20170214
-rw-r--r--bincompat-backward.whitelist.conf211
-rw-r--r--bincompat-forward.whitelist.conf349
-rw-r--r--src/compiler/scala/tools/nsc/transform/Erasure.scala38
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/RefChecks.scala2
-rw-r--r--src/library/scala/collection/immutable/FilteredTraversableInternal.scala104
-rw-r--r--src/library/scala/collection/immutable/List.scala53
-rw-r--r--src/library/scala/collection/immutable/RedBlackTree.scala5
-rw-r--r--src/library/scala/collection/mutable/ArrayOps.scala74
-rw-r--r--src/library/scala/collection/mutable/WrappedArray.scala71
-rw-r--r--src/reflect/scala/reflect/internal/Flags.scala2
-rw-r--r--src/reflect/scala/reflect/runtime/JavaUniverseForce.scala2
-rw-r--r--test/benchmarks/src/main/scala/scala/collection/immutable/ListBenchmark.scala72
-rw-r--r--test/files/run/repl-colon-type.check8
-rw-r--r--test/files/run/t1459.check3
-rw-r--r--test/files/run/t1459/InheritingPrinter.scala6
-rw-r--r--test/files/run/t1459/JavaPrinter.java7
-rw-r--r--test/files/run/t1459/ScalaPrinter.scala6
-rw-r--r--test/files/run/t1459/Test.java15
-rw-r--r--test/files/run/t1459/VarArg.java3
-rw-r--r--test/files/run/t1459generic.check4
-rw-r--r--test/files/run/t1459generic/Impl.scala4
-rw-r--r--test/files/run/t1459generic/Test.java10
-rw-r--r--test/files/run/t1459generic/VarargGeneric.java7
-rw-r--r--test/files/run/t9013/Test.java20
-rw-r--r--test/files/run/t9013/test.scala18
-rw-r--r--test/junit/scala/collection/IndexedSeqTest.scala578
26 files changed, 1606 insertions, 66 deletions
diff --git a/bincompat-backward.whitelist.conf b/bincompat-backward.whitelist.conf
index b88fa64584..57dc564e8a 100644
--- a/bincompat-backward.whitelist.conf
+++ b/bincompat-backward.whitelist.conf
@@ -48,6 +48,217 @@ filter {
{
matchName="scala.collection.immutable.HashMap#HashMapCollision1.contains0"
problemName=DirectMissingMethodProblem
+ },
+ {
+ matchName="scala.collection.mutable.ArrayOps.unzip"
+ problemName=MissingMethodProblem
+ },
+ {
+ matchName="scala.collection.mutable.ArrayOps.unzip3"
+ problemName=MissingMethodProblem
+ },
+ {
+ matchName="scala.collection.mutable.ArrayOps#ofFloat.unzip"
+ problemName=IncompatibleMethTypeProblem
+ },
+ {
+ matchName="scala.collection.mutable.ArrayOps#ofFloat.unzip3"
+ problemName=IncompatibleMethTypeProblem
+ },
+ {
+ matchName="scala.collection.mutable.ArrayOps#ofBoolean.unzip"
+ problemName=IncompatibleMethTypeProblem
+ },
+ {
+ matchName="scala.collection.mutable.ArrayOps#ofBoolean.unzip3"
+ problemName=IncompatibleMethTypeProblem
+ },
+ {
+ matchName="scala.collection.mutable.ArrayOps#ofRef.unzip"
+ problemName=IncompatibleMethTypeProblem
+ },
+ {
+ matchName="scala.collection.mutable.ArrayOps#ofRef.unzip3"
+ problemName=IncompatibleMethTypeProblem
+ },
+ {
+ matchName="scala.collection.mutable.ArrayOps#ofUnit.unzip"
+ problemName=IncompatibleMethTypeProblem
+ },
+ {
+ matchName="scala.collection.mutable.ArrayOps#ofUnit.unzip3"
+ problemName=IncompatibleMethTypeProblem
+ },
+ {
+ matchName="scala.collection.mutable.ArrayOps#ofDouble.unzip"
+ problemName=IncompatibleMethTypeProblem
+ },
+ {
+ matchName="scala.collection.mutable.ArrayOps#ofDouble.unzip3"
+ problemName=IncompatibleMethTypeProblem
+ },
+ // see SI-8200
+ {
+ matchName="scala.reflect.api.StandardLiftables#StandardLiftableInstances.liftTree"
+ problemName=MissingMethodProblem
+ },
+ // see SI-8331
+ {
+ matchName="scala.reflect.api.Internals#ReificationSupportApi#SyntacticTypeAppliedExtractor.unapply"
+ problemName=IncompatibleResultTypeProblem
+ },
+ {
+ matchName="scala.reflect.api.Internals#ReificationSupportApi#SyntacticTypeAppliedExtractor.unapply"
+ problemName=MissingMethodProblem
+ },
+ {
+ matchName="scala.reflect.api.Internals#ReificationSupportApi.SyntacticSelectType"
+ problemName=MissingMethodProblem
+ },
+ {
+ matchName="scala.reflect.api.Internals#ReificationSupportApi.SyntacticAppliedType"
+ problemName=MissingMethodProblem
+ },
+ {
+ matchName="scala.reflect.api.Internals#ReificationSupportApi.SyntacticSelectTerm"
+ problemName=MissingMethodProblem
+ },
+ // see SI-8366
+ {
+ matchName="scala.reflect.api.Internals#ReificationSupportApi.SyntacticPartialFunction"
+ problemName=MissingMethodProblem
+ },
+ {
+ matchName="scala.reflect.api.Mirror.symbolOf"
+ problemName=MissingMethodProblem
+ },
+ {
+ matchName="scala.reflect.api.Mirror.typeOf"
+ problemName=MissingMethodProblem
+ },
+ {
+ matchName="scala.reflect.api.Mirror.weakTypeOf"
+ problemName=MissingMethodProblem
+ },
+ // see SI-8388
+ {
+ matchName="scala.reflect.api.Internals$ReificationSupportApi$SyntacticIdentExtractor"
+ problemName=MissingClassProblem
+ },
+ {
+ matchName="scala.reflect.api.Internals#ReificationSupportApi.SyntacticIdent"
+ problemName=MissingMethodProblem
+ },
+ {
+ matchName="scala.reflect.api.Internals#ReificationSupportApi.SyntacticSingletonType"
+ problemName=MissingMethodProblem
+ },
+ {
+ matchName="scala.reflect.api.Internals#ReificationSupportApi.SyntacticTermIdent"
+ problemName=MissingMethodProblem
+ },
+ {
+ matchName="scala.reflect.api.Internals#ReificationSupportApi.SyntacticTypeIdent"
+ problemName=MissingMethodProblem
+ },
+ {
+ matchName="scala.reflect.api.Internals#ReificationSupportApi.SyntacticCompoundType"
+ problemName=MissingMethodProblem
+ },
+ {
+ matchName="scala.reflect.api.Internals#ReificationSupportApi.SyntacticAnnotatedType"
+ problemName=MissingMethodProblem
+ },
+ {
+ matchName="scala.reflect.api.Internals#ReificationSupportApi.SyntacticTypeProjection"
+ problemName=MissingMethodProblem
+ },
+ {
+ matchName="scala.reflect.api.Internals#ReificationSupportApi.SyntacticExistentialType"
+ problemName=MissingMethodProblem
+ },
+ {
+ matchName="scala.reflect.runtime.SynchronizedOps.newNestedScope"
+ problemName=MissingMethodProblem
+ },
+ // https://github.com/scala/scala/pull/3848 -- SI-8680
+ {
+ matchName="scala.collection.immutable.Stream.scala$collection$immutable$Stream$$loop$6"
+ problemName=MissingMethodProblem
+ },
+ {
+ matchName="scala.collection.immutable.Stream.scala$collection$immutable$Stream$$loop$5"
+ problemName=MissingMethodProblem
+ },
+ {
+ matchName="scala.collection.immutable.Stream.scala$collection$immutable$Stream$$loop$4"
+ problemName=MissingMethodProblem
+ },
+ // SI-8946
+ {
+ matchName="scala.reflect.runtime.ThreadLocalStorage#MyThreadLocalStorage.values"
+ problemName=MissingMethodProblem
+ },
+ // the below method was the unused private (sic!) method but the compatibility checker was complaining about it
+ {
+ matchName="scala.reflect.io.ZipArchive.scala$reflect$io$ZipArchive$$walkIterator"
+ problemName=MissingMethodProblem
+ },
+ // SI-8362: AbstractPromise extends AtomicReference
+ // It's ok to change a package-protected class in an impl package,
+ // even though it's not clear why it changed -- bug in generic signature generation?
+ // -public class scala.concurrent.impl.Promise$DefaultPromise<T> extends scala.concurrent.impl.AbstractPromise implements scala.concurrent.impl.Promise<T>
+ // +public class scala.concurrent.impl.Promise$DefaultPromise<T extends java.lang.Object> extends scala.concurrent.impl.AbstractPromise implements scala.concurrent.impl.Promise<T>
+ {
+ matchName="scala.concurrent.impl.Promise$DefaultPromise"
+ problemName=MissingTypesProblem
+ },
+ // SI-9488: Due to SI-8362 above, toString was silently changed to the AtomicReference toString implementation,
+ // This is fixed by SI-9488, and this should be safe since the class in question is stdlib internal.
+ {
+ matchName="scala.concurrent.impl.Promise.toString"
+ problemName=MissingMethodProblem
+ },
+ // https://github.com/scala/scala/pull/5652
+ {
+ matchName="scala.collection.mutable.ArrayOps#ofChar.slice"
+ problemName=FinalMethodProblem
+ },
+ {
+ matchName="scala.collection.mutable.ArrayOps#ofShort.slice"
+ problemName=FinalMethodProblem
+ },
+ {
+ matchName="scala.collection.mutable.ArrayOps#ofUnit.slice"
+ problemName=FinalMethodProblem
+ },
+ {
+ matchName="scala.collection.mutable.ArrayOps#ofInt.slice"
+ problemName=FinalMethodProblem
+ },
+ {
+ matchName="scala.collection.mutable.ArrayOps#ofBoolean.slice"
+ problemName=FinalMethodProblem
+ },
+ {
+ matchName="scala.collection.mutable.ArrayOps#ofDouble.slice"
+ problemName=FinalMethodProblem
+ },
+ {
+ matchName="scala.collection.mutable.ArrayOps#ofRef.slice"
+ problemName=FinalMethodProblem
+ },
+ {
+ matchName="scala.collection.mutable.ArrayOps#ofByte.slice"
+ problemName=FinalMethodProblem
+ },
+ {
+ matchName="scala.collection.mutable.ArrayOps#ofLong.slice"
+ problemName=FinalMethodProblem
+ },
+ {
+ matchName="scala.collection.mutable.ArrayOps#ofFloat.slice"
+ problemName=FinalMethodProblem
}
]
}
diff --git a/bincompat-forward.whitelist.conf b/bincompat-forward.whitelist.conf
index bb9078c362..045869d41a 100644
--- a/bincompat-forward.whitelist.conf
+++ b/bincompat-forward.whitelist.conf
@@ -58,6 +58,355 @@ filter {
{
matchName="scala.collection.immutable.HashMap#HashMapCollision1.contains0"
problemName=DirectMissingMethodProblem
+ },
+ {
+ matchName="scala.reflect.api.SerializedTypeTag.serialVersionUID"
+ problemName=MissingFieldProblem
+ },
+ {
+ matchName="scala.collection.mutable.ArrayOps$ofChar"
+ problemName=MissingTypesProblem
+ },
+ {
+ matchName="scala.collection.mutable.ArrayOps#ofChar.sliceImpl"
+ problemName=DirectMissingMethodProblem
+ },
+ {
+ matchName="scala.collection.mutable.ArrayOps#ofChar.emptyImpl"
+ problemName=DirectMissingMethodProblem
+ },
+ {
+ matchName="scala.collection.mutable.ArrayOps$ofShort"
+ problemName=MissingTypesProblem
+ },
+ {
+ matchName="scala.collection.mutable.ArrayOps#ofShort.sliceImpl"
+ problemName=DirectMissingMethodProblem
+ },
+ {
+ matchName="scala.collection.mutable.ArrayOps#ofShort.emptyImpl"
+ problemName=DirectMissingMethodProblem
+ },
+ {
+ matchName="scala.collection.mutable.WrappedArray#ofByte.sliceImpl"
+ problemName=DirectMissingMethodProblem
+ },
+ {
+ matchName="scala.collection.mutable.WrappedArray#ofByte.emptyImpl"
+ problemName=DirectMissingMethodProblem
+ },
+ {
+ matchName="scala.collection.mutable.WrappedArray#ofBoolean.sliceImpl"
+ problemName=DirectMissingMethodProblem
+ },
+ {
+ matchName="scala.collection.mutable.WrappedArray#ofBoolean.emptyImpl"
+ problemName=DirectMissingMethodProblem
+ },
+ {
+ matchName="scala.collection.mutable.WrappedArray#ofChar.sliceImpl"
+ problemName=DirectMissingMethodProblem
+ },
+ {
+ matchName="scala.collection.mutable.WrappedArray#ofChar.emptyImpl"
+ problemName=DirectMissingMethodProblem
+ },
+ {
+ matchName="scala.collection.mutable.WrappedArray#ofDouble.sliceImpl"
+ problemName=DirectMissingMethodProblem
+ },
+ {
+ matchName="scala.collection.mutable.WrappedArray#ofDouble.emptyImpl"
+ problemName=DirectMissingMethodProblem
+ },
+ {
+ matchName="scala.collection.mutable.ArrayOps$ofUnit"
+ problemName=MissingTypesProblem
+ },
+ {
+ matchName="scala.collection.mutable.ArrayOps#ofUnit.sliceImpl"
+ problemName=DirectMissingMethodProblem
+ },
+ {
+ matchName="scala.collection.mutable.ArrayOps#ofUnit.emptyImpl"
+ problemName=DirectMissingMethodProblem
+ },
+ {
+ matchName="scala.collection.mutable.ArrayOps#ofInt.sliceImpl$extension"
+ problemName=DirectMissingMethodProblem
+ },
+ {
+ matchName="scala.collection.mutable.ArrayOps#ofInt.emptyImpl$extension"
+ problemName=DirectMissingMethodProblem
+ },
+ {
+ matchName="scala.collection.mutable.ArrayOps$ofInt"
+ problemName=MissingTypesProblem
+ },
+ {
+ matchName="scala.collection.mutable.ArrayOps#ofInt.sliceImpl"
+ problemName=DirectMissingMethodProblem
+ },
+ {
+ matchName="scala.collection.mutable.ArrayOps#ofInt.emptyImpl"
+ problemName=DirectMissingMethodProblem
+ },
+ {
+ matchName="scala.collection.mutable.ArrayOps#ofRef.sliceImpl$extension"
+ problemName=DirectMissingMethodProblem
+ },
+ {
+ matchName="scala.collection.mutable.ArrayOps#ofRef.emptyImpl$extension"
+ problemName=DirectMissingMethodProblem
+ },
+ {
+ matchName="scala.collection.mutable.ArrayOps#ofChar.sliceImpl$extension"
+ problemName=DirectMissingMethodProblem
+ },
+ {
+ matchName="scala.collection.mutable.ArrayOps#ofChar.emptyImpl$extension"
+ problemName=DirectMissingMethodProblem
+ },
+ {
+ matchName="scala.collection.mutable.ArrayOps#ofUnit.sliceImpl$extension"
+ problemName=DirectMissingMethodProblem
+ },
+ {
+ matchName="scala.collection.mutable.ArrayOps#ofUnit.emptyImpl$extension"
+ problemName=DirectMissingMethodProblem
+ },
+ {
+ matchName="scala.collection.mutable.ArrayOps$ofBoolean"
+ problemName=MissingTypesProblem
+ },
+ {
+ matchName="scala.collection.mutable.ArrayOps#ofBoolean.sliceImpl"
+ problemName=DirectMissingMethodProblem
+ },
+ {
+ matchName="scala.collection.mutable.ArrayOps#ofBoolean.emptyImpl"
+ problemName=DirectMissingMethodProblem
+ },
+ {
+ matchName="scala.collection.mutable.ArrayOps#ofShort.sliceImpl$extension"
+ problemName=DirectMissingMethodProblem
+ },
+ {
+ matchName="scala.collection.mutable.ArrayOps#ofShort.emptyImpl$extension"
+ problemName=DirectMissingMethodProblem
+ },
+ {
+ matchName="scala.collection.mutable.WrappedArray#ofShort.sliceImpl"
+ problemName=DirectMissingMethodProblem
+ },
+ {
+ matchName="scala.collection.mutable.WrappedArray#ofShort.emptyImpl"
+ problemName=DirectMissingMethodProblem
+ },
+ {
+ matchName="scala.collection.mutable.WrappedArray#ofRef.sliceImpl"
+ problemName=DirectMissingMethodProblem
+ },
+ {
+ matchName="scala.collection.mutable.WrappedArray#ofRef.emptyImpl"
+ problemName=DirectMissingMethodProblem
+ },
+ {
+ matchName="scala.collection.mutable.WrappedArray#ofUnit.sliceImpl"
+ problemName=DirectMissingMethodProblem
+ },
+ {
+ matchName="scala.collection.mutable.WrappedArray#ofUnit.emptyImpl"
+ problemName=DirectMissingMethodProblem
+ },
+ {
+ matchName="scala.collection.mutable.ArrayOps#ofByte.sliceImpl$extension"
+ problemName=DirectMissingMethodProblem
+ },
+ {
+ matchName="scala.collection.mutable.ArrayOps#ofByte.emptyImpl$extension"
+ problemName=DirectMissingMethodProblem
+ },
+ {
+ matchName="scala.collection.mutable.ArrayOps#ofDouble.sliceImpl$extension"
+ problemName=DirectMissingMethodProblem
+ },
+ {
+ matchName="scala.collection.mutable.ArrayOps#ofDouble.emptyImpl$extension"
+ problemName=DirectMissingMethodProblem
+ },
+ {
+ matchName="scala.collection.mutable.ArrayOpsImpl"
+ problemName=MissingClassProblem
+ },
+ {
+ matchName="scala.collection.mutable.WrappedArray#ofInt.sliceImpl"
+ problemName=DirectMissingMethodProblem
+ },
+ {
+ matchName="scala.collection.mutable.WrappedArray#ofInt.emptyImpl"
+ problemName=DirectMissingMethodProblem
+ },
+ {
+ matchName="scala.collection.mutable.ArrayOps$ofDouble"
+ problemName=MissingTypesProblem
+ },
+ {
+ matchName="scala.collection.mutable.ArrayOps#ofDouble.sliceImpl"
+ problemName=DirectMissingMethodProblem
+ },
+ {
+ matchName="scala.collection.mutable.ArrayOps#ofDouble.emptyImpl"
+ problemName=DirectMissingMethodProblem
+ },
+ {
+ matchName="scala.collection.mutable.ArrayOps$ofRef"
+ problemName=MissingTypesProblem
+ },
+ {
+ matchName="scala.collection.mutable.ArrayOps#ofRef.sliceImpl"
+ problemName=DirectMissingMethodProblem
+ },
+ {
+ matchName="scala.collection.mutable.ArrayOps#ofRef.emptyImpl"
+ problemName=DirectMissingMethodProblem
+ },
+ {
+ matchName="scala.collection.mutable.WrappedArray#ofLong.sliceImpl"
+ problemName=DirectMissingMethodProblem
+ },
+ {
+ matchName="scala.collection.mutable.WrappedArray#ofLong.emptyImpl"
+ problemName=DirectMissingMethodProblem
+ },
+ {
+ matchName="scala.collection.mutable.ArrayOps$ofByte"
+ problemName=MissingTypesProblem
+ },
+ {
+ matchName="scala.collection.mutable.ArrayOps#ofByte.sliceImpl"
+ problemName=DirectMissingMethodProblem
+ },
+ {
+ matchName="scala.collection.mutable.ArrayOps#ofByte.emptyImpl"
+ problemName=DirectMissingMethodProblem
+ },
+ {
+ matchName="scala.collection.mutable.ArrayOps#ofFloat.sliceImpl$extension"
+ problemName=DirectMissingMethodProblem
+ },
+ {
+ matchName="scala.collection.mutable.ArrayOps#ofFloat.emptyImpl$extension"
+ problemName=DirectMissingMethodProblem
+ },
+ {
+ matchName="scala.collection.mutable.ArrayOps#ofLong.sliceImpl$extension"
+ problemName=DirectMissingMethodProblem
+ },
+ {
+ matchName="scala.collection.mutable.ArrayOps#ofLong.emptyImpl$extension"
+ problemName=DirectMissingMethodProblem
+ },
+ {
+ matchName="scala.collection.mutable.ArrayOps#ofBoolean.sliceImpl$extension"
+ problemName=DirectMissingMethodProblem
+ },
+ {
+ matchName="scala.collection.mutable.ArrayOps#ofBoolean.emptyImpl$extension"
+ problemName=DirectMissingMethodProblem
+ },
+ {
+ matchName="scala.collection.mutable.WrappedArray$ofByte"
+ problemName=MissingTypesProblem
+ },
+ {
+ matchName="scala.collection.mutable.WrappedArray$ofBoolean"
+ problemName=MissingTypesProblem
+ },
+ {
+ matchName="scala.collection.mutable.WrappedArray$ofChar"
+ problemName=MissingTypesProblem
+ },
+ {
+ matchName="scala.collection.mutable.WrappedArray$ofDouble"
+ problemName=MissingTypesProblem
+ },
+ {
+ matchName="scala.collection.mutable.WrappedArray$ofShort"
+ problemName=MissingTypesProblem
+ },
+ {
+ matchName="scala.collection.mutable.WrappedArray$ofRef"
+ problemName=MissingTypesProblem
+ },
+ {
+ matchName="scala.collection.mutable.WrappedArray$ofUnit"
+ problemName=MissingTypesProblem
+ },
+ {
+ matchName="scala.collection.mutable.WrappedArray$ofInt"
+ problemName=MissingTypesProblem
+ },
+ {
+ matchName="scala.collection.mutable.WrappedArrayImpl"
+ problemName=MissingClassProblem
+ },
+ {
+ matchName="scala.collection.mutable.WrappedArray$ofLong"
+ problemName=MissingTypesProblem
+ },
+ {
+ matchName="scala.collection.mutable.WrappedArray$ofFloat"
+ problemName=MissingTypesProblem
+ },
+ {
+ matchName="scala.collection.mutable.WrappedArray#ofFloat.sliceImpl"
+ problemName=DirectMissingMethodProblem
+ },
+ {
+ matchName="scala.collection.mutable.WrappedArray#ofFloat.emptyImpl"
+ problemName=DirectMissingMethodProblem
+ },
+ {
+ matchName="scala.collection.mutable.ArrayOps$ofLong"
+ problemName=MissingTypesProblem
+ },
+ {
+ matchName="scala.collection.mutable.ArrayOps#ofLong.sliceImpl"
+ problemName=DirectMissingMethodProblem
+ },
+ {
+ matchName="scala.collection.mutable.ArrayOps#ofLong.emptyImpl"
+ problemName=DirectMissingMethodProblem
+ },
+ {
+ matchName="scala.collection.mutable.ArrayOps$ofFloat"
+ problemName=MissingTypesProblem
+ },
+ {
+ matchName="scala.collection.mutable.ArrayOps#ofFloat.sliceImpl"
+ problemName=DirectMissingMethodProblem
+ },
+ {
+ matchName="scala.collection.mutable.ArrayOps#ofFloat.emptyImpl"
+ problemName=DirectMissingMethodProblem
+ },
+ // introduce FilteredTraversableInternal
+ {
+ matchName="scala.collection.immutable.Nil$"
+ problemName=MissingTypesProblem
+ },
+ {
+ matchName="scala.collection.immutable.FilteredTraversableInternal"
+ problemName=MissingClassProblem
+ },
+ {
+ matchName="scala.collection.immutable.List"
+ problemName=MissingTypesProblem
+ },
+ {
+ matchName="scala.collection.immutable.$colon$colon"
+ problemName=MissingTypesProblem
}
]
}
diff --git a/src/compiler/scala/tools/nsc/transform/Erasure.scala b/src/compiler/scala/tools/nsc/transform/Erasure.scala
index 3ce7db35d8..e327a6658c 100644
--- a/src/compiler/scala/tools/nsc/transform/Erasure.scala
+++ b/src/compiler/scala/tools/nsc/transform/Erasure.scala
@@ -456,7 +456,15 @@ abstract class Erasure extends InfoTransform
override def newTyper(context: Context) = new Eraser(context)
class ComputeBridges(unit: CompilationUnit, root: Symbol) {
- assert(phase == currentRun.erasurePhase, phase)
+
+ class BridgesCursor(root: Symbol) extends overridingPairs.Cursor(root) {
+ override def parents = List(root.info.firstParent)
+ // Varargs bridges may need generic bridges due to the non-repeated part of the signature of the involved methods.
+ // The vararg bridge is generated during refchecks (probably to simplify override checking),
+ // but then the resulting varargs "bridge" method may itself need an actual erasure bridge.
+ // TODO: like javac, generate just one bridge method that wraps Seq <-> varargs and does erasure-induced casts
+ override def exclude(sym: Symbol) = !sym.isMethod || super.exclude(sym)
+ }
var toBeRemoved = immutable.Set[Symbol]()
val site = root.thisType
@@ -464,12 +472,7 @@ abstract class Erasure extends InfoTransform
val bridgeTarget = mutable.HashMap[Symbol, Symbol]()
var bridges = List[Tree]()
- val opc = enteringExplicitOuter {
- new overridingPairs.Cursor(root) {
- override def parents = List(root.info.firstParent)
- override def exclude(sym: Symbol) = !sym.isMethod || super.exclude(sym)
- }
- }
+ val opc = enteringExplicitOuter { new BridgesCursor(root) }
def compute(): (List[Tree], immutable.Set[Symbol]) = {
while (opc.hasNext) {
@@ -860,6 +863,16 @@ abstract class Erasure extends InfoTransform
}
}
+ private class DoubleDefsCursor(root: Symbol) extends Cursor(root) {
+ // specialized members have no type history before 'specialize', causing double def errors for curried defs
+ override def exclude(sym: Symbol): Boolean = (
+ sym.isType
+ || super.exclude(sym)
+ || !sym.hasTypeAt(currentRun.refchecksPhase.id)
+ )
+ override def matches(lo: Symbol, high: Symbol) = !high.isPrivate
+ }
+
/** Emit an error if there is a double definition. This can happen if:
*
* - A template defines two members with the same name and erased type.
@@ -870,21 +883,12 @@ abstract class Erasure extends InfoTransform
*/
private def checkNoDoubleDefs(root: Symbol) {
checkNoDeclaredDoubleDefs(root)
- object opc extends Cursor(root) {
- // specialized members have no type history before 'specialize', causing double def errors for curried defs
- override def exclude(sym: Symbol): Boolean = (
- sym.isType
- || super.exclude(sym)
- || !sym.hasTypeAt(currentRun.refchecksPhase.id)
- )
- override def matches(lo: Symbol, high: Symbol) = !high.isPrivate
- }
def isErasureDoubleDef(pair: SymbolPair) = {
import pair._
log(s"Considering for erasure clash:\n$pair")
!exitingRefchecks(lowType matches highType) && sameTypeAfterErasure(low, high)
}
- opc.iterator filter isErasureDoubleDef foreach doubleDefError
+ (new DoubleDefsCursor(root)).iterator filter isErasureDoubleDef foreach doubleDefError
}
/** Add bridge definitions to a template. This means:
diff --git a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala
index 45dfb427f0..27e214af97 100644
--- a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala
@@ -189,7 +189,7 @@ abstract class RefChecks extends Transform {
def varargBridge(member: Symbol, bridgetpe: Type): Tree = {
log(s"Generating varargs bridge for ${member.fullLocationString} of type $bridgetpe")
- val newFlags = (member.flags | VBRIDGE | ARTIFACT) & ~PRIVATE
+ val newFlags = (member.flags | VBRIDGE) & ~PRIVATE
val bridge = member.cloneSymbolImpl(clazz, newFlags) setPos clazz.pos
bridge.setInfo(bridgetpe.cloneInfo(bridge))
clazz.info.decls enter bridge
diff --git a/src/library/scala/collection/immutable/FilteredTraversableInternal.scala b/src/library/scala/collection/immutable/FilteredTraversableInternal.scala
new file mode 100644
index 0000000000..35585b7826
--- /dev/null
+++ b/src/library/scala/collection/immutable/FilteredTraversableInternal.scala
@@ -0,0 +1,104 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2013, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+package scala
+package collection
+package immutable
+
+import scala.annotation.tailrec
+
+/**
+ * Optimised filter functions for List
+ * n.b. this is an internal class to help maintain compatibility and should not be used directly.
+ */
+private[immutable] trait FilteredTraversableInternal[+A, +Repr <: AnyRef with TraversableLike[A, Repr]] extends TraversableLike[A, Repr] {
+
+ // Optimized for List
+
+ override def filter(p: A => Boolean): Self = filterImpl(p, isFlipped = false)
+
+ override def filterNot(p: A => Boolean): Self = filterImpl(p, isFlipped = true)
+
+ private[this] def filterImpl(p: A => Boolean, isFlipped: Boolean): Self = {
+
+ // everything seen so far so far is not included
+ @tailrec def noneIn(l: Repr): Repr = {
+ if (l.isEmpty)
+ Nil.asInstanceOf[Repr]
+ else {
+ val h = l.head
+ val t = l.tail
+ if (p(h) != isFlipped)
+ allIn(l, t)
+ else
+ noneIn(t)
+ }
+ }
+
+ // everything from 'start' is included, if everything from this point is in we can return the origin
+ // start otherwise if we discover an element that is out we must create a new partial list.
+ @tailrec def allIn(start: Repr, remaining: Repr): Repr = {
+ if (remaining.isEmpty)
+ start
+ else {
+ val x = remaining.head
+ if (p(x) != isFlipped)
+ allIn(start, remaining.tail)
+ else
+ partialFill(start, remaining)
+ }
+ }
+
+ // we have seen elements that should be included then one that should be excluded, start building
+ def partialFill(origStart: Repr, firstMiss: Repr): Repr = {
+ val newHead = new ::(origStart.head, Nil)
+ var toProcess = origStart.tail
+ var currentLast = newHead
+
+ // we know that all elements are :: until at least firstMiss.tail
+ while (!(toProcess eq firstMiss)) {
+ val newElem = new ::(toProcess.head, Nil)
+ currentLast.tl = newElem
+ currentLast = newElem
+ toProcess = toProcess.tail
+ }
+
+ // at this point newHead points to a list which is a duplicate of all the 'in' elements up to the first miss.
+ // currentLast is the last element in that list.
+
+ // now we are going to try and share as much of the tail as we can, only moving elements across when we have to.
+ var next = firstMiss.tail
+ var nextToCopy = next // the next element we would need to copy to our list if we cant share.
+ while (!next.isEmpty) {
+ // generally recommended is next.isNonEmpty but this incurs an extra method call.
+ val head: A = next.head
+ if (p(head) != isFlipped) {
+ next = next.tail
+ } else {
+ // its not a match - do we have outstanding elements?
+ while (!(nextToCopy eq next)) {
+ val newElem = new ::(nextToCopy.head, Nil)
+ currentLast.tl = newElem
+ currentLast = newElem
+ nextToCopy = nextToCopy.tail
+ }
+ nextToCopy = next.tail
+ next = next.tail
+ }
+ }
+
+ // we have remaining elements - they are unchanged attach them to the end
+ if (!nextToCopy.isEmpty)
+ currentLast.tl = nextToCopy.asInstanceOf[List[A]]
+
+ newHead.asInstanceOf[Repr]
+ }
+
+ noneIn(repr)
+ }
+} \ No newline at end of file
diff --git a/src/library/scala/collection/immutable/List.scala b/src/library/scala/collection/immutable/List.scala
index e5444533a8..e12ce7c2eb 100644
--- a/src/library/scala/collection/immutable/List.scala
+++ b/src/library/scala/collection/immutable/List.scala
@@ -88,6 +88,7 @@ sealed abstract class List[+A] extends AbstractSeq[A]
with Product
with GenericTraversableTemplate[A, List]
with LinearSeqOptimized[A, List[A]]
+ with FilteredTraversableInternal[A, List[A]]
with scala.Serializable {
override def companion: GenericCompanion[List] = List
@@ -163,30 +164,41 @@ sealed abstract class List[+A] extends AbstractSeq[A]
// Note to developers: there exists a duplication between this function and `reflect.internal.util.Collections#map2Conserve`.
// If any successful optimization attempts or other changes are made, please rehash them there too.
@tailrec
- def loop(mapped: ListBuffer[B], unchanged: List[A], pending: List[A]): List[B] =
- if (pending.isEmpty) {
- if (mapped eq null) unchanged
- else mapped.prependToList(unchanged)
+ def loop(mappedHead: List[B] = Nil, mappedLast: ::[B], unchanged: List[A], pending: List[A]): List[B] =
+ if (pending.isEmpty) {
+ if (mappedHead eq null) unchanged
+ else {
+ mappedLast.tl = unchanged
+ mappedHead
}
+ }
+ else {
+ val head0 = pending.head
+ val head1 = f(head0)
+
+ if (head1 eq head0.asInstanceOf[AnyRef])
+ loop(mappedHead, mappedLast, unchanged, pending.tail)
else {
- val head0 = pending.head
- val head1 = f(head0)
-
- if (head1 eq head0.asInstanceOf[AnyRef])
- loop(mapped, unchanged, pending.tail)
- else {
- val b = if (mapped eq null) new ListBuffer[B] else mapped
- var xc = unchanged
- while (xc ne pending) {
- b += xc.head
- xc = xc.tail
- }
- b += head1
- val tail0 = pending.tail
- loop(b, tail0, tail0)
+ var xc = unchanged
+ var mappedHead1: List[B] = mappedHead
+ var mappedLast1: ::[B] = mappedLast
+ while (xc ne pending) {
+ val next = new ::[B](xc.head, Nil)
+ if (mappedHead1 eq null) mappedHead1 = next
+ if (mappedLast1 ne null) mappedLast1.tl = next
+ mappedLast1 = next
+ xc = xc.tail
}
+ val next = new ::(head1, Nil)
+ if (mappedHead1 eq null) mappedHead1 = next
+ if (mappedLast1 ne null) mappedLast1.tl = next
+ mappedLast1 = next
+ val tail0 = pending.tail
+ loop(mappedHead1, mappedLast1, tail0, tail0)
+
}
- loop(null, this, this)
+ }
+ loop(null, null, this, this)
}
// Overridden methods from IterableLike and SeqLike or overloaded variants of such methods
@@ -402,6 +414,7 @@ sealed abstract class List[+A] extends AbstractSeq[A]
// Create a proxy for Java serialization that allows us to avoid mutation
// during deserialization. This is the Serialization Proxy Pattern.
protected final def writeReplace(): AnyRef = new List.SerializationProxy(this)
+
}
/** The empty list.
diff --git a/src/library/scala/collection/immutable/RedBlackTree.scala b/src/library/scala/collection/immutable/RedBlackTree.scala
index afb4c9c552..4f2e9115fe 100644
--- a/src/library/scala/collection/immutable/RedBlackTree.scala
+++ b/src/library/scala/collection/immutable/RedBlackTree.scala
@@ -516,9 +516,10 @@ object RedBlackTree {
*
* According to {@see Integer#numberOfLeadingZeros} ceil(log_2(n)) = (32 - Integer.numberOfLeadingZeros(n - 1))
*
- * We also don't store the deepest nodes in the path so the maximum path length is further reduced by one.
+ * Although we don't store the deepest nodes in the path during iteration,
+ * we potentially do so in `startFrom`.
*/
- val maximumHeight = 2 * (32 - Integer.numberOfLeadingZeros(root.count + 2 - 1)) - 2 - 1
+ val maximumHeight = 2 * (32 - Integer.numberOfLeadingZeros(root.count + 2 - 1)) - 2
new Array[Tree[A, B]](maximumHeight)
}
private[this] var index = 0
diff --git a/src/library/scala/collection/mutable/ArrayOps.scala b/src/library/scala/collection/mutable/ArrayOps.scala
index 29382134aa..5de3dad256 100644
--- a/src/library/scala/collection/mutable/ArrayOps.scala
+++ b/src/library/scala/collection/mutable/ArrayOps.scala
@@ -10,6 +10,8 @@ package scala
package collection
package mutable
+import java.util
+
import scala.reflect.ClassTag
import parallel.mutable.ParArray
@@ -180,6 +182,23 @@ sealed trait ArrayOps[T] extends Any with ArrayLike[T, Array[T]] with CustomPara
def seq = thisCollection
}
+/** to provide binary compat for 2.11 and 2.12 this class contains
+ * functionality that should be migrated to ArrayOps in 2.13
+ *
+ */
+private[mutable] sealed trait ArrayOpsImpl[T] extends Any with ArrayOps[T] {
+ override final def slice(from: Int, until: Int): Array[T] = {
+ val start = if (from < 0) 0 else from
+ if (until <= start || start >= repr.length)
+ return emptyImpl
+ val end = if (until > length) length else until
+ sliceImpl(start, end)
+ }
+ protected def emptyImpl: Array[T]
+ protected def sliceImpl(from: Int, until: Int): Array[T]
+
+}
+
/**
* A companion object for `ArrayOps`.
*
@@ -187,12 +206,24 @@ sealed trait ArrayOps[T] extends Any with ArrayLike[T, Array[T]] with CustomPara
*/
object ArrayOps {
+ private val emptyByteArray = new Array[Byte](0)
+ private val emptyShortArray = new Array[Short](0)
+ private val emptyIntArray = new Array[Int](0)
+ private val emptyLongArray = new Array[Long](0)
+ private val emptyFloatArray = new Array[Float](0)
+ private val emptyDoubleArray = new Array[Double](0)
+ private val emptyUnitArray = new Array[Unit](0)
+ private val emptyCharArray = new Array[Char](0)
+ private val emptyBooleanArray = new Array[Boolean](0)
+
/** A subclass of `ArrayOps` for arrays containing reference types. */
- final class ofRef[T <: AnyRef](override val repr: Array[T]) extends AnyVal with ArrayOps[T] with ArrayLike[T, Array[T]] {
+ final class ofRef[T <: AnyRef](override val repr: Array[T]) extends AnyVal with ArrayOpsImpl[T] with ArrayLike[T, Array[T]] {
override protected[this] def thisCollection: WrappedArray[T] = new WrappedArray.ofRef[T](repr)
override protected[this] def toCollection(repr: Array[T]): WrappedArray[T] = new WrappedArray.ofRef[T](repr)
override protected[this] def newBuilder = new ArrayBuilder.ofRef[T]()(ClassTag[T](repr.getClass.getComponentType))
+ protected override def emptyImpl:Array[T] = util.Arrays.copyOf[T](repr,0)
+ protected override def sliceImpl(from: Int, until: Int): Array[T] = util.Arrays.copyOfRange[T](repr, from, until)
def length: Int = repr.length
def apply(index: Int): T = repr(index)
@@ -200,11 +231,13 @@ object ArrayOps {
}
/** A subclass of `ArrayOps` for arrays containing `Byte`s. */
- final class ofByte(override val repr: Array[Byte]) extends AnyVal with ArrayOps[Byte] with ArrayLike[Byte, Array[Byte]] {
+ final class ofByte(override val repr: Array[Byte]) extends AnyVal with ArrayOpsImpl[Byte] with ArrayLike[Byte, Array[Byte]] {
override protected[this] def thisCollection: WrappedArray[Byte] = new WrappedArray.ofByte(repr)
override protected[this] def toCollection(repr: Array[Byte]): WrappedArray[Byte] = new WrappedArray.ofByte(repr)
override protected[this] def newBuilder = new ArrayBuilder.ofByte
+ protected override def emptyImpl = emptyByteArray
+ protected override def sliceImpl(from: Int, until: Int) = util.Arrays.copyOfRange(repr, from, until)
def length: Int = repr.length
def apply(index: Int): Byte = repr(index)
@@ -212,11 +245,13 @@ object ArrayOps {
}
/** A subclass of `ArrayOps` for arrays containing `Short`s. */
- final class ofShort(override val repr: Array[Short]) extends AnyVal with ArrayOps[Short] with ArrayLike[Short, Array[Short]] {
+ final class ofShort(override val repr: Array[Short]) extends AnyVal with ArrayOpsImpl[Short] with ArrayLike[Short, Array[Short]] {
override protected[this] def thisCollection: WrappedArray[Short] = new WrappedArray.ofShort(repr)
override protected[this] def toCollection(repr: Array[Short]): WrappedArray[Short] = new WrappedArray.ofShort(repr)
override protected[this] def newBuilder = new ArrayBuilder.ofShort
+ protected override def emptyImpl = emptyShortArray
+ protected override def sliceImpl(from: Int, until: Int) = util.Arrays.copyOfRange(repr, from, until)
def length: Int = repr.length
def apply(index: Int): Short = repr(index)
@@ -224,11 +259,13 @@ object ArrayOps {
}
/** A subclass of `ArrayOps` for arrays containing `Char`s. */
- final class ofChar(override val repr: Array[Char]) extends AnyVal with ArrayOps[Char] with ArrayLike[Char, Array[Char]] {
+ final class ofChar(override val repr: Array[Char]) extends AnyVal with ArrayOpsImpl[Char] with ArrayLike[Char, Array[Char]] {
override protected[this] def thisCollection: WrappedArray[Char] = new WrappedArray.ofChar(repr)
override protected[this] def toCollection(repr: Array[Char]): WrappedArray[Char] = new WrappedArray.ofChar(repr)
override protected[this] def newBuilder = new ArrayBuilder.ofChar
+ protected override def emptyImpl = emptyCharArray
+ protected override def sliceImpl(from: Int, until: Int) = util.Arrays.copyOfRange(repr, from, until)
def length: Int = repr.length
def apply(index: Int): Char = repr(index)
@@ -236,11 +273,13 @@ object ArrayOps {
}
/** A subclass of `ArrayOps` for arrays containing `Int`s. */
- final class ofInt(override val repr: Array[Int]) extends AnyVal with ArrayOps[Int] with ArrayLike[Int, Array[Int]] {
+ final class ofInt(override val repr: Array[Int]) extends AnyVal with ArrayOpsImpl[Int] with ArrayLike[Int, Array[Int]] {
override protected[this] def thisCollection: WrappedArray[Int] = new WrappedArray.ofInt(repr)
override protected[this] def toCollection(repr: Array[Int]): WrappedArray[Int] = new WrappedArray.ofInt(repr)
override protected[this] def newBuilder = new ArrayBuilder.ofInt
+ protected override def emptyImpl = emptyIntArray
+ protected override def sliceImpl(from: Int, until: Int) = util.Arrays.copyOfRange(repr, from, until)
def length: Int = repr.length
def apply(index: Int): Int = repr(index)
@@ -248,11 +287,13 @@ object ArrayOps {
}
/** A subclass of `ArrayOps` for arrays containing `Long`s. */
- final class ofLong(override val repr: Array[Long]) extends AnyVal with ArrayOps[Long] with ArrayLike[Long, Array[Long]] {
+ final class ofLong(override val repr: Array[Long]) extends AnyVal with ArrayOpsImpl[Long] with ArrayLike[Long, Array[Long]] {
override protected[this] def thisCollection: WrappedArray[Long] = new WrappedArray.ofLong(repr)
override protected[this] def toCollection(repr: Array[Long]): WrappedArray[Long] = new WrappedArray.ofLong(repr)
override protected[this] def newBuilder = new ArrayBuilder.ofLong
+ protected override def emptyImpl = emptyLongArray
+ protected override def sliceImpl(from: Int, until: Int) = util.Arrays.copyOfRange(repr, from, until)
def length: Int = repr.length
def apply(index: Int): Long = repr(index)
@@ -260,11 +301,13 @@ object ArrayOps {
}
/** A subclass of `ArrayOps` for arrays containing `Float`s. */
- final class ofFloat(override val repr: Array[Float]) extends AnyVal with ArrayOps[Float] with ArrayLike[Float, Array[Float]] {
+ final class ofFloat(override val repr: Array[Float]) extends AnyVal with ArrayOpsImpl[Float] with ArrayLike[Float, Array[Float]] {
override protected[this] def thisCollection: WrappedArray[Float] = new WrappedArray.ofFloat(repr)
override protected[this] def toCollection(repr: Array[Float]): WrappedArray[Float] = new WrappedArray.ofFloat(repr)
override protected[this] def newBuilder = new ArrayBuilder.ofFloat
+ protected override def emptyImpl = emptyFloatArray
+ protected override def sliceImpl(from: Int, until: Int) = util.Arrays.copyOfRange(repr, from, until)
def length: Int = repr.length
def apply(index: Int): Float = repr(index)
@@ -272,11 +315,13 @@ object ArrayOps {
}
/** A subclass of `ArrayOps` for arrays containing `Double`s. */
- final class ofDouble(override val repr: Array[Double]) extends AnyVal with ArrayOps[Double] with ArrayLike[Double, Array[Double]] {
+ final class ofDouble(override val repr: Array[Double]) extends AnyVal with ArrayOpsImpl[Double] with ArrayLike[Double, Array[Double]] {
override protected[this] def thisCollection: WrappedArray[Double] = new WrappedArray.ofDouble(repr)
override protected[this] def toCollection(repr: Array[Double]): WrappedArray[Double] = new WrappedArray.ofDouble(repr)
override protected[this] def newBuilder = new ArrayBuilder.ofDouble
+ protected override def emptyImpl = emptyDoubleArray
+ protected override def sliceImpl(from: Int, until: Int) = util.Arrays.copyOfRange(repr, from, until)
def length: Int = repr.length
def apply(index: Int): Double = repr(index)
@@ -284,11 +329,13 @@ object ArrayOps {
}
/** A subclass of `ArrayOps` for arrays containing `Boolean`s. */
- final class ofBoolean(override val repr: Array[Boolean]) extends AnyVal with ArrayOps[Boolean] with ArrayLike[Boolean, Array[Boolean]] {
+ final class ofBoolean(override val repr: Array[Boolean]) extends AnyVal with ArrayOpsImpl[Boolean] with ArrayLike[Boolean, Array[Boolean]] {
override protected[this] def thisCollection: WrappedArray[Boolean] = new WrappedArray.ofBoolean(repr)
override protected[this] def toCollection(repr: Array[Boolean]): WrappedArray[Boolean] = new WrappedArray.ofBoolean(repr)
override protected[this] def newBuilder = new ArrayBuilder.ofBoolean
+ protected override def emptyImpl = emptyBooleanArray
+ protected override def sliceImpl(from: Int, until: Int) = util.Arrays.copyOfRange(repr, from, until)
def length: Int = repr.length
def apply(index: Int): Boolean = repr(index)
@@ -296,11 +343,18 @@ object ArrayOps {
}
/** A subclass of `ArrayOps` for arrays of `Unit` types. */
- final class ofUnit(override val repr: Array[Unit]) extends AnyVal with ArrayOps[Unit] with ArrayLike[Unit, Array[Unit]] {
+ final class ofUnit(override val repr: Array[Unit]) extends AnyVal with ArrayOpsImpl[Unit] with ArrayLike[Unit, Array[Unit]] {
override protected[this] def thisCollection: WrappedArray[Unit] = new WrappedArray.ofUnit(repr)
override protected[this] def toCollection(repr: Array[Unit]): WrappedArray[Unit] = new WrappedArray.ofUnit(repr)
override protected[this] def newBuilder = new ArrayBuilder.ofUnit
+ protected override def emptyImpl = emptyUnitArray
+ protected override def sliceImpl(from: Int, until: Int) = {
+ // cant use util.Arrays.copyOfRange[Unit](repr, from, until) - Unit is special and doesnt compile
+ val res = new Array[Unit](until-from)
+ System.arraycopy(repr, from, res, 0, res.size)
+ res
+ }
def length: Int = repr.length
def apply(index: Int): Unit = repr(index)
diff --git a/src/library/scala/collection/mutable/WrappedArray.scala b/src/library/scala/collection/mutable/WrappedArray.scala
index 0b5ebe7e9a..d0919c4357 100644
--- a/src/library/scala/collection/mutable/WrappedArray.scala
+++ b/src/library/scala/collection/mutable/WrappedArray.scala
@@ -85,12 +85,26 @@ extends AbstractSeq[T]
*/
override protected[this] def newBuilder: Builder[T, WrappedArray[T]] =
new WrappedArrayBuilder[T](elemTag)
+}
+
+private[mutable] abstract class WrappedArrayImpl[T] extends WrappedArray[T] {
+ override def slice(from: Int, until: Int): WrappedArray[T] = {
+ val start = if (from < 0) 0 else from
+ if (until <= start || start >= repr.length)
+ return emptyImpl
+ val end = if (until > length) length else until
+ sliceImpl(start, end)
+ }
+ protected def emptyImpl: WrappedArray[T]
+
+ protected def sliceImpl(from: Int, until: Int): WrappedArray[T]
}
/** A companion object used to create instances of `WrappedArray`.
*/
object WrappedArray {
+ import java.util
// This is reused for all calls to empty.
private val EmptyWrappedArray = new ofRef[AnyRef](new Array[AnyRef](0))
def empty[T <: AnyRef]: WrappedArray[T] = EmptyWrappedArray.asInstanceOf[WrappedArray[T]]
@@ -124,7 +138,17 @@ object WrappedArray {
def newBuilder[A]: Builder[A, IndexedSeq[A]] = new ArrayBuffer
- final class ofRef[T <: AnyRef](val array: Array[T]) extends WrappedArray[T] with Serializable {
+ private val emptyWrappedByte = new ofByte(new Array[Byte](0))
+ private val emptyWrappedShort = new ofShort(new Array[Short](0))
+ private val emptyWrappedInt = new ofInt(new Array[Int](0))
+ private val emptyWrappedLong = new ofLong(new Array[Long](0))
+ private val emptyWrappedFloat = new ofFloat(new Array[Float](0))
+ private val emptyWrappedDouble = new ofDouble(new Array[Double](0))
+ private val emptyWrappedUnit = new ofUnit(new Array[Unit](0))
+ private val emptyWrappedChar = new ofChar(new Array[Char](0))
+ private val emptyWrappedBoolean = new ofBoolean(new Array[Boolean](0))
+
+ final class ofRef[T <: AnyRef](val array: Array[T]) extends WrappedArrayImpl[T] with Serializable {
lazy val elemTag = ClassTag[T](array.getClass.getComponentType)
def length: Int = array.length
def apply(index: Int): T = array(index).asInstanceOf[T]
@@ -134,9 +158,11 @@ object WrappedArray {
case that: ofRef[_] => Arrays.equals(array.asInstanceOf[Array[AnyRef]], that.array.asInstanceOf[Array[AnyRef]])
case _ => super.equals(that)
}
+ protected override def emptyImpl = new ofRef(util.Arrays.copyOf[T](array,0))
+ protected override def sliceImpl(from: Int, until: Int) = new ofRef[T](util.Arrays.copyOfRange[T](array, from, until))
}
- final class ofByte(val array: Array[Byte]) extends WrappedArray[Byte] with Serializable {
+ final class ofByte(val array: Array[Byte]) extends WrappedArrayImpl[Byte] with Serializable {
def elemTag = ClassTag.Byte
def length: Int = array.length
def apply(index: Int): Byte = array(index)
@@ -146,9 +172,11 @@ object WrappedArray {
case that: ofByte => Arrays.equals(array, that.array)
case _ => super.equals(that)
}
+ protected override def emptyImpl = emptyWrappedByte
+ protected override def sliceImpl(from: Int, until: Int) = new ofByte(util.Arrays.copyOfRange(array, from, until))
}
- final class ofShort(val array: Array[Short]) extends WrappedArray[Short] with Serializable {
+ final class ofShort(val array: Array[Short]) extends WrappedArrayImpl[Short] with Serializable {
def elemTag = ClassTag.Short
def length: Int = array.length
def apply(index: Int): Short = array(index)
@@ -158,9 +186,11 @@ object WrappedArray {
case that: ofShort => Arrays.equals(array, that.array)
case _ => super.equals(that)
}
+ protected override def emptyImpl = emptyWrappedShort
+ protected override def sliceImpl(from: Int, until: Int) = new ofShort(util.Arrays.copyOfRange(array, from, until))
}
- final class ofChar(val array: Array[Char]) extends WrappedArray[Char] with Serializable {
+ final class ofChar(val array: Array[Char]) extends WrappedArrayImpl[Char] with Serializable {
def elemTag = ClassTag.Char
def length: Int = array.length
def apply(index: Int): Char = array(index)
@@ -170,9 +200,11 @@ object WrappedArray {
case that: ofChar => Arrays.equals(array, that.array)
case _ => super.equals(that)
}
+ protected override def emptyImpl = emptyWrappedChar
+ protected override def sliceImpl(from: Int, until: Int) = new ofChar(util.Arrays.copyOfRange(array, from, until))
}
- final class ofInt(val array: Array[Int]) extends WrappedArray[Int] with Serializable {
+ final class ofInt(val array: Array[Int]) extends WrappedArrayImpl[Int] with Serializable {
def elemTag = ClassTag.Int
def length: Int = array.length
def apply(index: Int): Int = array(index)
@@ -182,9 +214,11 @@ object WrappedArray {
case that: ofInt => Arrays.equals(array, that.array)
case _ => super.equals(that)
}
+ protected override def emptyImpl = emptyWrappedInt
+ protected override def sliceImpl(from: Int, until: Int) = new ofInt(util.Arrays.copyOfRange(array, from, until))
}
- final class ofLong(val array: Array[Long]) extends WrappedArray[Long] with Serializable {
+ final class ofLong(val array: Array[Long]) extends WrappedArrayImpl[Long] with Serializable {
def elemTag = ClassTag.Long
def length: Int = array.length
def apply(index: Int): Long = array(index)
@@ -194,9 +228,11 @@ object WrappedArray {
case that: ofLong => Arrays.equals(array, that.array)
case _ => super.equals(that)
}
+ protected override def emptyImpl = emptyWrappedLong
+ protected override def sliceImpl(from: Int, until: Int) = new ofLong(util.Arrays.copyOfRange(array, from, until))
}
- final class ofFloat(val array: Array[Float]) extends WrappedArray[Float] with Serializable {
+ final class ofFloat(val array: Array[Float]) extends WrappedArrayImpl[Float] with Serializable {
def elemTag = ClassTag.Float
def length: Int = array.length
def apply(index: Int): Float = array(index)
@@ -206,9 +242,11 @@ object WrappedArray {
case that: ofFloat => Arrays.equals(array, that.array)
case _ => super.equals(that)
}
+ protected override def emptyImpl = emptyWrappedFloat
+ protected override def sliceImpl(from: Int, until: Int) = new ofFloat(util.Arrays.copyOfRange(array, from, until))
}
- final class ofDouble(val array: Array[Double]) extends WrappedArray[Double] with Serializable {
+ final class ofDouble(val array: Array[Double]) extends WrappedArrayImpl[Double] with Serializable {
def elemTag = ClassTag.Double
def length: Int = array.length
def apply(index: Int): Double = array(index)
@@ -218,9 +256,11 @@ object WrappedArray {
case that: ofDouble => Arrays.equals(array, that.array)
case _ => super.equals(that)
}
+ protected override def emptyImpl = emptyWrappedDouble
+ protected override def sliceImpl(from: Int, until: Int) = new ofDouble(util.Arrays.copyOfRange(array, from, until))
}
- final class ofBoolean(val array: Array[Boolean]) extends WrappedArray[Boolean] with Serializable {
+ final class ofBoolean(val array: Array[Boolean]) extends WrappedArrayImpl[Boolean] with Serializable {
def elemTag = ClassTag.Boolean
def length: Int = array.length
def apply(index: Int): Boolean = array(index)
@@ -230,9 +270,11 @@ object WrappedArray {
case that: ofBoolean => Arrays.equals(array, that.array)
case _ => super.equals(that)
}
+ protected override def emptyImpl = emptyWrappedBoolean
+ protected override def sliceImpl(from: Int, until: Int) = new ofBoolean(util.Arrays.copyOfRange(array, from, until))
}
- final class ofUnit(val array: Array[Unit]) extends WrappedArray[Unit] with Serializable {
+ final class ofUnit(val array: Array[Unit]) extends WrappedArrayImpl[Unit] with Serializable {
def elemTag = ClassTag.Unit
def length: Int = array.length
def apply(index: Int): Unit = array(index)
@@ -242,5 +284,14 @@ object WrappedArray {
case that: ofUnit => array.length == that.array.length
case _ => super.equals(that)
}
+ protected override def emptyImpl = emptyWrappedUnit
+ protected override def sliceImpl(from: Int, until: Int) = {
+ // cant use
+ // new ofUnit(util.Arrays.copyOfRange[Unit](array, from, until)) - Unit is special and doesnt compile
+ // cant use util.Arrays.copyOfRange[Unit](repr, from, until) - Unit is special and doesnt compile
+ val res = new Array[Unit](until-from)
+ System.arraycopy(repr, from, res, 0, until-from)
+ new ofUnit(res)
+ }
}
}
diff --git a/src/reflect/scala/reflect/internal/Flags.scala b/src/reflect/scala/reflect/internal/Flags.scala
index 8aa6b16e06..d5bf8b7cef 100644
--- a/src/reflect/scala/reflect/internal/Flags.scala
+++ b/src/reflect/scala/reflect/internal/Flags.scala
@@ -163,7 +163,7 @@ class Flags extends ModifierFlags {
final val LOCKED = 1L << 39 // temporary flag to catch cyclic dependencies
final val SPECIALIZED = 1L << 40 // symbol is a generated specialized member
- final val VBRIDGE = 1L << 42 // symbol is a varargs bridge
+ final val VBRIDGE = 1L << 42 // symbol is a varargs bridge (but not a bridge at the bytecode level)
final val VARARGS = 1L << 43 // symbol is a Java-style varargs method
final val TRIEDCOOKING = 1L << 44 // `Cooking` has been tried on this symbol
diff --git a/src/reflect/scala/reflect/runtime/JavaUniverseForce.scala b/src/reflect/scala/reflect/runtime/JavaUniverseForce.scala
index 95d6662d14..f082ba2293 100644
--- a/src/reflect/scala/reflect/runtime/JavaUniverseForce.scala
+++ b/src/reflect/scala/reflect/runtime/JavaUniverseForce.scala
@@ -458,8 +458,8 @@ trait JavaUniverseForce { self: runtime.JavaUniverse =>
definitions.DoubleTpe
definitions.BooleanTpe
definitions.ScalaNumericValueClasses
- definitions.ScalaValueClassesNoUnit
definitions.ScalaValueClasses
+ definitions.ScalaValueClassesNoUnit
uncurry.VarargsSymbolAttachment
uncurry.DesugaredParameterType
diff --git a/test/benchmarks/src/main/scala/scala/collection/immutable/ListBenchmark.scala b/test/benchmarks/src/main/scala/scala/collection/immutable/ListBenchmark.scala
new file mode 100644
index 0000000000..94844dcae2
--- /dev/null
+++ b/test/benchmarks/src/main/scala/scala/collection/immutable/ListBenchmark.scala
@@ -0,0 +1,72 @@
+package scala.collection.immutable
+
+import java.util.concurrent.TimeUnit
+
+import org.openjdk.jmh.annotations._
+
+object ListBenchmark {
+ case class Content(value: Int)
+}
+
+@BenchmarkMode(Array(Mode.AverageTime))
+@Fork(2)
+@Threads(1)
+@Warmup(iterations = 10)
+@Measurement(iterations = 10)
+@OutputTimeUnit(TimeUnit.NANOSECONDS)
+@State(Scope.Benchmark)
+class ListBenchmark {
+ import ListBenchmark._
+ @Param(Array("0", "1", "10", "100", "1000"))
+ var size: Int = _
+
+ var values: List[Content] = _
+ var mid: Content = _
+ var last: Content = _
+
+
+ @Setup(Level.Trial) def initKeys(): Unit = {
+ values = List.tabulate(size)(v => Content(v))
+ mid = Content(size / 2)
+ last = Content(Math.max(0,size -1))
+ }
+
+ @Benchmark def filter_includeAll: Any = {
+ values.filter(v => true)
+ }
+
+ @Benchmark def filter_excludeAll: Any = {
+ values.filter(_ => false)
+ }
+
+ @Benchmark def filter_exc_mid: Any = {
+ values.filter(v => v.value != mid.value)
+ }
+
+ @Benchmark def filter_from_mid: Any = {
+ values.filter(v => v.value <= mid.value)
+ }
+
+ @Benchmark def filter_exc_last: Any = {
+ values.filter(v => v.value != last.value)
+ }
+
+ @Benchmark def filter_only_last: Any = {
+ values.filter(v => v.value == last.value)
+ }
+
+ @Setup(Level.Trial) def initKeys(): Unit = {
+ values = List.tabulate(size)(n => if (n == size / 2) "mid" else "")
+ }
+
+ @Benchmark def mapConserve_identity: Any = {
+ values.mapConserve(x => x)
+ }
+
+ @Benchmark def mapConserve_modifyAll: Any = {
+ values.mapConserve(x => "replace")
+ }
+ @Benchmark def mapConserve_modifyMid: Any = {
+ values.mapConserve(x => if (x == "mid") "replace" else x)
+ }
+}
diff --git a/test/files/run/repl-colon-type.check b/test/files/run/repl-colon-type.check
index 1217e8d8c2..5b7a3c7506 100644
--- a/test/files/run/repl-colon-type.check
+++ b/test/files/run/repl-colon-type.check
@@ -75,7 +75,7 @@ TypeRef(
)
TypeRef(
TypeSymbol(
- sealed abstract class List[+A] extends AbstractSeq[A] with LinearSeq[A] with Product with GenericTraversableTemplate[A,List] with LinearSeqOptimized[A,List[A]] with Serializable
+ sealed abstract class List[+A] extends AbstractSeq[A] with LinearSeq[A] with Product with GenericTraversableTemplate[A,List] with LinearSeqOptimized[A,List[A]] with FilteredTraversableInternal[A,List[A]] with Serializable
)
args = List(
@@ -142,7 +142,7 @@ TypeRef(
args = List(
TypeRef(
TypeSymbol(
- sealed abstract class List[+A] extends AbstractSeq[A] with LinearSeq[A] with Product with GenericTraversableTemplate[A,List] with LinearSeqOptimized[A,List[A]] with Serializable
+ sealed abstract class List[+A] extends AbstractSeq[A] with LinearSeq[A] with Product with GenericTraversableTemplate[A,List] with LinearSeqOptimized[A,List[A]] with FilteredTraversableInternal[A,List[A]] with Serializable
)
args = List(
@@ -175,7 +175,7 @@ PolyType(
args = List(
TypeRef(
TypeSymbol(
- sealed abstract class List[+A] extends AbstractSeq[A] with LinearSeq[A] with Product with GenericTraversableTemplate[A,List] with LinearSeqOptimized[A,List[A]] with Serializable
+ sealed abstract class List[+A] extends AbstractSeq[A] with LinearSeq[A] with Product with GenericTraversableTemplate[A,List] with LinearSeqOptimized[A,List[A]] with FilteredTraversableInternal[A,List[A]] with Serializable
)
args = List(TypeParamTypeRef(TypeParam(T <: AnyVal)))
@@ -198,7 +198,7 @@ PolyType(
params = List(TermSymbol(x: T), TermSymbol(y: List[U]))
resultType = TypeRef(
TypeSymbol(
- sealed abstract class List[+A] extends AbstractSeq[A] with LinearSeq[A] with Product with GenericTraversableTemplate[A,List] with LinearSeqOptimized[A,List[A]] with Serializable
+ sealed abstract class List[+A] extends AbstractSeq[A] with LinearSeq[A] with Product with GenericTraversableTemplate[A,List] with LinearSeqOptimized[A,List[A]] with FilteredTraversableInternal[A,List[A]] with Serializable
)
args = List(TypeParamTypeRef(TypeParam(U >: T)))
diff --git a/test/files/run/t1459.check b/test/files/run/t1459.check
new file mode 100644
index 0000000000..93b4c5a810
--- /dev/null
+++ b/test/files/run/t1459.check
@@ -0,0 +1,3 @@
+JavaPrinter: one two three
+InheritingPrinter extends JavaPrinter: one two three
+ScalaPrinter: onetwothree
diff --git a/test/files/run/t1459/InheritingPrinter.scala b/test/files/run/t1459/InheritingPrinter.scala
new file mode 100644
index 0000000000..70301307f5
--- /dev/null
+++ b/test/files/run/t1459/InheritingPrinter.scala
@@ -0,0 +1,6 @@
+class InheritingPrinter extends JavaPrinter {
+ override def doit(s: String*) {
+ print("InheritingPrinter extends ")
+ super.doit(s: _*);
+ }
+} \ No newline at end of file
diff --git a/test/files/run/t1459/JavaPrinter.java b/test/files/run/t1459/JavaPrinter.java
new file mode 100644
index 0000000000..3912ea613a
--- /dev/null
+++ b/test/files/run/t1459/JavaPrinter.java
@@ -0,0 +1,7 @@
+public class JavaPrinter implements VarArg {
+ public void doit(String... s) {
+ System.out.print("JavaPrinter: ");
+ for(String str : s)
+ System.out.print(str + " ");
+ }
+}
diff --git a/test/files/run/t1459/ScalaPrinter.scala b/test/files/run/t1459/ScalaPrinter.scala
new file mode 100644
index 0000000000..46305804c2
--- /dev/null
+++ b/test/files/run/t1459/ScalaPrinter.scala
@@ -0,0 +1,6 @@
+class ScalaPrinter extends VarArg {
+ override def doit(s: String*) = {
+ print("ScalaPrinter: ")
+ s.foreach(print _)
+ }
+} \ No newline at end of file
diff --git a/test/files/run/t1459/Test.java b/test/files/run/t1459/Test.java
new file mode 100644
index 0000000000..3cf91e2e8b
--- /dev/null
+++ b/test/files/run/t1459/Test.java
@@ -0,0 +1,15 @@
+public class Test {
+ public static void main(String[] args) {
+ VarArg jp = new JavaPrinter();
+ VarArg ip = new InheritingPrinter();
+ VarArg sp = new ScalaPrinter();
+ doYourThing(jp);
+ doYourThing(ip);
+ doYourThing(sp);
+ }
+
+ public static void doYourThing(VarArg va) {
+ va.doit("one", "two", "three");
+ System.out.println();
+ }
+}
diff --git a/test/files/run/t1459/VarArg.java b/test/files/run/t1459/VarArg.java
new file mode 100644
index 0000000000..7039f99e7b
--- /dev/null
+++ b/test/files/run/t1459/VarArg.java
@@ -0,0 +1,3 @@
+public interface VarArg {
+ void doit(String... s);
+}
diff --git a/test/files/run/t1459generic.check b/test/files/run/t1459generic.check
new file mode 100644
index 0000000000..346fadbc0d
--- /dev/null
+++ b/test/files/run/t1459generic.check
@@ -0,0 +1,4 @@
+Note: t1459generic/Test.java uses unchecked or unsafe operations.
+Note: Recompile with -Xlint:unchecked for details.
+ab
+ab
diff --git a/test/files/run/t1459generic/Impl.scala b/test/files/run/t1459generic/Impl.scala
new file mode 100644
index 0000000000..9234e70456
--- /dev/null
+++ b/test/files/run/t1459generic/Impl.scala
@@ -0,0 +1,4 @@
+class Impl extends VarargGeneric[String] {
+ def genericOne(x: String, arg: String): String = x + arg
+ def genericVar(x: String, args: String*): String = x + args.head
+}
diff --git a/test/files/run/t1459generic/Test.java b/test/files/run/t1459generic/Test.java
new file mode 100644
index 0000000000..a97158796b
--- /dev/null
+++ b/test/files/run/t1459generic/Test.java
@@ -0,0 +1,10 @@
+public class Test {
+ public static void main(String[] args) throws Exception {
+ VarargGeneric vg = new Impl();
+ System.out.println(vg.genericOne("a", "b"));
+ System.out.println(vg.genericVar("a", "b"));
+ // should not result in java.lang.AbstractMethodError: Impl.genericVar(Ljava/lang/Object;[Ljava/lang/String;)Ljava/lang/String;
+ // --> genericVar needs a varargs bridge (scala -> java varargs) and a standard generics bridge
+ // (for comparison, including genericOne, which needs only a generics bridge)
+ }
+}
diff --git a/test/files/run/t1459generic/VarargGeneric.java b/test/files/run/t1459generic/VarargGeneric.java
new file mode 100644
index 0000000000..9b37a0fe3f
--- /dev/null
+++ b/test/files/run/t1459generic/VarargGeneric.java
@@ -0,0 +1,7 @@
+public interface VarargGeneric<T> {
+ String genericOne(T x, String args);
+ // we cannot annotate this with @SafeVarargs, because
+ // it's in an interface. so that's why a warning from
+ // javac appears in the checkfile.
+ String genericVar(T x, String... args);
+}
diff --git a/test/files/run/t9013/Test.java b/test/files/run/t9013/Test.java
new file mode 100644
index 0000000000..14152b16ac
--- /dev/null
+++ b/test/files/run/t9013/Test.java
@@ -0,0 +1,20 @@
+import java.util.Comparator;
+
+public class Test {
+ public static void main(String[] args) {
+ ClassImplementsClass c = new ClassImplementsClass();
+
+ c.x("a", "b", "c");
+ c.y("a", "b", "c");
+ c.z("a", "b", "c");
+
+ VarargAbstractClass i = new ClassImplementsClass();
+
+ i.x("a", "b", "c");
+ i.y("a", "b", "c");
+ // System.out.println(i.z("a", "b", "c")); // still incurs a LinkageError.
+ // Perhaps due to Uncurry:
+ // > for every repeated Java parameter `x: T...' --> x: Array[T], except:
+ // > if T is an unbounded abstract type, replace --> x: Array[Object]
+ }
+}
diff --git a/test/files/run/t9013/test.scala b/test/files/run/t9013/test.scala
new file mode 100644
index 0000000000..073f8d086f
--- /dev/null
+++ b/test/files/run/t9013/test.scala
@@ -0,0 +1,18 @@
+import scala.annotation.varargs
+
+abstract class VarargAbstractClass[T] {
+ @varargs
+ def x(els: String*): Int
+
+ @varargs
+ def y(els: String*): Int
+
+ @varargs
+ def z(els: T*): Int
+}
+class ClassImplementsClass extends VarargAbstractClass[String] {
+
+ override def x(els: String*): Int = els.length
+ override def y(els: String*): Int = els.length
+ override def z(els: String*): Int = els.length
+}
diff --git a/test/junit/scala/collection/IndexedSeqTest.scala b/test/junit/scala/collection/IndexedSeqTest.scala
new file mode 100644
index 0000000000..a33849e60b
--- /dev/null
+++ b/test/junit/scala/collection/IndexedSeqTest.scala
@@ -0,0 +1,578 @@
+package scala.collection
+
+import org.junit.Test
+import org.junit.Ignore
+import org.junit.Assert.{assertEquals, _}
+import org.junit.runner.RunWith
+import org.junit.runners.JUnit4
+
+// with the Ant JUnit runner, it's necessary to @Ignore the abstract
+// classes here, or JUnit tries to instantiate them. the annotations
+// can be removed when this is merged forward (TODO 2.12.x)
+
+/**
+ * base class for testing common methods on a various implementations
+ *
+ * @tparam T the collection type
+ * @tparam E the element type
+ */
+@RunWith(classOf[JUnit4])
+@Ignore
+abstract class IndexedTest[T, E] {
+
+ protected def size = 10
+
+ /**
+ * create a new instance of the test data with known values
+ */
+ protected def underTest(size: Int): T
+
+ /**
+ * returns the value of the data that is expected to be present int the original data at index {{{index}}}
+ * This is conceptully the same as the normal apply operation but unavaialbe due to the base types of T not supporting apply
+ *
+ * @param index the index to use for the returned value
+ * @return the value at the specified index
+ */
+ protected def expectedValueAtIndex(index: Int): E
+ /**
+ * check some simple indexed access
+ */
+ @Test def checkIndexedAccess: Unit = {
+ val test = underTest(size)
+ for (i <- 0 until size) {
+ assertEquals(s" at index $i", expectedValueAtIndex(i), get(test, i))
+ }
+ }
+
+ /**
+ * check simple equallity of the initial data.
+ * More a test of the infra that we use in this est than a full test of equallity
+ */
+ @Test def checkEquals: Unit = {
+ val test1 = underTest(size)
+ val test2 = underTest(size)
+ doAssertEquals("", test1, test2)
+ assertNotSame(test1, test2)
+ expectSameContent("basic equallity", false, test1, test2, 0, size)
+ }
+
+ protected def expectSameContent(txt: String, canBeSame:Boolean, orig: T, test: T, offset: Int, len: Int): Unit = {
+ val txtAndState = s"$txt canBeSame $canBeSame isMutableContent $isMutableContent isTakeAllSame $isTakeAllSame offset $offset len $len length(test) ${length(test)}"
+ val isValidSame = canBeSame && !isMutableContent && offset == 0 && len == size
+ if (isValidSame && isTakeAllSame)
+ assertSame(txtAndState, orig, test)
+ else
+ assertNotSame(txtAndState, orig, test)
+ assertSame(txtAndState, len, length(test))
+ for (i <- 0 until len) {
+ assertEquals(s" $txtAndState $i $offset $len", expectedValueAtIndex(i + offset), get(test, i))
+ }
+ }
+
+ /**
+ * check the operation of {{{take}}} when the parameter is less than the size of the test data
+ */
+ @Test def checkTakeNormal: Unit = {
+ val orig = underTest(size)
+ for (len <- 0 until size) {
+ val taken = take(orig, len)
+ expectSameContent(s" len $len", true, orig, taken, 0, len)
+ }
+ }
+
+ /**
+ * check the operation of {{{slice}}} within the bounds of the source
+ */
+ @Test def checkSliceNormal: Unit = {
+ val orig = underTest(size)
+ for (
+ from <- 0 until size;
+ to <- from until size) {
+
+ val sliced = slice(orig, from, to)
+ expectSameContent(s"from $from, to $to", true, orig, sliced, from, to - from)
+ }
+ }
+
+ /**
+ * check the operation of {{{take}}} works for size of 0
+ * There is a special case tha for some implementations empty will be a singleton
+ */
+ @Test def checkTakeEmpty: Unit = {
+ val orig = underTest(size)
+ val empty1 = take(orig, 0)
+ val empty2 = take(orig, 0)
+ assertEquals(0, length(empty1))
+ if (isEmptyConstant) assertSame(empty1, empty2)
+ }
+
+ /**
+ * check the operation of {{{slice}}} works for size of 0
+ * There is a special case tha for some implementations empty will be a singleton
+ */
+ @Test def checkSliceEmpty: Unit = {
+ val orig = underTest(size)
+ for (start <- 0 until size) {
+ val empty1 = slice(orig, start, start)
+ val empty2 = slice(orig, start, start)
+ assertEquals(s"start $start", 0, length(empty1))
+ if (isEmptyConstant) assertSame(s"start $start", empty1, empty2)
+ }
+ }
+
+ /**
+ * check the operation of {{{take}}} works for the entire content
+ * There is a special case that for some immutable implementations they can share the result
+ */
+ @Test def checkTakeAll: Unit = {
+ val orig = underTest(size)
+ val all = take(orig, size)
+ assertEquals(size, length(all))
+ expectSameContent("take all", true, orig, all, 0, size)
+ if (isMutableContent)
+ assertNotSame(orig, all)
+ else if (isTakeAllSame)
+ assertSame(orig, all)
+ }
+
+ /**
+ * check the operation of {{{slice}}} works for the entire content
+ * There is a special case that for some immutable implementations they can share the result
+ */
+ @Test def checkSliceAll: Unit = {
+ val orig = underTest(size)
+ val all = slice(orig, 0, size)
+ assertEquals(size, length(all))
+ expectSameContent("", true, orig, all, 0, size)
+ if (isMutableContent)
+ assertNotSame(orig, all)
+ else if (isTakeAllSame)
+ assertSame(orig, all)
+ }
+
+ /**
+ * check that take operates appropriately for negative values
+ * take and slice should be lenient and silently ignore any data outside valid ranges
+ */
+ @Test def checkTakeNeg: Unit = {
+ val orig = underTest(size)
+ val e = take(orig, 0)
+ for (len <- List(-1, -10, -99, Int.MinValue)) {
+ val empty = take(orig, len)
+ assertEquals(s"len $len", 0, length(empty))
+ if (isEmptyConstant) assertSame(s"len $len", e, empty)
+ }
+ }
+
+ /**
+ * check that take operates appropriately for lengths that exceed the input size
+ * take and slice should be lenient and silently ignore any data outside valid ranges
+ */
+ @Test def checkTakeTooBig: Unit = {
+ val orig = underTest(size)
+ val e = take(orig, 0)
+ for (len <- List(size + 1, size + 10, Int.MaxValue)) {
+ val all = take(orig, len)
+ assertEquals(s"len $len", size, length(all))
+ expectSameContent("", true, orig, all, 0, size)
+ }
+ }
+
+ /**
+ * check that slice operates appropriately for negative start point
+ * take and slice should be lenient and silently ignore any data outside valid ranges
+ */
+ @Test def checkSliceFromNeg: Unit = {
+ val orig = underTest(size)
+ for (
+ from <- List(-1, -10, -99, Int.MinValue);
+ to <- List(-1, 0, 1, 5)) {
+ val start = slice(orig, from, to)
+ expectSameContent(s"from $from, to $to", true, orig, start, 0, Math.max(0, to))
+ }
+ }
+
+ /**
+ * check that slice operates appropriately for out of range end values
+ * take and slice should be lenient and silently ignore any data outside valid ranges
+ */
+ @Test def checkSliceToTooBig: Unit = {
+ val orig = underTest(size)
+ for (
+ from <- List(-1, -10, -99, Int.MinValue, 0, 1, 5);
+ to <- List(size + 1, size + 10, Int.MaxValue)) {
+ val start = slice(orig, from, to)
+ val realStart = Math.max(0, from)
+ val realLen = size - realStart
+ expectSameContent(s"from $from, to $to", true, orig, start, realStart, realLen)
+ }
+ }
+
+ /**
+ * check that slice operates appropriately for negative values start and ends too large
+ * take and slice should be lenient and silently ignore any data outside valid ranges
+ */
+ @Test def checkSliceFromNegAndToTooBig: Unit = {
+ val orig = underTest(size)
+ for (
+ from <- List(-1, -10, -99, Int.MinValue);
+ to <- List(size + 1, size + 10, Int.MaxValue)) {
+ val all = slice(orig, from, to)
+ expectSameContent(s"from $from, to $to", true, orig, all, 0, size)
+ }
+ }
+
+ protected def intercept[EX <: Exception : Manifest](fn: => Any) {
+ try {
+ val res = fn
+ fail(s"expected exception was not thrown: $res")
+ } catch {
+ case failed: AssertionError => throw failed
+ case e: Exception if manifest[EX].runtimeClass.isAssignableFrom(e.getClass) =>
+ }
+ }
+
+ //accessors
+ //the length of underTest
+ def length(underTest: T): Int
+
+ //the value at index i of underTest
+ def get(underTest: T, i: Int): E
+
+ def slice(underTest: T, from: Int, to: Int): T
+
+ def take(underTest: T, size: Int): T
+
+ //behaviour
+ /** is an empty value the same JVM instance */
+ def isEmptyConstant: Boolean
+
+ /** is a take / slice that results in all the data returned return this
+ * This is only relevant if !isMutableContent
+ */
+ def isTakeAllSame: Boolean
+
+ /** is the content of the collection mutable.
+ * If mutable there is not data sharing allowed by take/slice, if immutable then data sharing is possible
+ * and tested based on isTakeAllSame
+ */
+ def isMutableContent: Boolean
+
+ //helpers
+ //delegate equals check for support arrays
+ def doAssertEquals(txt: String, expected: T, actual: T)
+
+}
+package IndexedTestImpl {
+ import java.lang.reflect.{Array => jlArray}
+ import java.lang.{Boolean => jlBoolean}
+ import java.lang.{Byte => jlByte}
+ import java.lang.{Short => jlShort}
+ import java.lang.{Integer => jlInt}
+ import java.lang.{Long => jlLong}
+ import java.lang.{Float => jlFloat}
+ import java.lang.{Double => jlDouble}
+ import java.lang.{Character => jlChar}
+
+ import scala.collection.immutable.{StringLike, StringOps, WrappedString}
+ import scala.collection.mutable
+ import scala.runtime.BoxedUnit
+ trait DataProvider[E] {
+ protected def expectedValueAtIndex(index: Int): E = {
+ val someNumber = index + jlInt.bitCount(index)
+ toType(someNumber)
+ }
+
+ protected def toType(n: Int): E
+ }
+ trait StringTestData extends DataProvider [String] {
+ def toType(n: Int) = n.toString
+ }
+ trait ByteTestData extends DataProvider [Byte] {
+ def toType(n: Int) = n.toByte
+ }
+ trait ShortTestData extends DataProvider [Short] {
+ def toType(n: Int) = n.toShort
+ }
+ trait IntTestData extends DataProvider [Int] {
+ def toType(n: Int) = n
+ }
+ trait LongTestData extends DataProvider [Long] {
+ def toType(n: Int) = n
+ }
+ trait FloatTestData extends DataProvider [Float] {
+ def toType(n: Int) = n
+ }
+ trait DoubleTestData extends DataProvider [Double] {
+ def toType(n: Int) = n
+ }
+ trait CharTestData extends DataProvider [Char] {
+ def toType(n: Int)= (n+64).toChar
+ }
+ trait BooleanTestData extends DataProvider [Boolean] {
+ def toType(n: Int)= (n & 0) == 0
+ }
+ trait UnitTestData extends DataProvider [BoxedUnit] {
+ def toType(n: Int)= if ((n & 0) == 0) null else BoxedUnit.UNIT
+ }
+
+ @Ignore
+ abstract class ArrayTest[E] (
+ //the object or primitive type of the array
+ val TYPE: Class[_]) extends IndexedTest[Array[E], E]{
+ override final def length(underTest: Array[E]) = underTest.length
+
+ override def get(underTest: Array[E], i: Int) = underTest(i)
+
+ override def slice(underTest: Array[E], from: Int, to: Int) = underTest.slice(from, to)
+
+ override def take(underTest: Array[E], size: Int) = underTest.take(size)
+
+ override def isEmptyConstant = false
+
+ override def isMutableContent = true
+
+ override def isTakeAllSame = false
+
+ override def doAssertEquals(txt: String, expected: Array[E], actual: Array[E]): Unit = {
+ assertEquals(txt, expected.mkString("'"), actual.mkString("'"))
+ }
+
+ override def underTest(size: Int): Array[E] = {
+ val res = jlArray.newInstance(TYPE, size)
+ for (i <- 0 until size) {
+ jlArray.set(res, i, expectedValueAtIndex(i))
+ }
+ res.asInstanceOf[Array[E]]
+ }
+ }
+
+
+ @Ignore
+ abstract class WrappedArrayTest[E](
+ //the object or primitive type of the array
+ val TYPE: Class[_]) extends IndexedTest[mutable.WrappedArray[E], E] with DataProvider[E]{
+ import mutable.WrappedArray
+ override final def length(underTest: WrappedArray[E]) = underTest.length
+
+ override def get(underTest: WrappedArray[E], i: Int) = underTest(i)
+
+ override def slice(underTest: WrappedArray[E], from: Int, to: Int) = underTest.slice(from, to)
+
+ override def take(underTest: WrappedArray[E], size: Int) = underTest.take(size)
+
+ override def isEmptyConstant = false
+
+ override def isMutableContent = true
+
+ override def isTakeAllSame = false
+
+ override def doAssertEquals(txt: String, expected: WrappedArray[E], actual: WrappedArray[E]): Unit = {
+ assertEquals(txt, expected.mkString("'"), actual.mkString("'"))
+ }
+
+ override def underTest(size: Int): WrappedArray[E] = {
+ val res = jlArray.newInstance(TYPE, size)
+ for (i <- 0 until size) {
+ jlArray.set(res, i, expectedValueAtIndex(i))
+ }
+ WrappedArray.make(res.asInstanceOf[Array[E]])
+ }
+ }
+
+ //construct the data using java as much as possible to avoid invalidating the test
+
+ @Ignore
+ abstract class MutableIndexedSeqTest[T <: mutable.Seq[E], E] extends IndexedTest[T, E] with DataProvider[E]{
+ override final def length(underTest: T) = underTest.length
+
+ override def get(underTest: T, i: Int) = underTest(i)
+
+ override def slice(underTest: T, from: Int, to: Int) = underTest.slice(from, to).asInstanceOf[T]
+
+ override def take(underTest: T, size: Int) = underTest.take(size).asInstanceOf[T]
+
+ override def isEmptyConstant = false
+
+ override def isMutableContent = true
+
+ override def isTakeAllSame = true
+
+ override def doAssertEquals(txt: String, expected: T, actual: T): Unit = {
+ assertEquals(txt, expected, actual)
+ }
+
+ def createEmpty(size: Int) : T
+
+ override protected def underTest(size: Int): T = {
+ val res:T = createEmpty(size)
+ for (i <- 0 until size)
+ res(i) = expectedValueAtIndex(i)
+ res
+ }
+
+ }
+ @Ignore
+ abstract class ImmutableIndexedSeqTest[T <: SeqLike[E, T], E] extends IndexedTest[T, E] with DataProvider[E] {
+ override final def length(underTest: T) = underTest.length
+
+ override def get(underTest: T, i: Int) = underTest(i)
+
+ override def slice(underTest: T, from: Int, to: Int) = underTest.slice(from, to)
+
+ override def take(underTest: T, size: Int) = underTest.take(size)
+
+ override def isEmptyConstant = false
+
+ override def isMutableContent = false
+
+ override def isTakeAllSame = true
+
+ override def doAssertEquals(txt: String, expected: T, actual: T): Unit = {
+ assertEquals(txt, expected, actual)
+ }
+
+ }
+ @Ignore
+ abstract class StringOpsBaseTest extends IndexedTest[StringOps, Char] with DataProvider[Char] {
+ override final def length(underTest: StringOps) = underTest.length
+
+ override def get(underTest: StringOps, i: Int) = underTest(i)
+
+ override def slice(underTest: StringOps, from: Int, to: Int) = underTest.slice(from, to)
+
+ override def take(underTest: StringOps, size: Int) = underTest.take(size)
+
+ override def isEmptyConstant = false
+
+ override def isMutableContent = false
+
+ override def isTakeAllSame = false
+
+ override def doAssertEquals(txt: String, expected: StringOps, actual: StringOps): Unit = {
+ assertEquals(txt, expected, actual)
+ }
+
+ }
+
+ class BooleanArrayTest extends ArrayTest[Boolean](jlBoolean.TYPE) with BooleanTestData
+ class ByteArrayTest extends ArrayTest[Byte](jlByte.TYPE) with ByteTestData
+ class ShortArrayTest extends ArrayTest[Short](jlShort.TYPE) with ShortTestData
+ class IntArrayTest extends ArrayTest[Int](jlInt.TYPE) with IntTestData
+ class LongArrayTest extends ArrayTest[Long](jlLong.TYPE) with LongTestData
+ class DoubleArrayTest extends ArrayTest[Double](jlDouble.TYPE) with DoubleTestData
+ class FloatArrayTest extends ArrayTest[Float](jlFloat.TYPE) with FloatTestData
+ class CharArrayTest extends ArrayTest[Char](jlChar.TYPE) with CharTestData
+ class UnitArrayTest extends ArrayTest[BoxedUnit](null) with UnitTestData {
+ override def underTest(size: Int): Array[BoxedUnit] = {
+ val res = new Array[Unit](size)
+ for (i <- 0 until size) {
+ jlArray.set(res, i, expectedValueAtIndex(i))
+ }
+ res.asInstanceOf[Array[BoxedUnit]]
+ }
+ }
+ class RefArrayTest extends ArrayTest[String](classOf[String]) with StringTestData
+
+ class BooleanWrappedArrayTest extends WrappedArrayTest[Boolean](jlBoolean.TYPE) with BooleanTestData
+ class ByteWrappedArrayTest extends WrappedArrayTest[Byte](jlByte.TYPE) with ByteTestData
+ class ShortWrappedArrayTest extends WrappedArrayTest[Short](jlShort.TYPE) with ShortTestData
+ class IntWrappedArrayTest extends WrappedArrayTest[Int](jlInt.TYPE) with IntTestData
+ class LongWrappedArrayTest extends WrappedArrayTest[Long](jlLong.TYPE) with LongTestData
+ class DoubleWrappedArrayTest extends WrappedArrayTest[Double](jlDouble.TYPE) with DoubleTestData
+ class FloatWrappedArrayTest extends WrappedArrayTest[Float](jlFloat.TYPE) with FloatTestData
+ class CharWrappedArrayTest extends WrappedArrayTest[Char](jlChar.TYPE) with CharTestData
+ class UnitWrappedArrayTest extends WrappedArrayTest[BoxedUnit](null) with UnitTestData {
+ import mutable.WrappedArray
+ override def underTest(size: Int): WrappedArray[BoxedUnit] = {
+ val res = new Array[Unit](size)
+ for (i <- 0 until size) {
+ jlArray.set(res, i, expectedValueAtIndex(i))
+ }
+ WrappedArray.make(res.asInstanceOf[Array[Unit]])
+ }
+ }
+ class RefWrappedArrayTest extends WrappedArrayTest[String](classOf[String]) with StringTestData
+
+ class ListBufferTest extends MutableIndexedSeqTest[mutable.ListBuffer[String], String] with StringTestData {
+ import mutable.ListBuffer
+ override def createEmpty(size: Int): ListBuffer[String] = {
+ val res = new ListBuffer[String]
+ for (i <- 0 until size)
+ res += expectedValueAtIndex(i)
+ res
+ }
+ }
+ class ArraySeqTest extends MutableIndexedSeqTest[mutable.ArraySeq[String], String] with StringTestData {
+ import mutable.ArraySeq
+ override def createEmpty(size: Int): ArraySeq[String] = {
+ val res = new ArraySeq[String](size)
+ for (i <- 0 until size)
+ res (i) = expectedValueAtIndex(i)
+ res
+ }
+ }
+ class ArrayBufferTest extends MutableIndexedSeqTest[mutable.ArrayBuffer[String], String] with StringTestData {
+ import mutable.ArrayBuffer
+ override def createEmpty(size: Int): ArrayBuffer[String] = {
+ val res = new ArrayBuffer[String](size)
+ for (i <- 0 until size)
+ res += expectedValueAtIndex(i)
+ res
+ }
+ }
+ class ListTest extends ImmutableIndexedSeqTest[List[String], String] with StringTestData {
+
+ override protected def underTest(size: Int): List[String] = {
+ var res:List[String] = Nil
+ var index = size-1
+ while (index >= 0) {
+ res = expectedValueAtIndex(index) :: res
+ index -= 1
+ }
+ res
+ }
+ }
+ class StringBuilderTest extends MutableIndexedSeqTest[StringBuilder, Char] with CharTestData {
+
+ override def createEmpty(size: Int): StringBuilder = new StringBuilder(size)
+
+ override protected def underTest(size: Int): StringBuilder = {
+ var res = createEmpty(size)
+ for (i <- 0 until size)
+ res += expectedValueAtIndex(i)
+ res
+ }
+ }
+ class StringOpsTest extends StringOpsBaseTest with CharTestData {
+
+ override protected def underTest(size: Int): StringOps = {
+ var res = new StringBuilder(size)
+ for (i <- 0 until size)
+ res += expectedValueAtIndex(i)
+ res.toString
+ }
+ }
+ class WrappedStringTest extends ImmutableIndexedSeqTest[WrappedString, Char] with CharTestData {
+
+ override def isTakeAllSame: Boolean = false
+
+ override protected def underTest(size: Int): WrappedString = {
+ var res = new StringBuilder(size)
+ for (i <- 0 until size)
+ res += expectedValueAtIndex(i)
+ new WrappedString(res.toString)
+ }
+ }
+ class VectorTest extends ImmutableIndexedSeqTest[Vector[String], String] with StringTestData {
+
+ override protected def underTest(size: Int): Vector[String] = {
+ var res = Vector.newBuilder[String]
+ for (i <- 0 until size)
+ res += expectedValueAtIndex(i)
+ res.result()
+ }
+ }
+
+}