From 5156cd1377c0b3d394d50ded9c72f49cb1f5c4ce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=A8=E5=8D=9A=20=28Yang=20Bo=29?= Date: Wed, 28 Feb 2018 21:06:34 +0800 Subject: [PATCH 001/143] Replace UnApply to Apply in resetLocalAttris This change fixes SI-8825 --- src/compiler/scala/tools/nsc/ast/Trees.scala | 4 ++++ test/files/run/idempotency-extractors.check | 2 +- test/files/run/idempotency-extractors.scala | 5 +++-- 3 files changed, 8 insertions(+), 3 deletions(-) diff --git a/src/compiler/scala/tools/nsc/ast/Trees.scala b/src/compiler/scala/tools/nsc/ast/Trees.scala index 1dbbf7e0f3e4..0a3b439461c1 100644 --- a/src/compiler/scala/tools/nsc/ast/Trees.scala +++ b/src/compiler/scala/tools/nsc/ast/Trees.scala @@ -289,6 +289,10 @@ trait Trees extends scala.reflect.internal.Trees { self: Global => transform(fn) case EmptyTree => tree + // The typer does not accept UnApply. Replace it to Apply, which can be retyped. + case UnApply(Apply(Select(prefix, termNames.unapply | termNames.unapplySeq), + List(Ident(termNames.SELECTOR_DUMMY))), args) => + Apply(prefix, transformTrees(args)) case _ => val dupl = tree.duplicate // Typically the resetAttrs transformer cleans both symbols and types. diff --git a/test/files/run/idempotency-extractors.check b/test/files/run/idempotency-extractors.check index fcd50faa7905..e9bcb720077b 100644 --- a/test/files/run/idempotency-extractors.check +++ b/test/files/run/idempotency-extractors.check @@ -2,4 +2,4 @@ 2 match { case Test.this.Extractor.unapply() ((x @ _)) => x } -error! +2 diff --git a/test/files/run/idempotency-extractors.scala b/test/files/run/idempotency-extractors.scala index 590147cae6a3..c7df2e734121 100644 --- a/test/files/run/idempotency-extractors.scala +++ b/test/files/run/idempotency-extractors.scala @@ -14,9 +14,10 @@ object Test extends App { println(textractor) val rtextractor = tb.untypecheck(textractor) try { + // should print 2 without error println(tb.eval(rtextractor)) } catch { - // this is the current behaviour, rather than the desired behavior; see scala/bug#5465 + // this is the old behaviour, rather than the desired behavior; see scala/bug#5465 case _: ToolBoxError => println("error!") } -} \ No newline at end of file +} From 8c9c70d6a7ac916dc4dcc4391e9124eaec105b34 Mon Sep 17 00:00:00 2001 From: Georgi Krastev Date: Mon, 15 Jan 2018 19:10:06 +0100 Subject: [PATCH 002/143] Factor out duplicated logic from elimSub/elimSuper --- .../scala/reflect/internal/tpe/GlbLubs.scala | 39 +++++++++---------- 1 file changed, 19 insertions(+), 20 deletions(-) diff --git a/src/reflect/scala/reflect/internal/tpe/GlbLubs.scala b/src/reflect/scala/reflect/internal/tpe/GlbLubs.scala index fb136fd570c1..712c61dcdd5c 100644 --- a/src/reflect/scala/reflect/internal/tpe/GlbLubs.scala +++ b/src/reflect/scala/reflect/internal/tpe/GlbLubs.scala @@ -158,31 +158,30 @@ private[internal] trait GlbLubs { rest filter (t => !first.typeSymbol.isSubClass(t.typeSymbol))) } + /** From a list of types, retain only maximal types as determined by the partial order `po`. */ + private def maxTypes(ts: List[Type])(po: (Type, Type) => Boolean): List[Type] = { + def loop(ts: List[Type]): List[Type] = ts match { + case t :: ts1 => + val ts2 = loop(ts1.filterNot(po(_, t))) + if (ts2.exists(po(t, _))) ts2 else t :: ts2 + case Nil => Nil + } + + loop(ts) + } + /** Eliminate from list of types all elements which are a supertype * of some other element of the list. */ - private def elimSuper(ts: List[Type]): List[Type] = ts match { - case List() | List(_) => ts - case t :: ts1 => - val rest = elimSuper(ts1 filter (t1 => !(t <:< t1))) - if (rest exists (t1 => t1 <:< t)) rest else t :: rest - } + private def elimSuper(ts: List[Type]): List[Type] = + maxTypes(ts)((t1, t2) => t2 <:< t1) /** Eliminate from list of types all elements which are a subtype * of some other element of the list. */ - private def elimSub(ts: List[Type], depth: Depth): List[Type] = { - def elimSub0(ts: List[Type]): List[Type] = ts match { - case List() => ts - case List(t) => ts - case t :: ts1 => - val rest = elimSub0(ts1 filter (t1 => !isSubType(t1, t, depth.decr))) - if (rest exists (t1 => isSubType(t, t1, depth.decr))) rest else t :: rest - } - val ts0 = elimSub0(ts) - if (ts0.isEmpty || ts0.tail.isEmpty) ts0 - else { - val ts1 = ts0 mapConserve (t => elimAnonymousClass(t.dealiasWiden)) - if (ts1 eq ts0) ts0 - else elimSub(ts1, depth) + @tailrec private def elimSub(ts: List[Type], depth: Depth): List[Type] = { + val ts1 = maxTypes(ts)(isSubType(_, _, depth.decr)) + if (ts1.lengthCompare(1) <= 0) ts1 else { + val ts2 = ts1.mapConserve(t => elimAnonymousClass(t.dealiasWiden)) + if (ts1 eq ts2) ts1 else elimSub(ts2, depth) } } From 6bbef4e3fd3a19260a68fe9b9431e5cb7a6684e1 Mon Sep 17 00:00:00 2001 From: Georgi Krastev Date: Mon, 15 Jan 2018 19:10:57 +0100 Subject: [PATCH 003/143] Eliminate TypeVars and Wildcards early in glb/lub Type variables and wildcards can act both as subtypes and supertypes depending on the direction of the test. This means types with variables and/or wildcards can shadow other types in `glb/lub`. Consider the following examples: ```scala lub((Int, ? ) :: (Int, String) :: Nil) glb((Int, ?A) :: (Int, String) :: Nil) ``` Intuitively both should return `(Int, String)`, but this depends on the order of types in the list passed to `glb/lub`. This commit incorporates the simple heuristic of moving types that contain variables and/or wildcards to the end of the list. Fixes scala/bug#10686 and fixes scala/bug#10740 --- src/reflect/scala/reflect/internal/tpe/GlbLubs.scala | 9 ++++++++- test/files/pos/t10686.scala | 6 ++++++ test/files/pos/t10740.scala | 11 +++++++++++ 3 files changed, 25 insertions(+), 1 deletion(-) create mode 100644 test/files/pos/t10686.scala create mode 100644 test/files/pos/t10740.scala diff --git a/src/reflect/scala/reflect/internal/tpe/GlbLubs.scala b/src/reflect/scala/reflect/internal/tpe/GlbLubs.scala index 712c61dcdd5c..8b01b15b5249 100644 --- a/src/reflect/scala/reflect/internal/tpe/GlbLubs.scala +++ b/src/reflect/scala/reflect/internal/tpe/GlbLubs.scala @@ -167,7 +167,14 @@ private[internal] trait GlbLubs { case Nil => Nil } - loop(ts) + // The order here matters because type variables and + // wildcards can act both as subtypes and supertypes. + val (ts2, ts1) = ts.partition(_ exists { + case tv: TypeVar => !tv.isGround + case t => t.isWildcard + }) + + loop(ts1 ::: ts2) } /** Eliminate from list of types all elements which are a supertype diff --git a/test/files/pos/t10686.scala b/test/files/pos/t10686.scala new file mode 100644 index 000000000000..ff803e4b6b53 --- /dev/null +++ b/test/files/pos/t10686.scala @@ -0,0 +1,6 @@ +object Test { + def ltr[A](implicit ev: (Int, A) =:= (Int, String)) = null + def rtl[A](implicit ev: (Int, String) =:= (Int, A)) = null + ltr + rtl +} diff --git a/test/files/pos/t10740.scala b/test/files/pos/t10740.scala new file mode 100644 index 000000000000..5b409e659378 --- /dev/null +++ b/test/files/pos/t10740.scala @@ -0,0 +1,11 @@ +object Test { + case class Inv[A](x: A) + def diff1[A](i: Inv[A], j: Inv[_ <: A]) = 1 + def diff2[A](i: Inv[_ >: A], j: Inv[A]) = 2 + def diff3[A](i: Inv[_ >: A], j: Inv[_ <: A]) = 3 + val i = Inv(Option(42)) + val j = Inv(Some(42)) + diff1(i, j) + diff2(i, j) + diff3(i, j) +} From 2449721812ce36b0b11ee2653aa809b11f8e3765 Mon Sep 17 00:00:00 2001 From: Martijn Hoekstra Date: Mon, 28 May 2018 13:02:45 +0200 Subject: [PATCH 004/143] deprecate either projections --- src/library/scala/util/Either.scala | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/library/scala/util/Either.scala b/src/library/scala/util/Either.scala index 6165649e2f0c..4f3c2ce6b8ee 100644 --- a/src/library/scala/util/Either.scala +++ b/src/library/scala/util/Either.scala @@ -162,12 +162,14 @@ sealed abstract class Either[+A, +B] extends Product with Serializable { * for (e <- interactWithDB(someQuery).left) log(s"query failed, reason was $e") * }}} */ + @deprecated("use swap instead", "2.13.0") def left = Either.LeftProjection(this) /** Projects this `Either` as a `Right`. * * Because `Either` is right-biased, this method is not normally needed. */ + @deprecated("Either is now right-biased", "2.13.0") def right = Either.RightProjection(this) /** Applies `fa` if this is a `Left` or `fb` if this is a `Right`. @@ -476,6 +478,7 @@ object Either { * @version 1.0, 11/10/2008 * @see [[scala.util.Either#left]] */ + @deprecated("use swap instead", "2.13.0") final case class LeftProjection[+A, +B](e: Either[A, B]) { /** Returns the value from this `Left` or throws `java.util.NoSuchElementException` * if this is a `Right`. @@ -620,6 +623,7 @@ object Either { * @author Tony Morris, Workingmouse * @version 1.0, 11/10/2008 */ + @deprecated("Either is now right-biased", "2.13.0") final case class RightProjection[+A, +B](e: Either[A, B]) { /** Returns the value from this `Right` or throws From 24f143869398505a4a20159ef1ee62b3a5af61e1 Mon Sep 17 00:00:00 2001 From: Harrison Houghton Date: Sat, 9 Jun 2018 19:22:04 -0400 Subject: [PATCH 005/143] Parenthesize infix type constructors before using them as a prefix. Otherwise, `(A ^ B)#T` prints as `A ^ B#T`, which just ain't right. Fixes scala/bug#10937. --- src/reflect/scala/reflect/internal/Types.scala | 5 ++++- test/files/run/t4700.check | 6 ++++++ test/files/run/t4700.scala | 2 ++ 3 files changed, 12 insertions(+), 1 deletion(-) diff --git a/src/reflect/scala/reflect/internal/Types.scala b/src/reflect/scala/reflect/internal/Types.scala index bec839b85606..4c99c52fbd72 100644 --- a/src/reflect/scala/reflect/internal/Types.scala +++ b/src/reflect/scala/reflect/internal/Types.scala @@ -932,7 +932,10 @@ trait Types def trimPrefix(str: String) = str stripPrefix objectPrefix stripPrefix packagePrefix /** The string representation of this type used as a prefix */ - def prefixString = trimPrefix(toString) + "#" + def prefixString = { + val pre = trimPrefix(toString) + if (isShowAsInfixType) s"($pre)#" else pre + "#" + } /** Convert toString avoiding infinite recursions by cutting off * after `maxToStringRecursions` recursion levels. Uses `safeToString` diff --git a/test/files/run/t4700.check b/test/files/run/t4700.check index ae854b959db9..2c72a3723f24 100644 --- a/test/files/run/t4700.check +++ b/test/files/run/t4700.check @@ -41,4 +41,10 @@ foo: (Int && String) &: Boolean scala> def foo: Int && (Boolean &: String) = ??? foo: Int && (Boolean &: String) +scala> trait ^[A, B] { type T } /* scala/bug#10937 */ +defined trait $up + +scala> def x[A, B] : (A ^ B)#T = ??? +x: [A, B]=> (A ^ B)#T + scala> :quit diff --git a/test/files/run/t4700.scala b/test/files/run/t4700.scala index 7c02676e89f0..b62aab0358fb 100644 --- a/test/files/run/t4700.scala +++ b/test/files/run/t4700.scala @@ -17,6 +17,8 @@ object Test extends ReplTest { |def foo: Int &: Boolean &: String = ??? |def foo: (Int && String) &: Boolean = ??? |def foo: Int && (Boolean &: String) = ??? + |trait ^[A, B] { type T } /* scala/bug#10937 */ + |def x[A, B] : (A ^ B)#T = ??? |""".stripMargin } From 04cd5c392ccb4543520e39be738857f45c8ddc1a Mon Sep 17 00:00:00 2001 From: Lukas Rytz Date: Wed, 13 Jun 2018 12:51:27 +0200 Subject: [PATCH 006/143] Consider delayedInit$body classes as top-level for Java compatibility We do the same for specialized subclasses. There's no real advantage in putting these classes into an INNERCLASS attribute. They have synthetic names anyway and are not intended to be used from Java. --- src/compiler/scala/tools/nsc/backend/jvm/BCodeHelpers.scala | 4 +++- test/files/run/t10487.scala | 3 +++ 2 files changed, 6 insertions(+), 1 deletion(-) create mode 100644 test/files/run/t10487.scala diff --git a/src/compiler/scala/tools/nsc/backend/jvm/BCodeHelpers.scala b/src/compiler/scala/tools/nsc/backend/jvm/BCodeHelpers.scala index 2f5f0ad246c6..c526306cecd6 100644 --- a/src/compiler/scala/tools/nsc/backend/jvm/BCodeHelpers.scala +++ b/src/compiler/scala/tools/nsc/backend/jvm/BCodeHelpers.scala @@ -33,7 +33,9 @@ abstract class BCodeHelpers extends BCodeIdiomatic { * True for classes generated by the Scala compiler that are considered top-level in terms of * the InnerClass / EnclosingMethod classfile attributes. See comment in BTypes. */ - def considerAsTopLevelImplementationArtifact(classSym: Symbol) = classSym.isSpecialized + def considerAsTopLevelImplementationArtifact(classSym: Symbol) = + classSym.isSpecialized || + classSym.isSynthetic && classSym.name.containsName(nme.delayedInitArg.toTypeName) /** * Cache the value of delambdafy == "inline" for each run. We need to query this value many diff --git a/test/files/run/t10487.scala b/test/files/run/t10487.scala new file mode 100644 index 000000000000..f1b50cde6d27 --- /dev/null +++ b/test/files/run/t10487.scala @@ -0,0 +1,3 @@ +object Test extends App { + assert(Class.forName("Test$delayedInit$body").getEnclosingClass() == null) +} From 5ff703ea9ac9aed0ed84d9898ce39adb674b17f1 Mon Sep 17 00:00:00 2001 From: Som Snytt Date: Thu, 14 Jun 2018 16:01:54 -0700 Subject: [PATCH 007/143] Avoid complaining about implicit evidence Besides DummyImplicit, notice `<:<` and `=:=`. --- .../scala/tools/nsc/typechecker/TypeDiagnostics.scala | 10 +++++++--- src/reflect/scala/reflect/internal/Definitions.scala | 4 ++++ src/reflect/scala/reflect/internal/StdNames.scala | 4 ++++ test/files/neg/warn-unused-params.check | 11 ++++++++++- test/files/neg/warn-unused-params.scala | 11 +++++++++++ 5 files changed, 36 insertions(+), 4 deletions(-) diff --git a/src/compiler/scala/tools/nsc/typechecker/TypeDiagnostics.scala b/src/compiler/scala/tools/nsc/typechecker/TypeDiagnostics.scala index c868b4e476be..9bd0ecfe364c 100644 --- a/src/compiler/scala/tools/nsc/typechecker/TypeDiagnostics.scala +++ b/src/compiler/scala/tools/nsc/typechecker/TypeDiagnostics.scala @@ -698,10 +698,14 @@ trait TypeDiagnostics { val opc = new overridingPairs.Cursor(classOf(m)) opc.iterator.exists(pair => pair.low == m) } + import PartialFunction._ def isConvention(p: Symbol): Boolean = { - (p.name.decoded == "args" && p.owner.isMethod && p.owner.name.decoded == "main") || - (p.tpe =:= typeOf[scala.Predef.DummyImplicit]) - } + val ds = currentRun.runDefinitions + import ds._ ; ( + p.name.decoded == "args" && p.owner.isMethod && p.owner.name.decoded == "main" + || + p.isImplicit && cond(p.tpe.typeSymbol) { case Predef_=:= | Predef_<:< | Predef_Dummy => true } + )} def warningIsOnFor(s: Symbol) = if (s.isImplicit) settings.warnUnusedImplicits else settings.warnUnusedExplicits def warnable(s: Symbol) = ( warningIsOnFor(s) diff --git a/src/reflect/scala/reflect/internal/Definitions.scala b/src/reflect/scala/reflect/internal/Definitions.scala index f68d9c1e859f..123dbec5eac5 100644 --- a/src/reflect/scala/reflect/internal/Definitions.scala +++ b/src/reflect/scala/reflect/internal/Definitions.scala @@ -1468,6 +1468,10 @@ trait Definitions extends api.StandardDefinitions { lazy val StringContext_raw = getMemberMethod(StringContextClass, nme.raw_) lazy val StringContext_apply = getMemberMethod(StringContextModule, nme.apply) + lazy val Predef_=:= = getMemberClass(PredefModule, nme.=:=) + lazy val Predef_<:< = getMemberClass(PredefModule, nme.<:<) + lazy val Predef_Dummy = getMemberClass(PredefModule, nme.DummyImplicit) + lazy val ArrowAssocClass = getMemberClass(PredefModule, TypeName("ArrowAssoc")) // scala/bug#5731 def isArrowAssoc(sym: Symbol) = sym.owner == ArrowAssocClass diff --git a/src/reflect/scala/reflect/internal/StdNames.scala b/src/reflect/scala/reflect/internal/StdNames.scala index 552d82b1eda2..3e0becad2b09 100644 --- a/src/reflect/scala/reflect/internal/StdNames.scala +++ b/src/reflect/scala/reflect/internal/StdNames.scala @@ -590,6 +590,10 @@ trait StdNames { } val ??? = encode("???") + val =:= = encode("=:=") + val <:< = encode("<:<") + + val DummyImplicit: NameType = "DummyImplicit" val wrapRefArray: NameType = "wrapRefArray" val wrapByteArray: NameType = "wrapByteArray" diff --git a/test/files/neg/warn-unused-params.check b/test/files/neg/warn-unused-params.check index 373417ce0809..ba0b6e884d5c 100644 --- a/test/files/neg/warn-unused-params.check +++ b/test/files/neg/warn-unused-params.check @@ -13,6 +13,15 @@ case class CaseyAtTheBat(k: Int)(s: String) // warn warn-unused-params.scala:62: warning: parameter value readResolve in method f is never used def f(readResolve: Int) = 42 // warn ^ +warn-unused-params.scala:77: warning: parameter value dummy in method g is never used + def g(dummy: DummyImplicit) = 42 + ^ +warn-unused-params.scala:82: warning: parameter value ev in method f2 is never used + def f2[A, B](ev: A =:= B) = 42 + ^ +warn-unused-params.scala:83: warning: parameter value ev in method g2 is never used + def g2[A, B](ev: A <:< B) = 42 + ^ error: No warnings can be incurred under -Xfatal-warnings. -5 warnings found +8 warnings found one error found diff --git a/test/files/neg/warn-unused-params.scala b/test/files/neg/warn-unused-params.scala index 559e6352434d..18863e4c2b07 100644 --- a/test/files/neg/warn-unused-params.scala +++ b/test/files/neg/warn-unused-params.scala @@ -71,3 +71,14 @@ class Main { trait Unimplementation { def f(u: Int): Int = ??? // no warn for param in unimplementation } + +trait DumbStuff { + def f(implicit dummy: DummyImplicit) = 42 + def g(dummy: DummyImplicit) = 42 +} +trait Proofs { + def f[A, B](implicit ev: A =:= B) = 42 + def g[A, B](implicit ev: A <:< B) = 42 + def f2[A, B](ev: A =:= B) = 42 + def g2[A, B](ev: A <:< B) = 42 +} From d736b3bded97af17fa7c477c7316a09c955a1771 Mon Sep 17 00:00:00 2001 From: Harrison Houghton Date: Tue, 22 May 2018 08:51:48 -0400 Subject: [PATCH 008/143] Move range position validation behind a flag. The motivation is that the validation step isn't fast, and takes up a good chunk of the "rangepos penalty" time difference. Moreover, Alex Average User can't do much about a fatal rangepos error other than twiddle around their source until it goes away, so it's likely to bother end users less like this. This is a backport to 2.12.x, since position validation is changing for performance, and we evidently want to be cautious about adding new breakages. References scala/scala-dev#472. --- build.sbt | 2 ++ project/ScalaOptionParser.scala | 2 +- src/compiler/scala/tools/nsc/Global.scala | 3 +++ src/compiler/scala/tools/nsc/ast/parser/SyntaxAnalyzer.scala | 3 --- src/compiler/scala/tools/nsc/settings/ScalaSettings.scala | 3 ++- src/compiler/scala/tools/nsc/typechecker/Analyzer.scala | 1 - src/reflect/scala/reflect/internal/Positions.scala | 5 ++--- 7 files changed, 10 insertions(+), 9 deletions(-) diff --git a/build.sbt b/build.sbt index 3793e5128284..a44226b9ecee 100644 --- a/build.sbt +++ b/build.sbt @@ -720,6 +720,8 @@ lazy val test = project // test sources are compiled in partest run, not here sources in IntegrationTest := Seq.empty, fork in IntegrationTest := true, + // enable this in 2.13, when tests pass + //scalacOptions in Compile += "-Yvalidate-pos:parser,typer", javaOptions in IntegrationTest ++= List("-Xmx2G", "-Dpartest.exec.in.process=true", "-Dfile.encoding=UTF-8", "-Duser.language=en", "-Duser.country=US"), testOptions in IntegrationTest += Tests.Argument("-Dfile.encoding=UTF-8", "-Duser.language=en", "-Duser.country=US"), testFrameworks += new TestFramework("scala.tools.partest.sbt.Framework"), diff --git a/project/ScalaOptionParser.scala b/project/ScalaOptionParser.scala index 26d75e51be84..a5cbb35dde40 100644 --- a/project/ScalaOptionParser.scala +++ b/project/ScalaOptionParser.scala @@ -97,7 +97,7 @@ object ScalaOptionParser { "-Ypresentation-log", "-Ypresentation-replay", "-Yrepl-outdir", "-d", "-dependencyfile", "-encoding", "-Xscript") private def pathSettingNames = List("-bootclasspath", "-classpath", "-extdirs", "-javabootclasspath", "-javaextdirs", "-sourcepath", "-toolcp") private val phases = List("all", "parser", "namer", "packageobjects", "typer", "patmat", "superaccessors", "extmethods", "pickler", "refchecks", "uncurry", "tailcalls", "specialize", "explicitouter", "erasure", "posterasure", "fields", "lambdalift", "constructors", "flatten", "mixin", "cleanup", "delambdafy", "icode", "jvm", "terminal") - private val phaseSettings = List("-Xprint-icode", "-Ystop-after", "-Yskip", "-Yshow", "-Ystop-before", "-Ybrowse", "-Ylog", "-Ycheck", "-Xprint") + private val phaseSettings = List("-Xprint-icode", "-Ystop-after", "-Yskip", "-Yshow", "-Ystop-before", "-Ybrowse", "-Ylog", "-Ycheck", "-Xprint", "-Yvalidate-pos") private def multiStringSettingNames = List("-Xmacro-settings", "-Xplugin", "-Xplugin-disable", "-Xplugin-require", "-Ywarn-unused") private def intSettingNames = List("-Xmax-classfile-name", "-Xelide-below", "-Ypatmat-exhaust-depth", "-Ypresentation-delay", "-Yrecursion") private def choiceSettingNames = Map[String, List[String]]( diff --git a/src/compiler/scala/tools/nsc/Global.scala b/src/compiler/scala/tools/nsc/Global.scala index 3edac10cf026..4f0fa16cf52a 100644 --- a/src/compiler/scala/tools/nsc/Global.scala +++ b/src/compiler/scala/tools/nsc/Global.scala @@ -1471,6 +1471,9 @@ class Global(var currentSettings: Settings, reporter0: Reporter) if (settings.browse containsPhase globalPhase) treeBrowser browse (phase.name, units) + if ((settings.Yvalidatepos containsPhase globalPhase) && !reporter.hasErrors) + currentRun.units.foreach(unit => validatePositions(unit.body)) + // move the pointer globalPhase = globalPhase.next diff --git a/src/compiler/scala/tools/nsc/ast/parser/SyntaxAnalyzer.scala b/src/compiler/scala/tools/nsc/ast/parser/SyntaxAnalyzer.scala index e0667b5a3ebb..b4b6f25dc999 100644 --- a/src/compiler/scala/tools/nsc/ast/parser/SyntaxAnalyzer.scala +++ b/src/compiler/scala/tools/nsc/ast/parser/SyntaxAnalyzer.scala @@ -98,9 +98,6 @@ abstract class SyntaxAnalyzer extends SubComponent with Parsers with MarkupParse if (unit.body == EmptyTree) unit.body = initialUnitBody(unit) - if (settings.Yrangepos && !reporter.hasErrors) - validatePositions(unit.body) - if (settings.Ymemberpos.isSetByUser) new MemberPosReporter(unit) show (style = settings.Ymemberpos.value) } diff --git a/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala b/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala index 2e9477cf38c6..a0fbedc03924 100644 --- a/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala +++ b/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala @@ -220,7 +220,8 @@ trait ScalaSettings extends AbsScalaSettings val stopAfter = PhasesSetting ("-Ystop-after", "Stop after") withAbbreviation ("-stop") // backward compat val stopBefore = PhasesSetting ("-Ystop-before", "Stop before") val Yrangepos = BooleanSetting ("-Yrangepos", "Use range positions for syntax trees.") - val Ymemberpos = StringSetting ("-Yshow-member-pos", "output style", "Show start and end positions of members", "") withPostSetHook (_ => Yrangepos.value = true) + val Yvalidatepos = PhasesSetting ("-Yvalidate-pos", s"Validate positions after the given phases (implies ${Yrangepos.name})") withPostSetHook (_ => Yrangepos.value = true) + val Ymemberpos = StringSetting ("-Yshow-member-pos", "output style", s"Show start and end positions of members (implies ${Yrangepos.name})", "") withPostSetHook (_ => Yrangepos.value = true) val Yreifycopypaste = BooleanSetting ("-Yreify-copypaste", "Dump the reified trees in copypasteable representation.") val Ymacroexpand = ChoiceSetting ("-Ymacro-expand", "policy", "Control expansion of macros, useful for scaladoc and presentation compiler.", List(MacroExpand.Normal, MacroExpand.None, MacroExpand.Discard), MacroExpand.Normal) val Ymacronoexpand = BooleanSetting ("-Ymacro-no-expand", "Don't expand macros. Might be useful for scaladoc and presentation compiler, but will crash anything which uses macros and gets past typer.") withDeprecationMessage(s"Use ${Ymacroexpand.name}:${MacroExpand.None}") withPostSetHook(_ => Ymacroexpand.value = MacroExpand.None) diff --git a/src/compiler/scala/tools/nsc/typechecker/Analyzer.scala b/src/compiler/scala/tools/nsc/typechecker/Analyzer.scala index ccd414cc457d..5fc17c191477 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Analyzer.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Analyzer.scala @@ -102,7 +102,6 @@ trait Analyzer extends AnyRef try { val typer = newTyper(rootContext(unit)) unit.body = typer.typed(unit.body) - if (global.settings.Yrangepos && !global.reporter.hasErrors) global.validatePositions(unit.body) for (workItem <- unit.toCheck) workItem() if (settings.warnUnusedImport) warnUnusedImports(unit) diff --git a/src/reflect/scala/reflect/internal/Positions.scala b/src/reflect/scala/reflect/internal/Positions.scala index 1a1aa2e72160..b56762c42b37 100644 --- a/src/reflect/scala/reflect/internal/Positions.scala +++ b/src/reflect/scala/reflect/internal/Positions.scala @@ -105,7 +105,7 @@ trait Positions extends api.Positions { self: SymbolTable => def validate(tree: Tree, encltree: Tree): Unit = { if (!tree.isEmpty && tree.canHaveAttrs) { - if (settings.Yposdebug && (settings.verbose || settings.Yrangepos)) + if (settings.Yposdebug && settings.verbose) inform("[%10s] %s".format("validate", treeStatus(tree, encltree))) if (!tree.pos.isDefined) @@ -143,8 +143,7 @@ trait Positions extends api.Positions { self: SymbolTable => } } - if (!isPastTyper) - validate(tree, tree) + validate(tree, tree) } def solidDescendants(tree: Tree): List[Tree] = From 5af85b5ce690d62bab90f8738c3fe1d0d2e0e41f Mon Sep 17 00:00:00 2001 From: Danila Matveev Date: Tue, 27 Feb 2018 11:28:10 +0300 Subject: [PATCH 009/143] [nomerge] Several entries with the same key in mutable.HashMap - Add HashMap test to check scala/collection-strawman#382 / scala/bug#10703 - Clean code. - Repeat search of key after evaluating default value. - Fix code style. Cherry pick of 0c30c04a6920f7f7daa08df8ee22349f12686906 --- src/library/scala/collection/mutable/HashMap.scala | 13 ++++++++++--- .../scala/collection/mutable/HashMapTest.scala | 13 +++++++++++++ 2 files changed, 23 insertions(+), 3 deletions(-) diff --git a/src/library/scala/collection/mutable/HashMap.scala b/src/library/scala/collection/mutable/HashMap.scala index 2391080658e3..c32e9d2f7d35 100644 --- a/src/library/scala/collection/mutable/HashMap.scala +++ b/src/library/scala/collection/mutable/HashMap.scala @@ -75,18 +75,25 @@ extends AbstractMap[A, B] override def getOrElseUpdate(key: A, defaultValue: => B): B = { val hash = elemHashCode(key) val i = index(hash) - val entry = findEntry(key, i) - if (entry != null) entry.value + val firstEntry = findEntry(key, i) + if (firstEntry != null) firstEntry.value else { val table0 = table val default = defaultValue // Avoid recomputing index if the `defaultValue()` hasn't triggered // a table resize. val newEntryIndex = if (table0 eq table) i else index(hash) - addEntry(createNewEntry(key, default), newEntryIndex) + val e = createNewEntry(key, default) + // Repeat search + // because evaluation of `default` can bring entry with `key` + val secondEntry = findEntry(key, newEntryIndex) + if (secondEntry == null) addEntry0(e, newEntryIndex) + else secondEntry.value = default + default } } + /* inlined HashTable.findEntry0 to preserve its visibility */ private[this] def findEntry(key: A, h: Int): Entry = { var e = table(h).asInstanceOf[Entry] diff --git a/test/junit/scala/collection/mutable/HashMapTest.scala b/test/junit/scala/collection/mutable/HashMapTest.scala index cc1979a9200c..426cc8de55bb 100644 --- a/test/junit/scala/collection/mutable/HashMapTest.scala +++ b/test/junit/scala/collection/mutable/HashMapTest.scala @@ -35,4 +35,17 @@ class HashMapTest { hm.put(0, 0) hm.getOrElseUpdate(0, throw new AssertionError()) } + + @Test + def getOrElseUpdate_keyIdempotence_t10703(): Unit = { + val map = mutable.HashMap[String, String]() + + val key = "key" + map.getOrElseUpdate(key, { + map.getOrElseUpdate(key, "value1") + "value2" + }) + + assertEquals(List((key, "value2")), map.toList) + } } From e5d311ed388742deca02c5cafc827f6a53e84b87 Mon Sep 17 00:00:00 2001 From: Som Snytt Date: Sat, 23 Jun 2018 03:10:01 -0700 Subject: [PATCH 010/143] X marks the terse mode failure Build stringly test report and delay echoing it in terse mode until summary time. --- .../scala/tools/partest/ConsoleLog.scala | 9 +- .../tools/partest/nest/AbstractRunner.scala | 82 +++++++++++-------- 2 files changed, 55 insertions(+), 36 deletions(-) diff --git a/src/partest/scala/tools/partest/ConsoleLog.scala b/src/partest/scala/tools/partest/ConsoleLog.scala index 1824b2db2786..d2c9f043fe56 100644 --- a/src/partest/scala/tools/partest/ConsoleLog.scala +++ b/src/partest/scala/tools/partest/ConsoleLog.scala @@ -48,13 +48,14 @@ class ConsoleLog(colorEnabled: Boolean) { def echoMixed(msg: String) = echo(bold(yellow(msg))) def echoWarning(msg: String) = echo(bold(red(msg))) - def printDot(): Unit = { + def printDot(): Unit = printProgress(".") + def printEx(): Unit = printProgress(_failure + "X" + _default) + private def printProgress(icon: String): Unit = if (dotCount >= DotWidth) { - outline("\n.") + outline("\n" + icon) dotCount = 1 } else { - outline(".") + outline(icon) dotCount += 1 } - } } diff --git a/src/partest/scala/tools/partest/nest/AbstractRunner.scala b/src/partest/scala/tools/partest/nest/AbstractRunner.scala index 637ca902b340..ec7390c1aac1 100644 --- a/src/partest/scala/tools/partest/nest/AbstractRunner.scala +++ b/src/partest/scala/tools/partest/nest/AbstractRunner.scala @@ -73,26 +73,32 @@ class AbstractRunner(val config: RunnerSpec.Config, protected final val testSour f"$word $testNumber - $testIdent%-40s$reasonString$durationString" } - def reportTest(state: TestState, info: TestInfo, durationMs: Long, diffOnFail: Boolean, logOnFail: Boolean): Unit = { - if (terse && state.isOk) printDot() - else { - echo(statusLine(state, durationMs)) - if (!state.isOk) { - def showLog() = if (info.logFile.canRead) { - echo(bold(cyan(s"##### Log file '${info.logFile}' from failed test #####\n"))) - echo(info.logFile.fileContents) - } + def reportTest(state: TestState, info: TestInfo, durationMs: Long, diffOnFail: Boolean, logOnFail: Boolean): List[String] = { + def errInfo: List[String] = { + def showLog() = + if (info.logFile.canRead) List ( + bold(cyan(s"##### Log file '${info.logFile}' from failed test #####\n")), + info.logFile.fileContents + ) else Nil + val diffed = if (diffOnFail) { val differ = bold(red("% ")) + "diff " - val diffed = state.transcript find (_ startsWith differ) - diffed match { - case Some(diff) => echo(diff) + state.transcript.find(_ startsWith differ) match { + case Some(diff) => diff :: Nil case None if !logOnFail && !verbose => showLog() - case _ => () + case _ => Nil } - } - if (logOnFail) showLog() - } + } else Nil + val logged = if (logOnFail) showLog() else Nil + diffed ::: logged + } + if (terse) { + if (state.isOk) { printDot() ; Nil } + else { printEx() ; statusLine(state, durationMs) :: errInfo } + } else { + echo(statusLine(state, durationMs)) + if (!state.isOk) errInfo.foreach(echo) + Nil } } @@ -244,6 +250,7 @@ class AbstractRunner(val config: RunnerSpec.Config, protected final val testSour passedTests ++= passed failedTests ++= failed if (failed.nonEmpty) { + if (terse) failed.foreach(_.transcript.foreach(echo)) comment(passFailString(passed.size, failed.size, 0) + " in " + kind) } echo("") @@ -297,9 +304,15 @@ class AbstractRunner(val config: RunnerSpec.Config, protected final val testSour case t: Throwable => throw new RuntimeException(s"Error running $testFile", t) } stopwatchDuration = Some(durationMs) - reportTest(state, runner, durationMs, diffOnFail = config.optShowDiff || onlyIndividualTests , logOnFail = config.optShowLog || onlyIndividualTests) + val more = reportTest(state, runner, durationMs, diffOnFail = config.optShowDiff || onlyIndividualTests , logOnFail = config.optShowLog || onlyIndividualTests) runner.cleanup() - state + if (more.isEmpty) state + else { + state match { + case f: TestState.Fail => f.copy(transcript = more.toArray) + case _ => state + } + } } val end = System.nanoTime() val durationMs = stopwatchDuration.getOrElse(TimeUnit.NANOSECONDS.toMillis(end - start)) @@ -313,19 +326,8 @@ class AbstractRunner(val config: RunnerSpec.Config, protected final val testSour val futures = kindFiles map (f => pool submit callable(runTest(f.getAbsoluteFile))) pool.shutdown() - Try (pool.awaitTermination(PartestDefaults.waitTime) { - throw TimeoutException(PartestDefaults.waitTime) - }) match { - case Success(_) => futures map (_.get) - case Failure(e) => - e match { - case TimeoutException(d) => - warning("Thread pool timeout elapsed before all tests were complete!") - case ie: InterruptedException => - warning("Thread pool was interrupted") - ie.printStackTrace() - } - pool.shutdownNow() // little point in continuing + def aborted = { + pool.shutdownNow() // little point in continuing // try to get as many completions as possible, in case someone cares val results = for (f <- futures) yield { try { @@ -334,7 +336,23 @@ class AbstractRunner(val config: RunnerSpec.Config, protected final val testSour case _: Throwable => None } } - results.flatten + results.flatten + } + Try (pool.awaitTermination(PartestDefaults.waitTime) { + throw TimeoutException(PartestDefaults.waitTime) + }) match { + case Success(_) => futures.map(_.get) + case Failure(TimeoutException(e)) => + warning("Thread pool timeout elapsed before all tests were complete!") + aborted + case Failure(ie: InterruptedException) => + warning("Thread pool was interrupted") + ie.printStackTrace() + aborted + case Failure(e) => + warning("Unexpected failure") + e.printStackTrace() + aborted } } } From dc0b8b201553069ec9d5c2f3a1cb061f7e8402b4 Mon Sep 17 00:00:00 2001 From: Harrison Houghton Date: Sat, 23 Jun 2018 16:30:31 -0400 Subject: [PATCH 011/143] Minor optimizations in implicit search. - cache `settings.isScala213` - use `mutable.Set#add` rather than `contains` followed by `+=` - match on `_ :: _` rather than `nonEmpty` followed by `head` - use `mutable.Map#update` rather than `+=` (avoiding a tuple alloc) --- .../tools/nsc/typechecker/Implicits.scala | 24 +++++++++---------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/src/compiler/scala/tools/nsc/typechecker/Implicits.scala b/src/compiler/scala/tools/nsc/typechecker/Implicits.scala index f167a653ffb9..4db10827f248 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Implicits.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Implicits.scala @@ -1071,17 +1071,20 @@ trait Implicits { * bound, the implicits infos which are members of these companion objects. */ private def companionImplicitMap(tp: Type): InfoMap = { + val isScala213 = settings.isScala213 /* Populate implicit info map by traversing all parts of type `tp`. * Parameters as for `getParts`. */ - def getClassParts(tp: Type)(implicit infoMap: InfoMap, seen: mutable.Set[Type], pending: Set[Symbol]) = tp match { + def getClassParts(tp: Type)(implicit infoMap: InfoMap, seen: mutable.HashSet[Type], pending: Set[Symbol]) = tp match { case TypeRef(pre, sym, args) => infoMap get sym match { case Some(infos1) => - if (infos1.nonEmpty && !(pre =:= infos1.head.pre.prefix)) { - log(s"Ignoring implicit members of $pre#$sym as it is also visible via another prefix: ${infos1.head.pre.prefix}") - infoMap(sym) = List() // ambiguous prefix - ignore implicit members + infos1 match { + case head :: _ if !(pre =:= head.pre.prefix) => + log(s"Ignoring implicit members of $pre#$sym as it is also visible via another prefix: ${infos1.head.pre.prefix}") + infoMap(sym) = List() // ambiguous prefix - ignore implicit members + case _ => } case None => if (pre.isStable && !pre.typeSymbol.isExistentiallyBound) { @@ -1090,7 +1093,7 @@ trait Implicits { else singleType(pre, companionSymbolOf(sym, context)) val infos = pre1.implicitMembers.iterator.map(mem => new ImplicitInfo(mem.name, pre1, mem)).toList if (infos.nonEmpty) - infoMap += (sym -> infos) + infoMap(sym) = infos } val bts = tp.baseTypeSeq var i = 1 @@ -1110,14 +1113,11 @@ trait Implicits { * @param pending The set of static symbols for which we are currently trying to collect their parts * in order to cache them in infoMapCache */ - def getParts(tp: Type)(implicit infoMap: InfoMap, seen: mutable.Set[Type], pending: Set[Symbol]) { - if (seen(tp)) - return - seen += tp - tp match { + def getParts(tp: Type)(implicit infoMap: InfoMap, seen: mutable.HashSet[Type], pending: Set[Symbol]) { + if (seen add tp) tp match { case TypeRef(pre, sym, args) => if (sym.isClass && !sym.isRoot && - (settings.isScala213 || !sym.isAnonOrRefinementClass)) { + (isScala213 || !sym.isAnonOrRefinementClass)) { if (sym.isStatic && !(pending contains sym)) infoMap ++= { infoMapCache get sym match { @@ -1140,7 +1140,7 @@ trait Implicits { // - if `T` is an abstract type, the parts of its upper bound; getParts(tp.bounds.hi) - if(settings.isScala213) { + if (isScala213) { // - if `T` is a parameterized type `S[T1,…,Tn]`, the union of the parts of `S` and `T1,…,Tn` args foreach getParts From 9ae3932dea4a3e88104c6c4f04b3d5789dfcd656 Mon Sep 17 00:00:00 2001 From: Matthew de Detrich Date: Mon, 25 Jun 2018 00:10:22 +0200 Subject: [PATCH 012/143] Add LinkedMap/VectorMap --- .../collection/immutable/LinkedMap.scala | 209 ++++++++++++++++++ .../scala/collection/immutable/ListMap.scala | 1 + .../collection/immutable/VectorMap.scala | 155 +++++++++++++ .../immutable/LinkedMapBenchmark.scala | 29 +++ test/scalacheck/LinkedMap.scala | 27 +++ 5 files changed, 421 insertions(+) create mode 100644 src/library/scala/collection/immutable/LinkedMap.scala create mode 100644 src/library/scala/collection/immutable/VectorMap.scala create mode 100644 test/benchmarks/src/main/scala/scala/collection/immutable/LinkedMapBenchmark.scala create mode 100644 test/scalacheck/LinkedMap.scala diff --git a/src/library/scala/collection/immutable/LinkedMap.scala b/src/library/scala/collection/immutable/LinkedMap.scala new file mode 100644 index 000000000000..f3c2e0966cb2 --- /dev/null +++ b/src/library/scala/collection/immutable/LinkedMap.scala @@ -0,0 +1,209 @@ +package scala +package collection +package immutable + +import java.io.{ObjectInputStream, ObjectOutputStream} + +import scala.collection.mutable.{Builder, ImmutableBuilder} + +/** + * A generic trait for ordered immutable maps. Concrete classes have to provide + * functionality for the abstract methods in `LinkedMap`: + * + * @tparam A + * @tparam B + */ + +trait LinkedMap[K, +V] + extends Map[K, V] + with Iterable[(K, V)] + with MapOps[K, V, LinkedMap, LinkedMap[K, V]] + with Equals + +object LinkedMap extends MapFactory[LinkedMap] { + def empty[K, V]: LinkedMap[K, V] = EmptyLinkedMap.asInstanceOf[LinkedMap[K, V]] + + def from[K, V](it: collection.IterableOnce[(K, V)]): LinkedMap[K, V] = + it match { + case vm: LinkedMap[K, V] => vm + case _ => (newBuilder[K, V] ++= it).result() + } + + def newBuilder[K, V]: Builder[(K, V), LinkedMap[K, V]] = + new ImmutableBuilder[(K, V), LinkedMap[K, V]](empty) { + def addOne(elem: (K, V)): this.type = { elems = elems + elem; this } + } + + @SerialVersionUID(3L) + private object EmptyLinkedMap extends LinkedMap[Any, Nothing] { + override def size: Int = 0 + override def knownSize: Int = 0 + override def apply(key: Any) = throw new NoSuchElementException("key not found: " + key) + override def contains(key: Any) = false + def get(key: Any): Option[Nothing] = None + override def getOrElse [V1](key: Any, default: => V1): V1 = default + def iterator: Iterator[(Any, Nothing)] = Iterator.empty + def updated [V1] (key: Any, value: V1): LinkedMap[Any, V1] = new LinkedMap1(key, value) + def remove(key: Any): LinkedMap[Any, Nothing] = this + } + + @SerialVersionUID(3L) + final class LinkedMap1[K, +V](key1: K, value1: V) extends LinkedMap[K,V] with Serializable { + override def size: Int = 1 + override def knownSize: Int = 1 + override def apply(key: K) = if (key == key1) value1 else throw new NoSuchElementException("key not found: " + key) + override def contains(key: K) = key == key1 + def get(key: K): Option[V] = + if (key == key1) Some(value1) else None + override def getOrElse [V1 >: V](key: K, default: => V1): V1 = + if (key == key1) value1 else default + def iterator = Iterator.single((key1, value1)) + def updated[V1 >: V](key: K, value: V1): LinkedMap[K, V1] = + if (key == key1) new LinkedMap1(key1, value) + else new LinkedMap2(key1, value1, key, value) + def remove(key: K): LinkedMap[K, V] = + if (key == key1) LinkedMap.empty else this + override def foreach[U](f: ((K, V)) => U): Unit = { + f((key1, value1)) + } + } + + @SerialVersionUID(3L) + final class LinkedMap2[K, +V](key1: K, value1: V, key2: K, value2: V) extends LinkedMap[K,V] with Serializable { + override def size: Int = 2 + override def knownSize: Int = 2 + override def apply(key: K) = + if (key == key1) value1 + else if (key == key2) value2 + else throw new NoSuchElementException("key not found: " + key) + override def contains(key: K) = (key == key1) || (key == key2) + def get(key: K): Option[V] = + if (key == key1) Some(value1) + else if (key == key2) Some(value2) + else None + override def getOrElse [V1 >: V](key: K, default: => V1): V1 = + if (key == key1) value1 + else if (key == key2) value2 + else default + def iterator = ((key1, value1) :: (key2, value2) :: Nil).iterator + def updated[V1 >: V](key: K, value: V1): LinkedMap[K, V1] = + if (key == key1) new LinkedMap2(key1, value, key2, value2) + else if (key == key2) new LinkedMap2(key1, value1, key2, value) + else new LinkedMap3(key1, value1, key2, value2, key, value) + def remove(key: K): LinkedMap[K, V] = + if (key == key1) new LinkedMap1(key2, value2) + else if (key == key2) new LinkedMap1(key1, value1) + else this + override def foreach[U](f: ((K, V)) => U): Unit = { + f((key1, value1)); f((key2, value2)) + } + } + + @SerialVersionUID(3L) + class LinkedMap3[K, +V](key1: K, value1: V, key2: K, value2: V, key3: K, value3: V) extends LinkedMap[K,V] with Serializable { + override def size: Int = 3 + override def knownSize: Int = 3 + override def apply(key: K) = + if (key == key1) value1 + else if (key == key2) value2 + else if (key == key3) value3 + else throw new NoSuchElementException("key not found: " + key) + override def contains(key: K) = (key == key1) || (key == key2) || (key == key3) + def get(key: K): Option[V] = + if (key == key1) Some(value1) + else if (key == key2) Some(value2) + else if (key == key3) Some(value3) + else None + override def getOrElse [V1 >: V](key: K, default: => V1): V1 = + if (key == key1) value1 + else if (key == key2) value2 + else if (key == key3) value3 + else default + def iterator = ((key1, value1) :: (key2, value2) :: (key3, value3) :: Nil).iterator + def updated[V1 >: V](key: K, value: V1): LinkedMap[K, V1] = + if (key == key1) new LinkedMap3(key1, value, key2, value2, key3, value3) + else if (key == key2) new LinkedMap3(key1, value1, key2, value, key3, value3) + else if (key == key3) new LinkedMap3(key1, value1, key2, value2, key3, value) + else new LinkedMap4(key1, value1, key2, value2, key3, value3, key, value) + def remove(key: K): LinkedMap[K, V] = + if (key == key1) new LinkedMap2(key2, value2, key3, value3) + else if (key == key2) new LinkedMap2(key1, value1, key3, value3) + else if (key == key3) new LinkedMap2(key1, value1, key2, value2) + else this + override def foreach[U](f: ((K, V)) => U): Unit = { + f((key1, value1)); f((key2, value2)); f((key3, value3)) + } + } + + @SerialVersionUID(3L) + final class LinkedMap4[K, +V](key1: K, value1: V, key2: K, value2: V, key3: K, value3: V, key4: K, value4: V) extends LinkedMap[K,V] with Serializable { + override def size: Int = 4 + override def knownSize: Int = 4 + override def apply(key: K) = + if (key == key1) value1 + else if (key == key2) value2 + else if (key == key3) value3 + else if (key == key4) value4 + else throw new NoSuchElementException("key not found: " + key) + override def contains(key: K) = (key == key1) || (key == key2) || (key == key3) || (key == key4) + def get(key: K): Option[V] = + if (key == key1) Some(value1) + else if (key == key2) Some(value2) + else if (key == key3) Some(value3) + else if (key == key4) Some(value4) + else None + override def getOrElse [V1 >: V](key: K, default: => V1): V1 = + if (key == key1) value1 + else if (key == key2) value2 + else if (key == key3) value3 + else if (key == key4) value4 + else default + def iterator = ((key1, value1) :: (key2, value2) :: (key3, value3) :: (key4, value4) :: Nil).iterator + def updated[V1 >: V](key: K, value: V1): LinkedMap[K, V1] = + if (key == key1) new LinkedMap4(key1, value, key2, value2, key3, value3, key4, value4) + else if (key == key2) new LinkedMap4(key1, value1, key2, value, key3, value3, key4, value4) + else if (key == key3) new LinkedMap4(key1, value1, key2, value2, key3, value, key4, value4) + else if (key == key4) new LinkedMap4(key1, value1, key2, value2, key3, value3, key4, value) + else { + // Directly create the elements for performance reasons + val fields = Vector(key1, key2, key3, key4, key) + val underlying = if (useBaseline) + HashMap( + (key1, (0, value1)), + (key2, (1, value2)), + (key3, (2, value3)), + (key4, (3, value4)), + (key, (4, value)) + ) + else + ChampHashMap( + (key1, (0, value1)), + (key2, (1, value2)), + (key3, (2, value3)), + (key4, (3, value4)), + (key, (4, value)) + ) + new VectorMap(fields, underlying) + } + def remove(key: K): LinkedMap[K, V] = + if (key == key1) new LinkedMap3(key2, value2, key3, value3, key4, value4) + else if (key == key2) new LinkedMap3(key1, value1, key3, value3, key4, value4) + else if (key == key3) new LinkedMap3(key1, value1, key2, value2, key4, value4) + else if (key == key4) new LinkedMap3(key1, value1, key2, value2, key3, value3) + else this + override def foreach[U](f: ((K, V)) => U): Unit = { + f((key1, value1)); f((key2, value2)); f((key3, value3)); f((key4, value4)) + } + } + + // getenv not getProperty for Scala.js friendliness. + // TODO remove before 2.13.0-RC1? see scala/collection-strawman#572 + private final val useBaseline: Boolean = + System.getenv("SCALA_COLLECTION_IMMUTABLE_USE_BASELINE") == "true" + + // scalac generates a `readReplace` method to discard the deserialized state (see https://github.com/scala/bug/issues/10412). + // This prevents it from serializing it in the first place: + private[this] def writeObject(out: ObjectOutputStream): Unit = () + private[this] def readObject(in: ObjectInputStream): Unit = () + +} diff --git a/src/library/scala/collection/immutable/ListMap.scala b/src/library/scala/collection/immutable/ListMap.scala index bf13677a3afd..3d11a58f604a 100644 --- a/src/library/scala/collection/immutable/ListMap.scala +++ b/src/library/scala/collection/immutable/ListMap.scala @@ -43,6 +43,7 @@ import scala.collection.mutable.{Builder, ImmutableBuilder} */ sealed class ListMap[K, +V] extends AbstractMap[K, V] + with LinkedMap[K, V] with MapOps[K, V, ListMap, ListMap[K, V]] with StrictOptimizedIterableOps[(K, V), Iterable, ListMap[K, V]] { diff --git a/src/library/scala/collection/immutable/VectorMap.scala b/src/library/scala/collection/immutable/VectorMap.scala new file mode 100644 index 000000000000..5d898517229b --- /dev/null +++ b/src/library/scala/collection/immutable/VectorMap.scala @@ -0,0 +1,155 @@ +package scala +package collection +package immutable + +import java.io.{ObjectInputStream, ObjectOutputStream} + +import scala.collection.mutable.{Builder, ImmutableBuilder} +import scala.annotation.unchecked.{uncheckedVariance => uV} +import scala.collection.immutable.Map.useBaseline + +/** This class implements immutable maps using a vector/map-based data structure, which preserves insertion order. + * + * Unlike `ListMap`, `VectorMap` has amortized effectively constant lookup at the expense + * of using extra memory and generally lower performance for other operations + * + * @tparam K the type of the keys contained in this vector map. + * @tparam V the type of the values associated with the keys in this vector map. + * + * @author Matthew de Detrich + * @version 2.13 + * @since 2.13 + * @define coll immutable vector map + * @define Coll `immutable.VectorMap` + */ +final class VectorMap[K, +V] private[immutable] ( + val fields: Vector[K], + val underlying: Map[K, (Int, V)]) + extends AbstractMap[K, V] + with LinkedMap[K, V] + with MapOps[K, V, VectorMap, VectorMap[K, V]] + with StrictOptimizedIterableOps[(K, V), Iterable, VectorMap[K, V]] { + + override protected[this] def className: String = "VectorMap" + + override def updated[V1 >: V](key: K, value: V1): VectorMap[K, V1] = { + if (underlying.get(key).isDefined) { + val oldKey = underlying(key)._1 + new VectorMap(fields, + underlying.updated(key, (oldKey, value.asInstanceOf[V]))) + } else { + new VectorMap( + fields :+ key, + underlying.updated(key, (fields.length + 1, value.asInstanceOf[V]))) + } + } + + override def withDefault[V1 >: V](d: K => V1): Map.WithDefault[K, V1] = + new Map.WithDefault(this, d) + + override def withDefaultValue[V1 >: V](d: V1): Map.WithDefault[K, V1] = new Map.WithDefault[K, V1](this, _ => d) + + override def iterator: Iterator[(K, V)] = new Iterator[(K, V)] { + private val fieldsIterator = fields.iterator + + override def hasNext: Boolean = fieldsIterator.hasNext + + override def next(): (K, V) = { + val field = fieldsIterator.next() + (field, underlying(field)._2) + } + } + + override def get(key: K): Option[V] = underlying.get(key) match { + case Some(v) => Some(v._2) + case None => None + } + + override def remove(key: K): VectorMap[K, V] = { + underlying.get(key) match { + case Some((index, _)) => + new VectorMap(fields.patch(index, Nil, 1), underlying - key) + case _ => + this + } + } + + override def mapFactory: MapFactory[VectorMap] = VectorMap + + override def size: Int = fields.size + + override def knownSize: Int = fields.size + + override def isEmpty: Boolean = fields.isEmpty + + override final def contains(key: K): Boolean = underlying.contains(key) + + override def head: (K, V) = iterator.next() + + override def last: (K, V) = { + val last = fields.last + (last, underlying(last)._2) + } + + override def lastOption: Option[(K, V)] = { + fields.lastOption match { + case Some(last) => Some(last, underlying(last)._2) + case None => None + } + } + + override def tail: VectorMap[K, V] = { + val tail = fields.last + + new VectorMap(fields.slice(1, fields.size), underlying.remove(tail)) + } + + override def init: VectorMap[K, V] = { + val head = fields.head + + new VectorMap(fields.slice(1, fields.size - 0), underlying.remove(head)) + } + + // Only care about content, not ordering for equality + override def equals(that: Any): Boolean = + that match { + case vmap: VectorMap[K, V] => + underlying == vmap.underlying + case _ => super.equals(that) + } + + override def foreach[U](f: ((K, V)) => U): Unit = iterator.foreach(f) + + override def keys: Iterable[K] = fields.toIterable + + override def values: Iterable[V] = new Iterable[V] { + override def iterator: Iterator[V] = fields.iterator.map(underlying(_)._2) + } +} + +object VectorMap extends MapFactory[VectorMap] { + + def empty[K, V]: VectorMap[K, V] = + new VectorMap[K, V](Vector.empty[K], + if (VectorMap.useBaseline) + HashMap.empty[K, (Int, V)] + else + ChampHashMap.empty[K, (Int, V)] + ) + + def from[K, V](it: collection.IterableOnce[(K, V)]): VectorMap[K, V] = + it match { + case vm: VectorMap[K, V] => vm + case _ => (newBuilder[K, V] ++= it).result() + } + + def newBuilder[K, V]: Builder[(K, V), VectorMap[K, V]] = + new ImmutableBuilder[(K, V), VectorMap[K, V]](empty) { + def addOne(elem: (K, V)): this.type = { elems = elems + elem; this } + } + + // getenv not getProperty for Scala.js friendliness. + // TODO remove before 2.13.0-RC1? see scala/collection-strawman#572 + private final val useBaseline: Boolean = + System.getenv("SCALA_COLLECTION_IMMUTABLE_USE_BASELINE") == "true" +} diff --git a/test/benchmarks/src/main/scala/scala/collection/immutable/LinkedMapBenchmark.scala b/test/benchmarks/src/main/scala/scala/collection/immutable/LinkedMapBenchmark.scala new file mode 100644 index 000000000000..4c7f495c4e1c --- /dev/null +++ b/test/benchmarks/src/main/scala/scala/collection/immutable/LinkedMapBenchmark.scala @@ -0,0 +1,29 @@ +package scala.collection.immutable + +import java.util.concurrent.TimeUnit + +import org.openjdk.jmh.annotations._ +import org.openjdk.jmh.infra._ + +@BenchmarkMode(Array(Mode.AverageTime)) +@Fork(2) +@Threads(1) +@Warmup(iterations = 10) +@Measurement(iterations = 10) +@OutputTimeUnit(TimeUnit.NANOSECONDS) +@State(Scope.Benchmark) +class LinkedMapBenchmark { + + var base: LinkedMap[String,String] = _ + + + @Setup(Level.Trial) def initKeys(): Unit = { + base = LinkedMap("a" -> "a", "b" -> "b", "c" -> "c", "d" -> "d") + } + + // immutable map is implemented as EmptyMap -> Map1 -> Map2 -> Map3 -> Map4 -> Hashmap + // add an extra entry to Map4 causes a lot of work, benchmark the transition + @Benchmark def map4AddElement(bh: Blackhole): Unit = { + bh.consume(base.updated("e", "e")) + } +} diff --git a/test/scalacheck/LinkedMap.scala b/test/scalacheck/LinkedMap.scala new file mode 100644 index 000000000000..e9ff39a565db --- /dev/null +++ b/test/scalacheck/LinkedMap.scala @@ -0,0 +1,27 @@ +import scala.collection.immutable.LinkedMap + +import org.scalacheck._ +import Arbitrary.arbitrary +import Prop._ +import Gen._ + +import scala.collection.mutable.ListBuffer + +object LinkedMapTest extends Properties("LinkedMap") { + + property("ordering") = forAll { (m: Map[Int, Int]) => + val list = m.toList + val lm = LinkedMap.from(list) + val iter = lm.iterator + iter.toList == list + } + + property("ordering append") = forAll(arbitrary[Map[Int,Int]] suchThat (_.size > 1)) + { (m: Map[Int, Int]) => + val list = m.toList + val first = list.init + val elem = list.last + val lm = LinkedMap.from(first) + (lm + elem).iterator.toList == first :+ elem + } +} From 8128fa790bd01833481999d077ccec99886bf0a5 Mon Sep 17 00:00:00 2001 From: NthPortal Date: Sat, 23 Jun 2018 17:22:43 -0400 Subject: [PATCH 013/143] bug#10747 Document thread-safety of Enumeration --- src/library/scala/Enumeration.scala | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/library/scala/Enumeration.scala b/src/library/scala/Enumeration.scala index 716d26164ea7..ab3fa18064c3 100644 --- a/src/library/scala/Enumeration.scala +++ b/src/library/scala/Enumeration.scala @@ -25,6 +25,11 @@ import scala.util.matching.Regex * `Value` type member of the enumeration (`Value` selected on the stable * identifier path of the enumeration instance). * + * Values SHOULD NOT be added to an enumeration after its construction; + * doing so makes the enumeration thread-unsafe. If values are added to an + * enumeration from multiple threads (in a non-synchronized fashion) after + * construction, the behavior of the enumeration is undefined. + * * @example {{{ * // Define a new enumeration with a type alias and work with the full set of enumerated values * object WeekDay extends Enumeration { From 5de2610bfe61aab86a00b23b11be6528f9647f87 Mon Sep 17 00:00:00 2001 From: Jason Zaugg Date: Mon, 25 Jun 2018 12:47:27 +1000 Subject: [PATCH 014/143] Augment HashMapBenchmark - Control whether to include negative lookups through a new parameter - Benchmark getOrElse - Control whether to include negative lookups through a new parameter - Benchmark getOrElse - Use Champ or the HashTrie impl based on the USE_BASELINE env var. - benchmark the mutable version. - Add a parameter to just use string keys to look at the efficiency without cooperative equality in play. --- .../immutable/HashMapBenchmark.scala | 30 +++++++++-- .../collection/mutable/HashMapBenchmark.scala | 51 ++++++++++++------- 2 files changed, 59 insertions(+), 22 deletions(-) diff --git a/test/benchmarks/src/main/scala/scala/collection/immutable/HashMapBenchmark.scala b/test/benchmarks/src/main/scala/scala/collection/immutable/HashMapBenchmark.scala index 134cd6879b39..1e9adf789ee1 100644 --- a/test/benchmarks/src/main/scala/scala/collection/immutable/HashMapBenchmark.scala +++ b/test/benchmarks/src/main/scala/scala/collection/immutable/HashMapBenchmark.scala @@ -16,31 +16,38 @@ import java.util.concurrent.TimeUnit class HashMapBenchmark { @Param(Array("10", "100", "1000")) var size: Int = _ + @Param(Array("true")) + var useMissingValues = true + @Param(Array("false")) + var stringsOnly = false var existingKeys: Array[Any] = _ var missingKeys: Array[Any] = _ @Setup(Level.Trial) def initKeys(): Unit = { existingKeys = (0 to size).map(i => (i % 4) match { + case _ if stringsOnly => i.toString case 0 => i.toString case 1 => i.toChar case 2 => i.toDouble case 3 => i.toInt }).toArray - missingKeys = (size to 2 * size).toArray + missingKeys = (size to 2 * size).toArray.map(_.toString) } - var map: collection.immutable.HashMap[Any, Any] = null + var map: collection.immutable.Map[Any, Any] = null @Setup(Level.Trial) def initialize = { - map = collection.immutable.HashMap(existingKeys.map(x => (x, x)) : _*) + map = collection.immutable.Map(existingKeys.map(x => (x, x)) : _*) } @Benchmark def contains(bh: Blackhole): Unit = { var i = 0; while (i < size) { bh.consume(map.contains(existingKeys(i))) - bh.consume(map.contains(missingKeys(i))) + if (useMissingValues) { + bh.consume(map.contains(missingKeys(i))) + } i += 1 } } @@ -49,7 +56,20 @@ class HashMapBenchmark { var i = 0; while (i < size) { bh.consume(map.get(existingKeys(i))) - bh.consume(map.get(missingKeys(i))) + if (useMissingValues) { + bh.consume(map.get(missingKeys(i))) + } + i += 1 + } + } + + @Benchmark def getOrElse(bh: Blackhole): Unit = { + var i = 0; + while (i < size) { + bh.consume(map.getOrElse(existingKeys(i), "")) + if (useMissingValues) { + bh.consume(map.getOrElse(missingKeys(i), "")) + } i += 1 } } diff --git a/test/benchmarks/src/main/scala/scala/collection/mutable/HashMapBenchmark.scala b/test/benchmarks/src/main/scala/scala/collection/mutable/HashMapBenchmark.scala index 3f01d154e934..d06e960aa6ad 100644 --- a/test/benchmarks/src/main/scala/scala/collection/mutable/HashMapBenchmark.scala +++ b/test/benchmarks/src/main/scala/scala/collection/mutable/HashMapBenchmark.scala @@ -6,8 +6,6 @@ import org.openjdk.jmh.runner.IterationType import benchmark._ import java.util.concurrent.TimeUnit -import scala.collection.mutable - @BenchmarkMode(Array(Mode.AverageTime)) @Fork(2) @Threads(1) @@ -18,31 +16,38 @@ import scala.collection.mutable class HashMapBenchmark { @Param(Array("10", "100", "1000")) var size: Int = _ + @Param(Array("true")) + var useMissingValues = true + @Param(Array("false")) + var stringsOnly = false var existingKeys: Array[Any] = _ var missingKeys: Array[Any] = _ @Setup(Level.Trial) def initKeys(): Unit = { existingKeys = (0 to size).map(i => (i % 4) match { + case _ if stringsOnly => i.toString case 0 => i.toString case 1 => i.toChar case 2 => i.toDouble case 3 => i.toInt }).toArray - missingKeys = (size to 2 * size).toArray + missingKeys = (size to 2 * size).toArray.map(_.toString) } - var map = new mutable.HashMap[Any, Any] - - @Setup(Level.Invocation) def initializeMutable = existingKeys.foreach(v => map.put(v, v)) + var map: collection.mutable.HashMap[Any, Any] = null - @TearDown(Level.Invocation) def tearDown = map.clear() + @Setup(Level.Trial) def initialize = { + map = collection.mutable.HashMap(existingKeys.map(x => (x, x)) : _*) + } - @Benchmark def getOrElseUpdate(bh: Blackhole): Unit = { + @Benchmark def contains(bh: Blackhole): Unit = { var i = 0; while (i < size) { - bh.consume(map.getOrElseUpdate(existingKeys(i), -1)) - bh.consume(map.getOrElseUpdate(missingKeys(i), -1)) + bh.consume(map.contains(existingKeys(i))) + if (useMissingValues) { + bh.consume(map.contains(missingKeys(i))) + } i += 1 } } @@ -50,21 +55,33 @@ class HashMapBenchmark { @Benchmark def get(bh: Blackhole): Unit = { var i = 0; while (i < size) { - bh.consume(map.get(existingKeys(i), -1)) - bh.consume(map.get(missingKeys(i), -1)) + bh.consume(map.get(existingKeys(i))) + if (useMissingValues) { + bh.consume(map.get(missingKeys(i))) + } i += 1 } } - @Benchmark def put(bh: Blackhole): Any = { - var map = new mutable.HashMap[Any, Any] - + @Benchmark def getOrElse(bh: Blackhole): Unit = { var i = 0; while (i < size) { - map.put(existingKeys(i), i) + bh.consume(map.getOrElse(existingKeys(i), "")) + if (useMissingValues) { + bh.consume(map.getOrElse(missingKeys(i), "")) + } i += 1 } + } - map + @Benchmark def getOrElseUpdate(bh: Blackhole): Unit = { + var i = 0; + while (i < size) { + bh.consume(map.getOrElseUpdate(existingKeys(i), "")) + if (useMissingValues) { + bh.consume(map.getOrElse(missingKeys(i), "")) + } + i += 1 + } } } From a53a8d85e236217561158c9c8c39096f8ac2da11 Mon Sep 17 00:00:00 2001 From: Matthew de Detrich Date: Mon, 25 Jun 2018 23:19:18 +0200 Subject: [PATCH 015/143] Apply additional changes --- .../collection/immutable/LinkedMap.scala | 23 ++++++----- .../collection/immutable/VectorMap.scala | 39 ++++++++----------- 2 files changed, 31 insertions(+), 31 deletions(-) diff --git a/src/library/scala/collection/immutable/LinkedMap.scala b/src/library/scala/collection/immutable/LinkedMap.scala index f3c2e0966cb2..d3c77bd2cbf3 100644 --- a/src/library/scala/collection/immutable/LinkedMap.scala +++ b/src/library/scala/collection/immutable/LinkedMap.scala @@ -8,17 +8,24 @@ import scala.collection.mutable.{Builder, ImmutableBuilder} /** * A generic trait for ordered immutable maps. Concrete classes have to provide - * functionality for the abstract methods in `LinkedMap`: + * functionality for the abstract methods in `LinkedMap`. * - * @tparam A - * @tparam B + * Note that when checking for equality [[LinkedMap]] does not take into account + * ordering. + * + * @tparam K the type of the keys contained in this linked map. + * @tparam V the type of the values associated with the keys in this linked map. + * + * @author Matthew de Detrich + * @version 2.13 + * @since 2.13 + * @define coll immutable linked map + * @define Coll `immutable.LinkedMap` */ trait LinkedMap[K, +V] - extends Map[K, V] - with Iterable[(K, V)] + extends AbstractMap[K, V] with MapOps[K, V, LinkedMap, LinkedMap[K, V]] - with Equals object LinkedMap extends MapFactory[LinkedMap] { def empty[K, V]: LinkedMap[K, V] = EmptyLinkedMap.asInstanceOf[LinkedMap[K, V]] @@ -30,9 +37,7 @@ object LinkedMap extends MapFactory[LinkedMap] { } def newBuilder[K, V]: Builder[(K, V), LinkedMap[K, V]] = - new ImmutableBuilder[(K, V), LinkedMap[K, V]](empty) { - def addOne(elem: (K, V)): this.type = { elems = elems + elem; this } - } + new MapFactory.Delegate[LinkedMap](VectorMap).newBuilder @SerialVersionUID(3L) private object EmptyLinkedMap extends LinkedMap[Any, Nothing] { diff --git a/src/library/scala/collection/immutable/VectorMap.scala b/src/library/scala/collection/immutable/VectorMap.scala index 5d898517229b..c3993e1446c7 100644 --- a/src/library/scala/collection/immutable/VectorMap.scala +++ b/src/library/scala/collection/immutable/VectorMap.scala @@ -23,8 +23,8 @@ import scala.collection.immutable.Map.useBaseline * @define Coll `immutable.VectorMap` */ final class VectorMap[K, +V] private[immutable] ( - val fields: Vector[K], - val underlying: Map[K, (Int, V)]) + private val fields: Vector[K], + private val underlying: Map[K, (Int, V)]) extends AbstractMap[K, V] with LinkedMap[K, V] with MapOps[K, V, VectorMap, VectorMap[K, V]] @@ -32,15 +32,15 @@ final class VectorMap[K, +V] private[immutable] ( override protected[this] def className: String = "VectorMap" - override def updated[V1 >: V](key: K, value: V1): VectorMap[K, V1] = { - if (underlying.get(key).isDefined) { - val oldKey = underlying(key)._1 - new VectorMap(fields, - underlying.updated(key, (oldKey, value.asInstanceOf[V]))) - } else { - new VectorMap( - fields :+ key, - underlying.updated(key, (fields.length + 1, value.asInstanceOf[V]))) + def updated[V1 >: V](key: K, value: V1): VectorMap[K, V1] = { + underlying.get(key) match { + case Some(oldIndexWithValue) => + new VectorMap(fields, + underlying.updated(key, (oldIndexWithValue._1, value))) + case None => + new VectorMap( + fields :+ key, + underlying.updated(key, (fields.length + 1, value))) } } @@ -49,7 +49,7 @@ final class VectorMap[K, +V] private[immutable] ( override def withDefaultValue[V1 >: V](d: V1): Map.WithDefault[K, V1] = new Map.WithDefault[K, V1](this, _ => d) - override def iterator: Iterator[(K, V)] = new Iterator[(K, V)] { + def iterator: Iterator[(K, V)] = new Iterator[(K, V)] { private val fieldsIterator = fields.iterator override def hasNext: Boolean = fieldsIterator.hasNext @@ -60,12 +60,12 @@ final class VectorMap[K, +V] private[immutable] ( } } - override def get(key: K): Option[V] = underlying.get(key) match { + def get(key: K): Option[V] = underlying.get(key) match { case Some(v) => Some(v._2) case None => None } - override def remove(key: K): VectorMap[K, V] = { + def remove(key: K): VectorMap[K, V] = { underlying.get(key) match { case Some((index, _)) => new VectorMap(fields.patch(index, Nil, 1), underlying - key) @@ -99,22 +99,17 @@ final class VectorMap[K, +V] private[immutable] ( } override def tail: VectorMap[K, V] = { - val tail = fields.last - - new VectorMap(fields.slice(1, fields.size), underlying.remove(tail)) + new VectorMap(fields.tail, underlying.remove(fields.last)) } override def init: VectorMap[K, V] = { - val head = fields.head - - new VectorMap(fields.slice(1, fields.size - 0), underlying.remove(head)) + new VectorMap(fields.init, underlying.remove(fields.head)) } // Only care about content, not ordering for equality override def equals(that: Any): Boolean = that match { - case vmap: VectorMap[K, V] => - underlying == vmap.underlying + case vmap: VectorMap[_, _] => underlying == vmap.underlying case _ => super.equals(that) } From cd51e2be66faaa155b5562ae1d4b9416507e8c62 Mon Sep 17 00:00:00 2001 From: Jason Zaugg Date: Thu, 21 Jun 2018 14:20:07 +1000 Subject: [PATCH 016/143] Better performance, correctness for {mutable.HashMap, ChampHashMap}.getOrElse* - mutable.HashMap.getOrElse* should honour the potentially overridden get. I've done this by restricting the optimizations to the common case where `this.getClass == HashMap`. An alternative would be to factor out the optimizations into a concrete final subclass of `HashMap`, but the backwards compatibility story isn't great. - ChampHashMap should getOrElse Performance improvement: http://jmh.morethan.io/?gists=50f39587cab66ecef0f5d67aad3deb35,1e5c739010b8f5a98816c2d43c60cdbd --- .../collection/immutable/ChampHashMap.scala | 30 ++++++++++- .../scala/collection/mutable/HashMap.scala | 50 ++++++++++++------- .../collection/immutable/HashMapTest.scala | 13 +++++ .../collection/mutable/HashMapTest.scala | 9 ++++ 4 files changed, 83 insertions(+), 19 deletions(-) diff --git a/src/library/scala/collection/immutable/ChampHashMap.scala b/src/library/scala/collection/immutable/ChampHashMap.scala index f38a7d946000..897f07ed6b80 100644 --- a/src/library/scala/collection/immutable/ChampHashMap.scala +++ b/src/library/scala/collection/immutable/ChampHashMap.scala @@ -58,6 +58,8 @@ final class ChampHashMap[K, +V] private[immutable] (private val rootNode: MapNod def get(key: K): Option[V] = rootNode.get(key, computeHash(key), 0) + override def getOrElse[V1 >: V](key: K, default: => V1): V1 = rootNode.getOrElse(key, computeHash(key), 0, default) + def updated[V1 >: V](key: K, value: V1): ChampHashMap[K, V1] = { val keyHash = computeHash(key) val newRootNodeSource = rootNode.updated(key, value, keyHash, 0) @@ -130,9 +132,9 @@ private[immutable] sealed abstract class MapNode[K, +V] extends MapNodeSource[K, final def get: MapNode[K, V] = this def get(key: K, hash: Int, shift: Int): Option[V] + def getOrElse[V1 >: V](key: K, hash: Int, shift: Int, f: => V1): V1 - def containsKey(key: K, hash: Int, shift: Int): Boolean = - this.get(key, hash, shift).isDefined + def containsKey(key: K, hash: Int, shift: Int): Boolean def updated[V1 >: V](key: K, value: V1, hash: Int, shift: Int): MapNodeSource[K, V1] @@ -212,6 +214,22 @@ private class BitmapIndexedMapNode[K, +V](val dataMap: Int, val nodeMap: Int, va None } + def getOrElse[V1 >: V](key: K, keyHash: Int, shift: Int, f: => V1): V1 = { + val mask = maskFrom(keyHash, shift) + val bitpos = bitposFrom(mask) + + if ((dataMap & bitpos) != 0) { + val index = indexFrom(dataMap, mask, bitpos) + val key0 = this.getKey(index) + return if (key == key0) this.getValue(index) else f + } + + if ((nodeMap & bitpos) != 0) { + val index = indexFrom(nodeMap, mask, bitpos) + return this.getNode(index).getOrElse(key, keyHash, shift + BitPartitionSize, f) + } + f + } override def containsKey(key: K, keyHash: Int, shift: Int): Boolean = { val mask = maskFrom(keyHash, shift) @@ -517,6 +535,14 @@ private class HashCollisionMapNode[K, +V](val hash: Int, val content: Vector[(K, def get(key: K, hash: Int, shift: Int): Option[V] = if (this.hash == hash) content.find(key == _._1).map(_._2) else None + def getOrElse[V1 >: V](key: K, hash: Int, shift: Int, f: => V1): V1 = { + if (this.hash == hash) { + content.find(key == _._1) match { + case Some(pair) => pair._2 + case None => f + } + } else f + } override def containsKey(key: K, hash: Int, shift: Int): Boolean = this.hash == hash && content.exists(key == _._1) diff --git a/src/library/scala/collection/mutable/HashMap.scala b/src/library/scala/collection/mutable/HashMap.scala index 13acebccdcd4..2ea967c2cabd 100644 --- a/src/library/scala/collection/mutable/HashMap.scala +++ b/src/library/scala/collection/mutable/HashMap.scala @@ -75,23 +75,39 @@ class HashMap[K, V] } override def getOrElseUpdate(key: K, defaultValue: => V): V = { - val hash = table.elemHashCode(key) - val i = table.index(hash) - val firstEntry = table.findEntry0(key, i) - if (firstEntry != null) firstEntry.value - else { - val table0 = table.table - val default = defaultValue - // Avoid recomputing index if the `defaultValue()` hasn't triggered - // a table resize. - val newEntryIndex = if (table0 eq table.table) i else table.index(hash) - val e = table.createNewEntry(key, default) - // Repeat search - // because evaluation of `default` can bring entry with `key` - val secondEntry = table.findEntry0(key, newEntryIndex) - if (secondEntry == null) table.addEntry0(e, newEntryIndex) - else secondEntry.value = default - default + if (getClass != classOf[HashMap[_, _]]) { + // subclasses of HashMap might customise `get` ... + super.getOrElseUpdate(key, defaultValue) + } else { + val hash = table.elemHashCode(key) + val i = table.index(hash) + val firstEntry = table.findEntry0(key, i) + if (firstEntry != null) firstEntry.value + else { + val table0 = table.table + val default = defaultValue + // Avoid recomputing index if the `defaultValue()` hasn't triggered + // a table resize. + val newEntryIndex = if (table0 eq table.table) i else table.index(hash) + val e = table.createNewEntry(key, default) + // Repeat search + // because evaluation of `default` can bring entry with `key` + val secondEntry = table.findEntry0(key, newEntryIndex) + if (secondEntry == null) table.addEntry0(e, newEntryIndex) + else secondEntry.value = default + default + } + } + } + + override def getOrElse[V1 >: V](key: K, default: => V1): V1 = { + if (getClass != classOf[HashMap[_, _]]) { + // subclasses of HashMap might customise `get` ... + super.getOrElse(key, default) + } else { + // .. but in the common case, we can avoid the Option boxing. + val e = table.findEntry(key) + if (e eq null) default else e.value } } diff --git a/test/junit/scala/collection/immutable/HashMapTest.scala b/test/junit/scala/collection/immutable/HashMapTest.scala index 37140810bbf0..fd2b9168d3bf 100644 --- a/test/junit/scala/collection/immutable/HashMapTest.scala +++ b/test/junit/scala/collection/immutable/HashMapTest.scala @@ -53,4 +53,17 @@ class HashMapTest { assertEquals("a", m2(1)) assertEquals(0, m2(3)) } + + @Test + def testGetOrElse: Unit = { + val m1 = HashMap(1 -> "a", 2 -> "b") + assertEquals("a", m1.getOrElse(1, ???)) + assertEquals("c", m1.getOrElse(3, "c")) + + class Collider { override def hashCode = 0 } + val a, b, c = new Collider + val m2 = HashMap(a -> "a", b -> "b") + assertEquals("a", m2.getOrElse(a, ???)) + assertEquals("c", m2.getOrElse(c, "c")) + } } diff --git a/test/junit/scala/collection/mutable/HashMapTest.scala b/test/junit/scala/collection/mutable/HashMapTest.scala index 6290c3781f00..bf0987b1e56f 100644 --- a/test/junit/scala/collection/mutable/HashMapTest.scala +++ b/test/junit/scala/collection/mutable/HashMapTest.scala @@ -93,4 +93,13 @@ class HashMapTest { val fmip = hm.flatMapInPlace(_ => empty) assert(fmip.size == 0) } + + @Test + def customGet(): Unit = { + val gotItAll = new mutable.HashMap[String, String] { + override def get(key: String): Option[String] = Some(key) + } + assertEquals("a", gotItAll.getOrElse("a", "b")) + assertEquals("a", gotItAll.getOrElseUpdate("a", "b")) + } } From febeeda4b5bd8805150f7534dfe4433c7c946058 Mon Sep 17 00:00:00 2001 From: Jason Zaugg Date: Thu, 21 Jun 2018 14:10:18 +1000 Subject: [PATCH 017/143] Add a few fast paths to equals/sameElements --- src/library/scala/collection/Map.scala | 4 +++- src/library/scala/collection/Seq.scala | 12 +++++++++--- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/src/library/scala/collection/Map.scala b/src/library/scala/collection/Map.scala index 6c44389e4cf9..397ab1566b9e 100644 --- a/src/library/scala/collection/Map.scala +++ b/src/library/scala/collection/Map.scala @@ -35,7 +35,7 @@ trait Map[K, +V] (that canEqual this) && (this.size == that.size) && { try { - this forall { case (k, v) => that.get(k).contains(v) } + this forall { case (k, v) => that.getOrElse(k, Map.DefaultSentinel) == v } } catch { case _: ClassCastException => false } @@ -327,6 +327,8 @@ object MapOps { @SerialVersionUID(3L) object Map extends MapFactory.Delegate[Map](immutable.Map) { implicit def toLazyZipOps[K, V, CC[X, Y] <: Iterable[(X, Y)]](that: CC[K, V]): LazyZipOps[(K, V), CC[K, V]] = new LazyZipOps(that) + + private val DefaultSentinel: AnyRef = new AnyRef } /** Explicit instantiation of the `Map` trait to reduce class file size in subclasses. */ diff --git a/src/library/scala/collection/Seq.scala b/src/library/scala/collection/Seq.scala index c10b30ca30bf..f5f7a79ec190 100644 --- a/src/library/scala/collection/Seq.scala +++ b/src/library/scala/collection/Seq.scala @@ -30,7 +30,7 @@ trait Seq[+A] override def equals(o: scala.Any): Boolean = o match { - case it: Seq[A] => (it canEqual this) && sameElements(it) + case it: Seq[A] => (this eq it) || (it canEqual this) && sameElements(it) case _ => false } @@ -707,8 +707,14 @@ trait SeqOps[+A, +CC[_], +C] extends Any /** Are the elements of this collection the same (and in the same order) * as those of `that`? */ - def sameElements[B >: A](that: IterableOnce[B]): Boolean = - iterator.sameElements(that) + def sameElements[B >: A](that: IterableOnce[B]): Boolean = { + val thisKnownSize = knownSize + val knownSizeDifference = thisKnownSize != -1 && { + val thatKnownSize = that.knownSize + thatKnownSize != -1 && thisKnownSize != thatKnownSize + } + !knownSizeDifference && iterator.sameElements(that) + } /** Tests whether every element of this $coll relates to the * corresponding element of another sequence by satisfying a test predicate. From 76b3be07dff3bc91928a8d56a1221140b3ae7b71 Mon Sep 17 00:00:00 2001 From: Matthew de Detrich Date: Wed, 27 Jun 2018 01:19:45 +0200 Subject: [PATCH 018/143] Add ordering on withDefault test --- test/scalacheck/LinkedMap.scala | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/test/scalacheck/LinkedMap.scala b/test/scalacheck/LinkedMap.scala index e9ff39a565db..55283bb8e1bd 100644 --- a/test/scalacheck/LinkedMap.scala +++ b/test/scalacheck/LinkedMap.scala @@ -18,10 +18,17 @@ object LinkedMapTest extends Properties("LinkedMap") { property("ordering append") = forAll(arbitrary[Map[Int,Int]] suchThat (_.size > 1)) { (m: Map[Int, Int]) => - val list = m.toList - val first = list.init - val elem = list.last - val lm = LinkedMap.from(first) - (lm + elem).iterator.toList == first :+ elem - } + val (m1, m2) = m.splitAt(m.size / 2) + val first = m1.toList + val second = m2.toList + (LinkedMap.from(first) ++ second).iterator.toList == first ++ second + } + + property("ordering on withDefault") = forAll(arbitrary[Map[Int,Int]] suchThat (_.size > 1)) + { (m: Map[Int, Int]) => + val (m1, m2) = m.splitAt(m.size / 2) + val first = m1.toList + val second = m2.toList + (LinkedMap.from(first).withDefaultValue(1) ++ second).iterator.toList == first ++ second + } } From 11af00fe8f6c301075328e7c31fbd3cf007ea714 Mon Sep 17 00:00:00 2001 From: Guillaume Martres Date: Tue, 26 Jun 2018 23:15:20 +0200 Subject: [PATCH 019/143] Remove scala.Symbol literal singleton types Symbol literals may be removed in the future, as discussed in https://github.com/scala/scala-dev/issues/459. SIP-23 added literal singleton types for all supported literals, but it seems more prudent to not allow Symbol literal singleton types until we're sure that Symbol literals will not be dropped. --- .../scala/reflect/reify/phases/Reify.scala | 1 - .../scala/tools/nsc/ast/parser/Parsers.scala | 3 ++- .../nsc/backend/jvm/BCodeBodyBuilder.scala | 4 ---- .../tools/nsc/backend/jvm/CoreBTypes.scala | 5 ---- .../tools/nsc/symtab/classfile/Pickler.scala | 2 -- .../scala/tools/nsc/transform/Erasure.scala | 6 +---- .../scala/reflect/api/StandardLiftables.scala | 1 - .../reflect/internal/AnnotationInfos.scala | 2 -- .../scala/reflect/internal/Constants.scala | 8 +------ .../scala/reflect/internal/Definitions.scala | 1 - .../internal/pickling/PickleFormat.scala | 4 ++-- .../reflect/internal/pickling/UnPickler.scala | 2 +- .../reflect/internal/transform/Erasure.scala | 1 - .../reflect/runtime/JavaUniverseForce.scala | 1 - .../instrumented/indy-symbol-literal.scala | 19 --------------- test/files/neg/sip23-symbols.check | 11 --------- test/files/neg/sip23-symbols.scala | 24 ------------------- .../sip23-narrow-no-empty-refinements.scala | 2 -- test/files/pos/sip23-narrow.scala | 2 -- test/files/pos/sip23-singleton-sub.scala | 2 -- test/files/pos/sip23-symbols.scala | 24 ------------------- test/files/run/sip23-cast-1.scala | 8 ------- test/files/run/sip23-rangepos.scala | 1 - test/files/run/sip23-valueof.scala | 2 -- test/files/run/t6549.check | 2 +- 25 files changed, 8 insertions(+), 130 deletions(-) delete mode 100644 test/files/instrumented/indy-symbol-literal.scala delete mode 100644 test/files/neg/sip23-symbols.check delete mode 100644 test/files/neg/sip23-symbols.scala delete mode 100644 test/files/pos/sip23-symbols.scala diff --git a/src/compiler/scala/reflect/reify/phases/Reify.scala b/src/compiler/scala/reflect/reify/phases/Reify.scala index e9a90d4a69f8..93f6f99d813b 100644 --- a/src/compiler/scala/reflect/reify/phases/Reify.scala +++ b/src/compiler/scala/reflect/reify/phases/Reify.scala @@ -51,7 +51,6 @@ trait Reify extends GenSymbols case mods: global.Modifiers => reifyModifiers(mods) case xs: List[_] => reifyList(xs) case s: String => Literal(Constant(s)) - case s: scala.Symbol => Literal(Constant(s)) case v if isAnyVal(v) => Literal(Constant(v)) case null => Literal(Constant(null)) case _ => diff --git a/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala b/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala index 0f5d701cd472..aaba5c50d404 100644 --- a/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala +++ b/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala @@ -1300,6 +1300,8 @@ self => def finish(value: Any): Tree = try newLiteral(value) finally in.nextToken() if (in.token == INTERPOLATIONID) interpolatedString(inPattern = inPattern) + else if (in.token == SYMBOLLIT) + Apply(scalaDot(nme.Symbol), List(finish(in.strVal))) else finish(in.token match { case CHARLIT => in.charVal case INTLIT => in.intVal(isNegated).toInt @@ -1307,7 +1309,6 @@ self => case FLOATLIT => in.floatVal(isNegated) case DOUBLELIT => in.doubleVal(isNegated) case STRINGLIT | STRINGPART => in.strVal.intern() - case SYMBOLLIT => Symbol(in.strVal.intern()) case TRUE => true case FALSE => false case NULL => null diff --git a/src/compiler/scala/tools/nsc/backend/jvm/BCodeBodyBuilder.scala b/src/compiler/scala/tools/nsc/backend/jvm/BCodeBodyBuilder.scala index c4bae5b8ba7e..86ed9fd8bbbe 100644 --- a/src/compiler/scala/tools/nsc/backend/jvm/BCodeBodyBuilder.scala +++ b/src/compiler/scala/tools/nsc/backend/jvm/BCodeBodyBuilder.scala @@ -444,10 +444,6 @@ abstract class BCodeBodyBuilder extends BCodeSkelBuilder { assert(const.value != null, const) // TODO this invariant isn't documented in `case class Constant` mnode.visitLdcInsn(const.stringValue) // `stringValue` special-cases null, but not for a const with StringTag - case SSymbolTag => - mnode.visitLdcInsn(const.scalaSymbolValue.name) - genCallMethod(SSymbol_apply, InvokeStyle.Static, NoPosition) - case NullTag => emit(asm.Opcodes.ACONST_NULL) case ClazzTag => diff --git a/src/compiler/scala/tools/nsc/backend/jvm/CoreBTypes.scala b/src/compiler/scala/tools/nsc/backend/jvm/CoreBTypes.scala index d90062eb1783..8368bb62500c 100644 --- a/src/compiler/scala/tools/nsc/backend/jvm/CoreBTypes.scala +++ b/src/compiler/scala/tools/nsc/backend/jvm/CoreBTypes.scala @@ -357,11 +357,6 @@ abstract class CoreBTypesFromSymbols[G <: Global] extends CoreBTypes { }) } - def SSymbol_apply: Symbol = _SSymbol_apply.get - private[this] lazy val _SSymbol_apply: LazyVar[Symbol] = runLazy { - getMember(SymbolModule, nme.apply) - } - def lambdaMetaFactoryMetafactoryHandle: Handle = _lambdaMetaFactoryMetafactoryHandle.get private[this] lazy val _lambdaMetaFactoryMetafactoryHandle: LazyVar[Handle] = runLazy { new Handle(Opcodes.H_INVOKESTATIC, diff --git a/src/compiler/scala/tools/nsc/symtab/classfile/Pickler.scala b/src/compiler/scala/tools/nsc/symtab/classfile/Pickler.scala index 18a4fbec0086..95e63ef0b0df 100644 --- a/src/compiler/scala/tools/nsc/symtab/classfile/Pickler.scala +++ b/src/compiler/scala/tools/nsc/symtab/classfile/Pickler.scala @@ -299,7 +299,6 @@ abstract class Pickler extends SubComponent { private def putConstant(c: Constant): Unit = { if (putEntry(c)) { if (c.tag == StringTag) putEntry(newTermName(c.stringValue)) - else if (c.tag == SSymbolTag) putEntry(newTermName(c.scalaSymbolValue.name)) else if (c.tag == ClazzTag) putType(c.typeValue) else if (c.tag == EnumTag) putSymbol(c.symbolValue) } @@ -490,7 +489,6 @@ abstract class Pickler extends SubComponent { case FloatTag => writeLong(floatToIntBits(c.floatValue).toLong) case DoubleTag => writeLong(doubleToLongBits(c.doubleValue)) case StringTag => writeRef(newTermName(c.stringValue)) - case SSymbolTag => writeRef(newTermName(c.scalaSymbolValue.name)) case ClazzTag => writeRef(c.typeValue) case EnumTag => writeRef(c.symbolValue) case tag => if (ByteTag <= tag && tag <= LongTag) writeLong(c.longValue) diff --git a/src/compiler/scala/tools/nsc/transform/Erasure.scala b/src/compiler/scala/tools/nsc/transform/Erasure.scala index aa2bd39059a0..3482a9557793 100644 --- a/src/compiler/scala/tools/nsc/transform/Erasure.scala +++ b/src/compiler/scala/tools/nsc/transform/Erasure.scala @@ -1282,11 +1282,7 @@ abstract class Erasure extends InfoTransform val erased = erasure(typeValue.typeSymbol) applyInArray typeValue treeCopy.Literal(cleanLiteral, Constant(erased)) - } else if (ct.isSymbol) - atPos(tree.pos) { - gen.mkMethodCall(definitions.Symbol_apply, List(Literal(Constant(ct.scalaSymbolValue.name)))) - } - else cleanLiteral + } else cleanLiteral case ClassDef(_,_,_,_) => debuglog("defs of " + tree.symbol + " = " + tree.symbol.info.decls) diff --git a/src/reflect/scala/reflect/api/StandardLiftables.scala b/src/reflect/scala/reflect/api/StandardLiftables.scala index bb50f2683460..ebf15e4f5727 100644 --- a/src/reflect/scala/reflect/api/StandardLiftables.scala +++ b/src/reflect/scala/reflect/api/StandardLiftables.scala @@ -140,7 +140,6 @@ trait StandardLiftables { self: Universe => implicit def unliftScalaSymbol: Unliftable[scala.Symbol] = Unliftable { case Apply(ScalaDot(stdnme.Symbol), List(Literal(Constant(name: String)))) => scala.Symbol(name) - case Literal(Constant(s: scala.Symbol)) => s } implicit def unliftName[T <: Name : ClassTag]: Unliftable[T] = Unliftable[T] { case Ident(name: T) => name; case Bind(name: T, Ident(stdnme.WILDCARD)) => name } diff --git a/src/reflect/scala/reflect/internal/AnnotationInfos.scala b/src/reflect/scala/reflect/internal/AnnotationInfos.scala index 9e3d4a935c30..4e335568321d 100644 --- a/src/reflect/scala/reflect/internal/AnnotationInfos.scala +++ b/src/reflect/scala/reflect/internal/AnnotationInfos.scala @@ -280,8 +280,6 @@ trait AnnotationInfos extends api.Annotations { self: SymbolTable => def symbolArg(index: Int) = argAtIndex(index) collect { case Apply(fun, Literal(str) :: Nil) if fun.symbol == definitions.Symbol_apply => newTermName(str.stringValue) - case Literal(Constant(s: scala.Symbol)) => - newTermName(s.name) } // !!! when annotation arguments are not literals, but any sort of diff --git a/src/reflect/scala/reflect/internal/Constants.scala b/src/reflect/scala/reflect/internal/Constants.scala index 8abfa55f6adf..3b7808b3744a 100644 --- a/src/reflect/scala/reflect/internal/Constants.scala +++ b/src/reflect/scala/reflect/internal/Constants.scala @@ -7,7 +7,6 @@ package scala package reflect package internal -import scala.{ Symbol => SSymbol } import scala.annotation.switch trait Constants extends api.Constants { @@ -30,7 +29,6 @@ trait Constants extends api.Constants { final val ClazzTag = 12 // For supporting java enumerations inside java annotations (see ClassfileParser) final val EnumTag = 13 - final val SSymbolTag = 14 case class Constant(value: Any) extends ConstantApi { import java.lang.Double.doubleToRawLongBits @@ -50,7 +48,6 @@ trait Constants extends api.Constants { case x: Char => CharTag case x: Type => ClazzTag case x: Symbol => EnumTag - case x: SSymbol => SSymbolTag case _ => throw new Error("bad constant value: " + value + " of class " + value.getClass) } @@ -62,8 +59,7 @@ trait Constants extends api.Constants { def isFloatRange: Boolean = ByteTag <= tag && tag <= FloatTag def isNumeric: Boolean = ByteTag <= tag && tag <= DoubleTag def isNonUnitAnyVal = BooleanTag <= tag && tag <= DoubleTag - def isSymbol: Boolean = tag == SSymbolTag - def isSuitableLiteralType = (BooleanTag <= tag && tag <= NullTag) || tag == SSymbolTag + def isSuitableLiteralType = BooleanTag <= tag && tag <= NullTag def isAnyVal = UnitTag <= tag && tag <= DoubleTag def tpe: Type = tag match { @@ -80,7 +76,6 @@ trait Constants extends api.Constants { case NullTag => NullTpe case ClazzTag => ClassType(typeValue) case EnumTag => EnumType(symbolValue) - case SSymbolTag => SymbolTpe } /** We need the equals method to take account of tags as well as values. @@ -247,7 +242,6 @@ trait Constants extends api.Constants { } def typeValue: Type = value.asInstanceOf[Type] def symbolValue: Symbol = value.asInstanceOf[Symbol] - def scalaSymbolValue: SSymbol = value.asInstanceOf[SSymbol] /** * Consider two `NaN`s to be identical, despite non-equality diff --git a/src/reflect/scala/reflect/internal/Definitions.scala b/src/reflect/scala/reflect/internal/Definitions.scala index 6df1c2a87e53..06bf51cd0cdd 100644 --- a/src/reflect/scala/reflect/internal/Definitions.scala +++ b/src/reflect/scala/reflect/internal/Definitions.scala @@ -276,7 +276,6 @@ trait Definitions extends api.StandardDefinitions { lazy val SerializableTpe = SerializableClass.tpe lazy val StringTpe = StringClass.tpe lazy val ThrowableTpe = ThrowableClass.tpe - lazy val SymbolTpe = SymbolClass.tpe lazy val ConstantTrue = ConstantType(Constant(true)) lazy val ConstantFalse = ConstantType(Constant(false)) diff --git a/src/reflect/scala/reflect/internal/pickling/PickleFormat.scala b/src/reflect/scala/reflect/internal/pickling/PickleFormat.scala index cfd154bdd09e..294a07fb32c9 100644 --- a/src/reflect/scala/reflect/internal/pickling/PickleFormat.scala +++ b/src/reflect/scala/reflect/internal/pickling/PickleFormat.scala @@ -116,7 +116,7 @@ object PickleFormat { * len is remaining length after `len`. */ val MajorVersion = 5 - val MinorVersion = 1 + val MinorVersion = 2 final val TERMname = 1 final val TYPEname = 2 @@ -155,7 +155,7 @@ object PickleFormat { final val LITERALnull = 34 final val LITERALclass = 35 final val LITERALenum = 36 - final val LITERALsymbol = 37 + final val LITERALsymbol = 37 // TODO: Never pickled, to be dropped once we have a STARR that does not emit it. final val SYMANNOT = 40 final val CHILDREN = 41 final val ANNOTATEDtpe = 42 diff --git a/src/reflect/scala/reflect/internal/pickling/UnPickler.scala b/src/reflect/scala/reflect/internal/pickling/UnPickler.scala index 2600bf885cb4..25d4276eb245 100644 --- a/src/reflect/scala/reflect/internal/pickling/UnPickler.scala +++ b/src/reflect/scala/reflect/internal/pickling/UnPickler.scala @@ -434,7 +434,7 @@ abstract class UnPickler { case LITERALnull => Constant(null) case LITERALclass => Constant(readTypeRef()) case LITERALenum => Constant(readSymbolRef()) - case LITERALsymbol => Constant(scala.Symbol(readNameRef().toString)) + case LITERALsymbol => Constant(null) // TODO: needed until we have a STARR that does not emit it. case _ => noSuchConstantTag(tag, len) } } diff --git a/src/reflect/scala/reflect/internal/transform/Erasure.scala b/src/reflect/scala/reflect/internal/transform/Erasure.scala index f60adfe530a3..fc1afd3f7a3f 100644 --- a/src/reflect/scala/reflect/internal/transform/Erasure.scala +++ b/src/reflect/scala/reflect/internal/transform/Erasure.scala @@ -115,7 +115,6 @@ trait Erasure { case FoldableConstantType(ct) => // erase classOf[List[_]] to classOf[List]. special case for classOf[Unit], avoid erasing to classOf[BoxedUnit]. if (ct.tag == ClazzTag && ct.typeValue.typeSymbol != UnitClass) ConstantType(Constant(apply(ct.typeValue))) - else if(ct.isSymbol) SymbolTpe else tp case st: ThisType if st.sym.isPackageClass => tp diff --git a/src/reflect/scala/reflect/runtime/JavaUniverseForce.scala b/src/reflect/scala/reflect/runtime/JavaUniverseForce.scala index 8c59a96081a2..e47cf0366948 100644 --- a/src/reflect/scala/reflect/runtime/JavaUniverseForce.scala +++ b/src/reflect/scala/reflect/runtime/JavaUniverseForce.scala @@ -222,7 +222,6 @@ trait JavaUniverseForce { self: runtime.JavaUniverse => definitions.SerializableTpe definitions.StringTpe definitions.ThrowableTpe - definitions.SymbolTpe definitions.ConstantTrue definitions.ConstantFalse definitions.ConstantNull diff --git a/test/files/instrumented/indy-symbol-literal.scala b/test/files/instrumented/indy-symbol-literal.scala deleted file mode 100644 index a1c333cf95e6..000000000000 --- a/test/files/instrumented/indy-symbol-literal.scala +++ /dev/null @@ -1,19 +0,0 @@ -import scala.tools.partest.instrumented._ -import scala.tools.partest.instrumented.Instrumentation._ - -object Test { - def main(args: Array[String]): Unit = { - 'warmup - startProfiling() - var i = 0; - while (i < 2) { - 'foo.name - i += 1 - } - stopProfiling() - // Only expect a single call to lookup the interned Symbol at each call site the defines - // a single literal. - val Symbol_apply = MethodCallTrace("scala/Symbol$", "apply", "(Ljava/lang/String;)Lscala/Symbol;") - assert(getStatistics.get(Symbol_apply) == Some(1), getStatistics); - } -} diff --git a/test/files/neg/sip23-symbols.check b/test/files/neg/sip23-symbols.check deleted file mode 100644 index dc2070fc9d99..000000000000 --- a/test/files/neg/sip23-symbols.check +++ /dev/null @@ -1,11 +0,0 @@ -sip23-symbols.scala:4: error: type mismatch; - found : Test.sym0.type (with underlying type Symbol) - required: 's - sym0: 's - ^ -sip23-symbols.scala:19: error: type mismatch; - found : Test.sym3.type (with underlying type Symbol) - required: 's - sym3: 's - ^ -two errors found diff --git a/test/files/neg/sip23-symbols.scala b/test/files/neg/sip23-symbols.scala deleted file mode 100644 index 82a0f148d1ee..000000000000 --- a/test/files/neg/sip23-symbols.scala +++ /dev/null @@ -1,24 +0,0 @@ -object Test { - val sym0 = 's - //sym0: Symbol - sym0: 's - - //val sym1: 's = 's - //sym1: Symbol - //sym1: 's - - //final val sym2 = 's - //sym2: Symbol - //sym2: 's - - def id[T](t: T): T = t - //def narrow[T <: Singleton](t: T): T {} = t - - final val sym3 = id('s) - //sym3: Symbol - sym3: 's - - //val sym4 = narrow('s) - //sym4: Symbol - //sym4: 's -} diff --git a/test/files/pos/sip23-narrow-no-empty-refinements.scala b/test/files/pos/sip23-narrow-no-empty-refinements.scala index 2e99d2eead9f..10980bef0e33 100644 --- a/test/files/pos/sip23-narrow-no-empty-refinements.scala +++ b/test/files/pos/sip23-narrow-no-empty-refinements.scala @@ -116,8 +116,6 @@ object Test { ns5: '*' val ns6 = "foo".narrow ns6: "foo" - val ns7 = 'a.narrow - ns7: 'a sealed trait Nat sealed trait Succ[N <: Nat] extends Nat diff --git a/test/files/pos/sip23-narrow.scala b/test/files/pos/sip23-narrow.scala index 105ee2b065c8..a1931441dbf0 100644 --- a/test/files/pos/sip23-narrow.scala +++ b/test/files/pos/sip23-narrow.scala @@ -119,8 +119,6 @@ object Test { ns5: '*' val ns6 = "foo".narrow ns6: "foo" - val ns7 = 'a.narrow - ns7: 'a sealed trait Nat sealed trait Succ[N <: Nat] extends Nat diff --git a/test/files/pos/sip23-singleton-sub.scala b/test/files/pos/sip23-singleton-sub.scala index 76577c9f8d64..16794f6f203d 100644 --- a/test/files/pos/sip23-singleton-sub.scala +++ b/test/files/pos/sip23-singleton-sub.scala @@ -6,7 +6,6 @@ object Test { val e: Singleton = true val f: Singleton = 'c' val g: Singleton = "foo" - val h: Singleton = 'foo implicitly[1 <:< Singleton] implicitly[1L <:< Singleton] @@ -15,5 +14,4 @@ object Test { implicitly[true <:< Singleton] implicitly['c' <:< Singleton] implicitly["foo" <:< Singleton] - implicitly['foo <:< Singleton] } diff --git a/test/files/pos/sip23-symbols.scala b/test/files/pos/sip23-symbols.scala deleted file mode 100644 index 7162acf6932a..000000000000 --- a/test/files/pos/sip23-symbols.scala +++ /dev/null @@ -1,24 +0,0 @@ -object Test { - val sym0 = 's - sym0: Symbol - //sym0: 's - - val sym1: 's = 's - sym1: Symbol - sym1: 's - - final val sym2 = 's - sym2: Symbol - sym2: 's - - def id[T](t: T): T = t - def narrow[T <: Singleton](t: T): T {} = t - - final val sym3 = id('s) - sym3: Symbol - //sym3: 's - - val sym4 = narrow('s) - sym4: Symbol - sym4: 's -} diff --git a/test/files/run/sip23-cast-1.scala b/test/files/run/sip23-cast-1.scala index 2b5930a04f11..d7da02cae6b3 100644 --- a/test/files/run/sip23-cast-1.scala +++ b/test/files/run/sip23-cast-1.scala @@ -47,10 +47,6 @@ object Test extends App { "foo".asInstanceOf["bar"] null.asInstanceOf["foo"] - 'foo.asInstanceOf['foo] - 'foo.asInstanceOf['bar] - null.asInstanceOf['foo] - // isInstanceOf assert(global0.isInstanceOf[global0.type]) assert(!global0.isInstanceOf[global1.type]) @@ -91,8 +87,4 @@ object Test extends App { assert("foo".isInstanceOf["foo"]) assert(!"foo".isInstanceOf["bar"]) assert(!null.isInstanceOf["foo"]) - - assert('foo.isInstanceOf['foo]) - assert(!'foo.isInstanceOf['bar]) - assert(!null.isInstanceOf['foo]) } diff --git a/test/files/run/sip23-rangepos.scala b/test/files/run/sip23-rangepos.scala index 209ea86d5bb4..6ae158384090 100644 --- a/test/files/run/sip23-rangepos.scala +++ b/test/files/run/sip23-rangepos.scala @@ -1,5 +1,4 @@ object Test extends App { val foo: "foo" = "foo" - val bar: 'bar = 'bar val baz: -23 = -23 } diff --git a/test/files/run/sip23-valueof.scala b/test/files/run/sip23-valueof.scala index 0d5f81cb04b2..684257c3b001 100644 --- a/test/files/run/sip23-valueof.scala +++ b/test/files/run/sip23-valueof.scala @@ -9,7 +9,6 @@ object Test extends App { implicitly[ValueOf[true]] implicitly[ValueOf['f']] implicitly[ValueOf["foo"]] - implicitly[ValueOf['foo]] implicitly[ValueOf[Unit]] implicitly[ValueOf[Foo.type]] implicitly[ValueOf[foo.type]] @@ -21,7 +20,6 @@ object Test extends App { assert((valueOf[true]: true) == true) assert((valueOf['f']: 'f') == 'f') assert((valueOf["foo"]: "foo") == "foo") - assert((valueOf['foo]: 'foo) == 'foo) assert((valueOf[Unit]: Unit) == ((): Any)) assert((valueOf[Foo.type]: Foo.type) eq Foo) assert((valueOf[foo.type]: foo.type) eq foo) diff --git a/test/files/run/t6549.check b/test/files/run/t6549.check index 8fdee4f74546..5f76bed8077f 100644 --- a/test/files/run/t6549.check +++ b/test/files/run/t6549.check @@ -18,7 +18,7 @@ scala> m("").xxx = "\"" mutated m("").xxx scala> m('s).xxx = 's -mutated m('s).xxx +mutated m(scala.Symbol("s")).xxx scala> val `"` = 0 ": Int = 0 From 3e00af4525fc1e1ddf8747b792fe99950a72bde3 Mon Sep 17 00:00:00 2001 From: Harrison Houghton Date: Fri, 22 Jun 2018 20:18:15 -0400 Subject: [PATCH 020/143] Support @Repeatable Java annotations. Currently, duplicate classfile annotations cause a runtime crash when the JVM sees them (due to a call to `getAnnotations` or the like). Do instead exactly what Java does (since JEP-120): if the annotation type is (meta-)annotated with `@Repeatable`, wrap the annotations in an array and annotate the original element with a new annotation of the type given by `Repeatable#value`. It is now an error to have multiple annotations on the same tree with the same `typeSymbol` if the symbol is a classfile annotation. Fixes scala/bug#9529. --- .../tools/nsc/typechecker/RefChecks.scala | 61 ++++++++++++++----- .../mima-filters/2.12.0.forwards.excludes | 1 + .../reflect/internal/AnnotationInfos.scala | 3 + .../scala/reflect/internal/Definitions.scala | 3 +- .../scala/reflect/runtime/JavaMirrors.scala | 2 + .../reflect/runtime/JavaUniverseForce.scala | 1 + test/files/neg/t9529.check | 4 ++ test/files/neg/t9529.scala | 7 +++ test/files/pos/annotations.scala | 6 +- test/files/pos/attributes.scala | 2 - test/files/run/reify_ann1b.check | 31 ++++++---- test/files/run/reify_ann1b.scala | 11 ++-- test/files/run/t9529-types.check | 15 +++++ test/files/run/t9529-types/Test_1.scala | 29 +++++++++ test/files/run/t9529-types/TypeAnn_0.java | 16 +++++ test/files/run/t9529.check | 16 +++++ test/files/run/t9529/Ann_0.java | 15 +++++ test/files/run/t9529/Test_1.scala | 59 ++++++++++++++++++ 18 files changed, 243 insertions(+), 39 deletions(-) create mode 100644 test/files/neg/t9529.check create mode 100644 test/files/neg/t9529.scala create mode 100644 test/files/run/t9529-types.check create mode 100644 test/files/run/t9529-types/Test_1.scala create mode 100644 test/files/run/t9529-types/TypeAnn_0.java create mode 100644 test/files/run/t9529.check create mode 100644 test/files/run/t9529/Ann_0.java create mode 100644 test/files/run/t9529/Test_1.scala diff --git a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala index a40bf3be9c92..d4360308fa34 100644 --- a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala +++ b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala @@ -1405,18 +1405,46 @@ abstract class RefChecks extends Transform { } } - private def checkAnnotations(tpes: List[Type], tree: Tree) = tpes foreach { tp => - checkTypeRef(tp, tree, skipBounds = false) - checkTypeRefBounds(tp, tree) - } - private def doTypeTraversal(tree: Tree)(f: Type => Unit) = if (!inPattern) tree.tpe foreach f - private def applyRefchecksToAnnotations(tree: Tree): Unit = { - def applyChecks(annots: List[AnnotationInfo]) = { - checkAnnotations(annots map (_.atp), tree) - transformTrees(annots flatMap (_.args)) + def applyChecks(annots: List[AnnotationInfo]): List[AnnotationInfo] = { + annots.foreach { ann => + checkTypeRef(ann.tpe, tree, skipBounds = false) + checkTypeRefBounds(ann.tpe, tree) + } + + annots + .map(_.transformArgs(transformTrees)) + .groupBy(_.symbol) + .flatMap((groupRepeatableAnnotations _).tupled) + .toList } + // assumes non-empty `anns` + def groupRepeatableAnnotations(sym: Symbol, anns: List[AnnotationInfo]): List[AnnotationInfo] = + if (!(sym isSubClass ClassfileAnnotationClass)) anns else anns match { + case single :: Nil => anns + case multiple => + sym.getAnnotation(AnnotationRepeatableAttr) match { + case Some(repeatable) => + repeatable.assocs.collectFirst { + case (nme.value, LiteralAnnotArg(Constant(c: Type))) => c + } match { + case Some(container) => + val assocs = List( + nme.value -> ArrayAnnotArg(multiple.map(NestedAnnotArg(_)).toArray) + ) + AnnotationInfo(container, args = Nil, assocs = assocs) :: Nil + case None => + devWarning(s"@Repeatable $sym had no containing class") + multiple + } + + case None => + reporter.error(tree.pos, s"$sym may not appear multiple times on ${tree.symbol}") + multiple + } + } + def checkIsElisible(sym: Symbol) = if (sym ne null) sym.elisionLevel.foreach { level => if (!sym.isMethod || sym.isAccessor || sym.isLazy || sym.isDeferred) reporter.error(sym.pos, s"${sym.name}: Only methods can be marked @elidable.") @@ -1426,7 +1454,7 @@ abstract class RefChecks extends Transform { tree match { case m: MemberDef => val sym = m.symbol - applyChecks(sym.annotations) + sym.setAnnotations(applyChecks(sym.annotations)) def messageWarning(name: String)(warn: String) = reporter.warning(tree.pos, f"Invalid $name message for ${sym}%s${sym.locationString}%s:%n$warn") @@ -1444,11 +1472,12 @@ abstract class RefChecks extends Transform { } } - doTypeTraversal(tree) { - case tp @ AnnotatedType(annots, _) => - applyChecks(annots) - case tp => - } + if (!inPattern) + tree.setType(tree.tpe map { + case AnnotatedType(anns, ul) => + AnnotatedType(applyChecks(anns), ul) + case tp => tp + }) case _ => } } @@ -1713,7 +1742,7 @@ abstract class RefChecks extends Transform { var skipBounds = false // check all bounds, except those that are existential type parameters // or those within typed annotated with @uncheckedBounds - doTypeTraversal(tree) { + if (!inPattern) tree.tpe foreach { case tp @ ExistentialType(tparams, tpe) => existentialParams ++= tparams case ann: AnnotatedType if ann.hasAnnotation(UncheckedBoundsClass) => diff --git a/src/reflect/mima-filters/2.12.0.forwards.excludes b/src/reflect/mima-filters/2.12.0.forwards.excludes index fcac3f3749b7..d39f24039a81 100644 --- a/src/reflect/mima-filters/2.12.0.forwards.excludes +++ b/src/reflect/mima-filters/2.12.0.forwards.excludes @@ -9,6 +9,7 @@ ProblemFilters.exclude[MissingClassProblem]("scala.reflect.io.PlainNioFile") ProblemFilters.exclude[DirectMissingMethodProblem]("scala.reflect.runtime.SynchronizedOps.newMappedBaseTypeSeq") ProblemFilters.exclude[DirectMissingMethodProblem]("scala.reflect.runtime.JavaUniverse.newMappedBaseTypeSeq") ProblemFilters.exclude[DirectMissingMethodProblem]("scala.reflect.runtime.JavaUniverse.statistics") +ProblemFilters.exclude[DirectMissingMethodProblem]("scala.reflect.runtime.JavaMirrors#JavaMirror#JavaAnnotationProxy.transformArgs") ProblemFilters.exclude[MissingClassProblem]("scala.reflect.io.FileZipArchive$LazyEntry") ProblemFilters.exclude[DirectMissingMethodProblem]("scala.reflect.io.ZipArchive.closeZipFile") diff --git a/src/reflect/scala/reflect/internal/AnnotationInfos.scala b/src/reflect/scala/reflect/internal/AnnotationInfos.scala index 54764268c7e2..411d6e01382f 100644 --- a/src/reflect/scala/reflect/internal/AnnotationInfos.scala +++ b/src/reflect/scala/reflect/internal/AnnotationInfos.scala @@ -338,6 +338,9 @@ trait AnnotationInfos extends api.Annotations { self: SymbolTable => def argAtIndex(index: Int): Option[Tree] = if (index < args.size) Some(args(index)) else None + def transformArgs(f: List[Tree] => List[Tree]): AnnotationInfo = + new CompleteAnnotationInfo(atp, f(args), assocs) + override def hashCode = atp.## + args.## + assocs.## override def equals(other: Any) = other match { case x: AnnotationInfo => (atp == x.atp) && (args == x.args) && (assocs == x.assocs) diff --git a/src/reflect/scala/reflect/internal/Definitions.scala b/src/reflect/scala/reflect/internal/Definitions.scala index 20c330a56f2f..cdb2ab744936 100644 --- a/src/reflect/scala/reflect/internal/Definitions.scala +++ b/src/reflect/scala/reflect/internal/Definitions.scala @@ -1118,9 +1118,10 @@ trait Definitions extends api.StandardDefinitions { lazy val ClassfileAnnotationClass = requiredClass[scala.annotation.ClassfileAnnotation] lazy val StaticAnnotationClass = requiredClass[scala.annotation.StaticAnnotation] - // Java retention annotations + // Java annotation annotations lazy val AnnotationRetentionAttr = requiredClass[java.lang.annotation.Retention] lazy val AnnotationRetentionPolicyAttr = requiredClass[java.lang.annotation.RetentionPolicy] + lazy val AnnotationRepeatableAttr = requiredClass[java.lang.annotation.Repeatable] // Annotations lazy val BridgeClass = requiredClass[scala.annotation.bridge] diff --git a/src/reflect/scala/reflect/runtime/JavaMirrors.scala b/src/reflect/scala/reflect/runtime/JavaMirrors.scala index 7d0ef7ba3c31..436d652a62c6 100644 --- a/src/reflect/scala/reflect/runtime/JavaMirrors.scala +++ b/src/reflect/scala/reflect/runtime/JavaMirrors.scala @@ -176,6 +176,8 @@ private[scala] trait JavaMirrors extends internal.SymbolTable with api.JavaUnive TermName(m.getName) -> toAnnotArg(m.getReturnType -> m.invoke(jann)) ) ) + + override def transformArgs(f: List[Tree] => List[Tree]) = this } def reflect[T: ClassTag](obj: T): InstanceMirror = new JavaInstanceMirror(obj) diff --git a/src/reflect/scala/reflect/runtime/JavaUniverseForce.scala b/src/reflect/scala/reflect/runtime/JavaUniverseForce.scala index 2926bd4d6946..0d72cbd6f607 100644 --- a/src/reflect/scala/reflect/runtime/JavaUniverseForce.scala +++ b/src/reflect/scala/reflect/runtime/JavaUniverseForce.scala @@ -384,6 +384,7 @@ trait JavaUniverseForce { self: runtime.JavaUniverse => definitions.StaticAnnotationClass definitions.AnnotationRetentionAttr definitions.AnnotationRetentionPolicyAttr + definitions.AnnotationRepeatableAttr definitions.BridgeClass definitions.ElidableMethodClass definitions.ImplicitNotFoundClass diff --git a/test/files/neg/t9529.check b/test/files/neg/t9529.check new file mode 100644 index 000000000000..c1d30b7a1e70 --- /dev/null +++ b/test/files/neg/t9529.check @@ -0,0 +1,4 @@ +t9529.scala:7: error: Java annotation Resource may not appear multiple times on class TooMany +class TooMany + ^ +one error found diff --git a/test/files/neg/t9529.scala b/test/files/neg/t9529.scala new file mode 100644 index 000000000000..0be2254ae805 --- /dev/null +++ b/test/files/neg/t9529.scala @@ -0,0 +1,7 @@ +@deprecated("foo", "") +@deprecated("bar", "") +class `scala ftw` + +@javax.annotation.Resource(name = "baz") +@javax.annotation.Resource(name = "quux") +class TooMany \ No newline at end of file diff --git a/test/files/pos/annotations.scala b/test/files/pos/annotations.scala index 4832ce4ecdf7..8ab994dacef3 100644 --- a/test/files/pos/annotations.scala +++ b/test/files/pos/annotations.scala @@ -103,8 +103,10 @@ object Test3 { class Test4 { @Ann3(arr = Array("dlkfj", "DSF")) @Ann4(i = 2908) - @Ann4(i = Test3.i) @Ann5(value = classOf[Int]) - @Ann5(Test3.cls) def foo {} + + @Ann4(i = Test3.i) + @Ann5(Test3.cls) + def bar {} } diff --git a/test/files/pos/attributes.scala b/test/files/pos/attributes.scala index 60e00bff7d7c..c48c26d7a0de 100644 --- a/test/files/pos/attributes.scala +++ b/test/files/pos/attributes.scala @@ -19,8 +19,6 @@ object O5 { final val n = 2; @SerialVersionUID(0) class C1; @SerialVersionUID(n) class C2; - @SerialVersionUID(0) @SerialVersionUID(n) class C3; - @SerialVersionUID(0) @SerialVersionUID(n) class C4; } abstract class A1 { diff --git a/test/files/run/reify_ann1b.check b/test/files/run/reify_ann1b.check index a046dafeab0d..92db7046146e 100644 --- a/test/files/run/reify_ann1b.check +++ b/test/files/run/reify_ann1b.check @@ -1,33 +1,38 @@ reify_ann1b.scala:6: warning: Implementation restriction: subclassing Classfile does not make your annotation visible at runtime. If that is what you want, you must write the annotation class in Java. -class ann(bar: String) extends annotation.ClassfileAnnotation +class ann0(bar: String) extends annotation.ClassfileAnnotation + ^ +reify_ann1b.scala:7: warning: Implementation restriction: subclassing Classfile does not +make your annotation visible at runtime. If that is what +you want, you must write the annotation class in Java. +class ann1(bar: String) extends annotation.ClassfileAnnotation ^ { - @new ann(bar = "1a") @new ann(bar = "1b") class C[@new ann(bar = "2a") @new ann(bar = "2b") T] extends AnyRef { - @new ann(bar = "3a") @new ann(bar = "3b") private[this] val x: T @ann(bar = "4a") @ann(bar = "4b") = _; - def (@new ann(bar = "3a") @new ann(bar = "3b") x: T @ann(bar = "4a") @ann(bar = "4b")) = { + @new ann0(bar = "1a") @new ann1(bar = "1b") class C[@new ann0(bar = "2a") @new ann1(bar = "2b") T] extends AnyRef { + @new ann0(bar = "3a") @new ann1(bar = "3b") private[this] val x: T @ann0(bar = "4a") @ann1(bar = "4b") = _; + def (@new ann0(bar = "3a") @new ann1(bar = "3b") x: T @ann0(bar = "4a") @ann1(bar = "4b")) = { super.(); () }; - @new ann(bar = "5a") @new ann(bar = "5b") def f(x: Int @ann(bar = "6a") @ann(bar = "6b")) = { - @new ann(bar = "7a") @new ann(bar = "7b") val r = x.$plus(3): @ann(bar = "8a"): @ann(bar = "8b"); - val s = (4: Int @ann(bar = "9a") @ann(bar = "9b")); + @new ann0(bar = "5a") @new ann1(bar = "5b") def f(x: Int @ann0(bar = "6a") @ann1(bar = "6b")) = { + @new ann0(bar = "7a") @new ann1(bar = "7b") val r = x.$plus(3): @ann0(bar = "8a"): @ann1(bar = "8b"); + val s = (4: Int @ann0(bar = "9a") @ann1(bar = "9b")); r.$plus(s) } }; () } { - @ann(bar = "1a") @ann(bar = "1b") class C[@ann(bar = "2a") @ann(bar = "2b") T] extends AnyRef { - @ann(bar = "3a") @ann(bar = "3b") private[this] val x: T @ann(bar = "4b") @ann(bar = "4a") = _; - def (@ann(bar = "3a") @ann(bar = "3b") x: T @ann(bar = "4b") @ann(bar = "4a")): C[T] = { + @ann0(bar = "1a") @ann1(bar = "1b") class C[@ann0(bar = "2a") @ann1(bar = "2b") T] extends AnyRef { + @ann0(bar = "3a") @ann1(bar = "3b") private[this] val x: T @ann1(bar = "4b") @ann0(bar = "4a") = _; + def (@ann0(bar = "3a") @ann1(bar = "3b") x: T @ann1(bar = "4b") @ann0(bar = "4a")): C[T] = { C.super.(); () }; - @ann(bar = "5a") @ann(bar = "5b") def f(x: Int @ann(bar = "6b") @ann(bar = "6a")): Int = { - @ann(bar = "7a") @ann(bar = "7b") val r: Int @ann(bar = "8b") @ann(bar = "8a") = ((x.+(3): Int @ann(bar = "8a")): Int @ann(bar = "8b") @ann(bar = "8a")); - val s: Int @ann(bar = "9b") @ann(bar = "9a") = (4: Int @ann(bar = "9b") @ann(bar = "9a")); + @ann0(bar = "5a") @ann1(bar = "5b") def f(x: Int @ann1(bar = "6b") @ann0(bar = "6a")): Int = { + @ann0(bar = "7a") @ann1(bar = "7b") val r: Int @ann1(bar = "8b") @ann0(bar = "8a") = ((x.+(3): Int @ann0(bar = "8a")): Int @ann1(bar = "8b") @ann0(bar = "8a")); + val s: Int @ann1(bar = "9b") @ann0(bar = "9a") = (4: Int @ann1(bar = "9b") @ann0(bar = "9a")); r.+(s) } }; diff --git a/test/files/run/reify_ann1b.scala b/test/files/run/reify_ann1b.scala index 30bafadf75a3..f1710d6fc4c5 100644 --- a/test/files/run/reify_ann1b.scala +++ b/test/files/run/reify_ann1b.scala @@ -3,15 +3,16 @@ import scala.reflect.runtime.{universe => ru} import scala.reflect.runtime.{currentMirror => cm} import scala.tools.reflect.ToolBox -class ann(bar: String) extends annotation.ClassfileAnnotation +class ann0(bar: String) extends annotation.ClassfileAnnotation +class ann1(bar: String) extends annotation.ClassfileAnnotation object Test extends App { // test 1: reify val tree = reify{ - @ann(bar="1a") @ann(bar="1b") class C[@ann(bar="2a") @ann(bar="2b") T](@ann(bar="3a") @ann(bar="3b") x: T @ann(bar="4a") @ann(bar="4b")) { - @ann(bar="5a") @ann(bar="5b") def f(x: Int @ann(bar="6a") @ann(bar="6b")) = { - @ann(bar="7a") @ann(bar="7b") val r = (x + 3): @ann(bar="8a") @ann(bar="8b") - val s = 4: Int @ann(bar="9a") @ann(bar="9b") + @ann0(bar="1a") @ann1(bar="1b") class C[@ann0(bar="2a") @ann1(bar="2b") T](@ann0(bar="3a") @ann1(bar="3b") x: T @ann0(bar="4a") @ann1(bar="4b")) { + @ann0(bar="5a") @ann1(bar="5b") def f(x: Int @ann0(bar="6a") @ann1(bar="6b")) = { + @ann0(bar="7a") @ann1(bar="7b") val r = (x + 3): @ann0(bar="8a") @ann1(bar="8b") + val s = 4: Int @ann0(bar="9a") @ann1(bar="9b") r + s } } diff --git a/test/files/run/t9529-types.check b/test/files/run/t9529-types.check new file mode 100644 index 000000000000..44fa1f050ae3 --- /dev/null +++ b/test/files/run/t9529-types.check @@ -0,0 +1,15 @@ +[[syntax trees at end of pickler]] // newSource1.scala +package { + import anns._; + abstract trait Foo extends AnyRef with Int @anns.TypeAnn_0(value = "b") @anns.TypeAnn_0(value = "a") => String @anns.TypeAnn_0(value = "y") @anns.TypeAnn_0(value = "x") { + type Meh = Any @anns.TypeAnn_0(value = "q") @anns.TypeAnn_0(value = "p") + } +} + +[[syntax trees at end of refchecks]] // newSource1.scala +package { + abstract trait Foo extends AnyRef with Int @anns.TypeAnn_0.Anns(value = [anns.TypeAnn_0(value = "b"), anns.TypeAnn_0(value = "a")]) => String @anns.TypeAnn_0.Anns(value = [anns.TypeAnn_0(value = "y"), anns.TypeAnn_0(value = "x")]) { + type Meh = Any @anns.TypeAnn_0.Anns(value = [anns.TypeAnn_0(value = "q"), anns.TypeAnn_0(value = "p")]) + } +} + diff --git a/test/files/run/t9529-types/Test_1.scala b/test/files/run/t9529-types/Test_1.scala new file mode 100644 index 000000000000..956c6b960196 --- /dev/null +++ b/test/files/run/t9529-types/Test_1.scala @@ -0,0 +1,29 @@ +/* evidently annotations on types don't make it into bytecode yet, even though + * such a thing is allowed in Java 8 and onwards. Here's a test that it'll work + * with repeatable annotations anyways. + * + * nb. currently multiple annotations on type trees get reversed by typer + */ + +import scala.tools.partest._ + +import anns._ + +@TypeAnn_0("") +object Test extends DirectTest { + + override def extraSettings: String = + s"-usejavacp -cp ${testOutput.path} -Xprint:pic,ref -Ystop-after:ref -d ${testOutput.path}" + + override def code = + """import anns._ + |trait Foo extends ( + | (Int @TypeAnn_0("a") @TypeAnn_0("b")) + | => (String @TypeAnn_0("x") @TypeAnn_0("y")) + |) { + | type Meh = Any@TypeAnn_0("p")@TypeAnn_0("q") + |} + """.stripMargin + + override def show() = compile() +} diff --git a/test/files/run/t9529-types/TypeAnn_0.java b/test/files/run/t9529-types/TypeAnn_0.java new file mode 100644 index 000000000000..dbede53ba5c8 --- /dev/null +++ b/test/files/run/t9529-types/TypeAnn_0.java @@ -0,0 +1,16 @@ +package anns; + +import java.lang.annotation.*; + +@Repeatable(TypeAnn_0.Anns.class) +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.TYPE_USE) +public @interface TypeAnn_0 { + String value(); + + @Retention(RetentionPolicy.RUNTIME) + @Target(ElementType.TYPE_USE) + public static @interface Anns { + TypeAnn_0[] value(); + } +} \ No newline at end of file diff --git a/test/files/run/t9529.check b/test/files/run/t9529.check new file mode 100644 index 000000000000..7f567720ba6d --- /dev/null +++ b/test/files/run/t9529.check @@ -0,0 +1,16 @@ +A: List() +B: List(@javax.annotation.Resource(shareable=true, lookup=, name=B, description=, authenticationType=CONTAINER, type=class java.lang.Object, mappedName=)) +C: List(@anns.Ann_0(name=C, value=see)) +D: List(@anns.Ann_0$Container(value=[@anns.Ann_0(name=D, value=dee), @anns.Ann_0(name=D, value=dye)])) + +x: List(@anns.Ann_0(name=x, value=eks)) +y: List(@anns.Ann_0$Container(value=[@anns.Ann_0(name=y, value=why), @anns.Ann_0(name=y, value=wye)])) + +t: List(@anns.Ann_0(name=t, value=tee)) +u: List(@anns.Ann_0$Container(value=[@anns.Ann_0(name=u, value=you), @anns.Ann_0(name=u, value=yew)])) + +1: List(@anns.Ann_0(name=1, value=one)) +2: List(@anns.Ann_0$Container(value=[@anns.Ann_0(name=2, value=two), @anns.Ann_0(name=2, value=tew)])) + +List(@anns.Ann_0$Container(value=[@anns.Ann_0(name=, value=constructor), @anns.Ann_0(name=, value=initializer)])) + diff --git a/test/files/run/t9529/Ann_0.java b/test/files/run/t9529/Ann_0.java new file mode 100644 index 000000000000..bc5e9b0dea9e --- /dev/null +++ b/test/files/run/t9529/Ann_0.java @@ -0,0 +1,15 @@ +package anns; + +import java.lang.annotation.*; + +@Retention(RetentionPolicy.RUNTIME) +@Repeatable(Ann_0.Container.class) +public @interface Ann_0 { + String name(); + String value(); + + @Retention(RetentionPolicy.RUNTIME) + public static @interface Container { + public Ann_0[] value() default {}; + } +} \ No newline at end of file diff --git a/test/files/run/t9529/Test_1.scala b/test/files/run/t9529/Test_1.scala new file mode 100644 index 000000000000..d4efcddeb079 --- /dev/null +++ b/test/files/run/t9529/Test_1.scala @@ -0,0 +1,59 @@ +import java.lang.reflect._ +import anns._ + +class A +@javax.annotation.Resource(name = "B") class B +@Ann_0(name = "C", value = "see") class C +@Ann_0(name = "D", value = "dee") @Ann_0(name = "D", value = "dye") class D + +class Test @Ann_0(name = "", value = "constructor") @Ann_0(name = "", value = "initializer") () { + @Ann_0(name = "x", value = "eks") val x = 1 + @Ann_0(name = "y", value = "why") @Ann_0(name = "y", value = "wye") val y = 2 + + @Ann_0(name = "t", value = "tee") def t = 1 + @Ann_0(name = "u", value = "you") @Ann_0(name = "u", value = "yew") def u = 2 + + def meh( + @Ann_0(name = "1", value = "one") `1`: Int, + @Ann_0(name = "2", value = "two") @Ann_0(name = "2", value = "tew") `2`: Int, + ) = () + + // todo: annotations on types + // todo? annotaitons on packages +} + +object Test extends App { + val cls_test = classOf[Test] + + prints { + List(classOf[A], classOf[B], classOf[C], classOf[D]) + .map(cls => s"${cls.getName}: ${anns(cls)}") + } + + prints { + List("x", "y") + .map(cls_test.getDeclaredField) + .map(f => s"${f.getName}: ${anns(f)}") + } + + prints { + List("t", "u") + .map(cls_test.getDeclaredMethod(_)) + .map(m => s"${m.getName}: ${anns(m)}") + } + + prints { + cls_test + .getDeclaredMethod("meh", classOf[Int], classOf[Int]) + .getParameters.toList + .map(p => s"${p.getName}: ${anns(p)}") + } + + println { + anns(cls_test.getConstructor()).map(_.toString) + } ; println() + + def anns(ae: AnnotatedElement) = + ae.getAnnotations.toList.filterNot(_.isInstanceOf[reflect.ScalaSignature]) + def prints(l: List[String]) = { println(l mkString "\n") ; println() } +} \ No newline at end of file From e9c996636496c04fc438bc809ce50d41118282f8 Mon Sep 17 00:00:00 2001 From: Som Snytt Date: Tue, 26 Jun 2018 10:28:04 -0700 Subject: [PATCH 021/143] Remove LogContext, steps produce TestState Instead of boolean success, always produce a TestState. Delete mutable lastState. TestInfo is back in vogue. Delete unused code. --- .../scala/tools/partest/TestState.scala | 3 + .../tools/partest/nest/AbstractRunner.scala | 9 +- .../tools/partest/nest/DirectCompiler.scala | 12 +- .../scala/tools/partest/nest/Runner.scala | 228 +++++++----------- src/partest/scala/tools/partest/package.scala | 15 +- test/files/res/t687.check | 2 +- test/files/res/t687/QueryA.scala | 4 +- test/files/res/t687/QueryB.scala | 4 +- test/files/run/t7096.scala | 2 +- 9 files changed, 119 insertions(+), 160 deletions(-) diff --git a/src/partest/scala/tools/partest/TestState.scala b/src/partest/scala/tools/partest/TestState.scala index 6f8969738dc8..aa6e2d5f6bf5 100644 --- a/src/partest/scala/tools/partest/TestState.scala +++ b/src/partest/scala/tools/partest/TestState.scala @@ -18,6 +18,8 @@ sealed abstract class TestState { def shortStatus = if (isOk) "ok" else "!!" + final def andAlso(next: => TestState): TestState = if (isOk) next else this + override def toString = status } @@ -54,6 +56,7 @@ object TestState { case class Crash(testFile: java.io.File, caught: Throwable, transcript: Array[String]) extends TestState { def what = "crash" def reason = s"caught $caught_s - ${caught.getMessage}" + override def shortStatus = "?!" private def caught_s = (caught.getClass.getName split '.').last override def transcriptString = nljoin(super.transcriptString, caught_s) diff --git a/src/partest/scala/tools/partest/nest/AbstractRunner.scala b/src/partest/scala/tools/partest/nest/AbstractRunner.scala index ec7390c1aac1..d80b3a9438dd 100644 --- a/src/partest/scala/tools/partest/nest/AbstractRunner.scala +++ b/src/partest/scala/tools/partest/nest/AbstractRunner.scala @@ -289,13 +289,14 @@ class AbstractRunner(val config: RunnerSpec.Config, protected final val testSour def runTest(testFile: File): TestState = { val start = System.nanoTime() - val runner = new Runner(testFile, this) + val info = TestInfo(testFile) + val runner = new Runner(info, this) var stopwatchDuration: Option[Long] = None // when option "--failed" is provided execute test only if log // is present (which means it failed before) val state = - if (config.optFailed && !runner.logFile.canRead) + if (config.optFailed && !info.logFile.canRead) runner.genPass() else { val (state, durationMs) = @@ -304,8 +305,8 @@ class AbstractRunner(val config: RunnerSpec.Config, protected final val testSour case t: Throwable => throw new RuntimeException(s"Error running $testFile", t) } stopwatchDuration = Some(durationMs) - val more = reportTest(state, runner, durationMs, diffOnFail = config.optShowDiff || onlyIndividualTests , logOnFail = config.optShowLog || onlyIndividualTests) - runner.cleanup() + val more = reportTest(state, info, durationMs, diffOnFail = config.optShowDiff || onlyIndividualTests , logOnFail = config.optShowLog || onlyIndividualTests) + runner.cleanup(state) if (more.isEmpty) state else { state match { diff --git a/src/partest/scala/tools/partest/nest/DirectCompiler.scala b/src/partest/scala/tools/partest/nest/DirectCompiler.scala index 93eab3791888..e903097c25d0 100644 --- a/src/partest/scala/tools/partest/nest/DirectCompiler.scala +++ b/src/partest/scala/tools/partest/nest/DirectCompiler.scala @@ -74,14 +74,17 @@ class DirectCompiler(val runner: Runner) { } def compile(opts0: List[String], sources: List[File]): TestState = { - import runner.{ sources => _, _ } + import runner.{sources => _, _}, testInfo._ // adding codelib.jar to the classpath // codelib provides the possibility to override standard reify // this shields the massive amount of reification tests from changes in the API - val codeLib = runner.suiteRunner.pathSettings.srcCodeLib.fold[List[Path]](x => Nil, lib => List[Path](lib)) + val codeLib = suiteRunner.pathSettings.srcCodeLib.fold[List[Path]](x => Nil, lib => List[Path](lib)) // add the instrumented library version to classpath -- must come first - val specializedOverride: List[Path] = if (kind == "specialized") List(runner.suiteRunner.pathSettings.srcSpecLib.fold(sys.error, identity)) else Nil + val specializedOverride: List[Path] = + if (kind == "specialized") + List(suiteRunner.pathSettings.srcSpecLib.fold(sys.error, identity)) + else Nil val classPath: List[Path] = specializedOverride ++ codeLib ++ fileManager.testClassPath ++ List[Path](outDir) @@ -108,8 +111,7 @@ class DirectCompiler(val runner: Runner) { if (command.files.nonEmpty) reportError(command.files.mkString("flags file may only contain compiler options, found: ", space, "")) } - def ids = sources.map(_.testIdent) mkString space - suiteRunner.verbose(s"% scalac $ids") + suiteRunner.verbose(s"% scalac ${ sources.map(_.testIdent).mkString(space) }") def execCompile() = if (command.shouldStopWithInfo) { diff --git a/src/partest/scala/tools/partest/nest/Runner.scala b/src/partest/scala/tools/partest/nest/Runner.scala index 4f2489e8789d..d0d172113217 100644 --- a/src/partest/scala/tools/partest/nest/Runner.scala +++ b/src/partest/scala/tools/partest/nest/Runner.scala @@ -29,67 +29,53 @@ import FileManager.{compareContents, joinPaths, withTempFile} import scala.reflect.internal.util.ScalaClassLoader.URLClassLoader import scala.util.control.ControlThrowable -trait TestInfo { +/** pos/t1234.scala or pos/t1234 if dir */ +case class TestInfo(testFile: File) { /** pos/t1234 */ - def testIdent: String + val testIdent: String = testFile.testIdent /** pos */ - def kind: String + val kind: String = parentFile.getName // inputs - /** pos/t1234.scala or pos/t1234 if dir */ - def testFile: File - /** pos/t1234.check */ - def checkFile: File + val checkFile: File = testFile.changeExtension("check") /** pos/t1234.flags */ - def flagsFile: File + val flagsFile: File = testFile.changeExtension("flags") // outputs + /** pos/t1234-pos.log */ + val logFile: File = new File(parentFile, s"$fileBase-$kind.log") + /** pos/t1234-pos.obj */ - def outFile: File + val outFile: File = logFile.changeExtension("obj") - /** pos/t1234-pos.log */ - def logFile: File + // enclosing dir + def parentFile: File = testFile.getParentFile + + // test file name without extension + def fileBase: String = basename(testFile.getName) } -/** Run a single test. Rubber meets road. */ -class Runner(val testFile: File, val suiteRunner: AbstractRunner) extends TestInfo { +/** Run a single test. */ +class Runner(val testInfo: TestInfo, val suiteRunner: AbstractRunner) { private val stopwatch = new Stopwatch() + import testInfo._ import suiteRunner.{fileManager => fm, _} val fileManager = fm import fileManager._ - // Override to true to have the outcome of this test displayed - // whether it passes or not; in general only failures are reported, - // except for a . per passing test to show progress. - def isEnumeratedTest = false - - private var _lastState: TestState = null private val _transcript = new TestTranscript - def lastState = if (_lastState == null) Uninitialized(testFile) else _lastState - def setLastState(s: TestState) = _lastState = s - def pushTranscript(msg: String) = _transcript add msg - - val parentFile = testFile.getParentFile - val kind = parentFile.getName - val fileBase = basename(testFile.getName) - val logFile = new File(parentFile, s"$fileBase-$kind.log") - val outFile = logFile changeExtension "obj" - val checkFile = testFile changeExtension "check" - val flagsFile = testFile changeExtension "flags" - val testIdent = testFile.testIdent // e.g. pos/t1234 + def pushTranscript(msg: String) = _transcript.add(msg) lazy val outDir = { outFile.mkdirs() ; outFile } - type RanOneTest = (Boolean, LogContext) - def showCrashInfo(t: Throwable): Unit = { System.err.println(s"Crashed running test $testIdent: " + t) if (!suiteRunner.terse) @@ -104,8 +90,9 @@ class Runner(val testFile: File, val suiteRunner: AbstractRunner) extends TestIn genCrash(t) } - def genPass() = Pass(testFile) + def genPass(): TestState = Pass(testFile) def genFail(reason: String) = Fail(testFile, reason, transcript.toArray) + def genResult(b: Boolean) = if (b) genPass() else genFail("predicate failed") def genSkip(reason: String) = Skip(testFile, reason) def genTimeout() = Fail(testFile, "timed out", transcript.toArray) def genCrash(caught: Throwable) = Crash(testFile, caught, transcript.toArray) @@ -133,23 +120,12 @@ class Runner(val testFile: File, val suiteRunner: AbstractRunner) extends TestIn } } - def testPrompt = kind match { - case "res" => "nsc> " - case _ => "% " - } - - /** Evaluate an action body and update the test state. - * @param failFn optionally map a result to a test state. - */ - def nextTestAction[T](body: => T)(failFn: PartialFunction[T, TestState]): T = { - val result = body - setLastState( if (failFn isDefinedAt result) failFn(result) else genPass() ) - result - } - def nextTestActionExpectTrue(reason: String, body: => Boolean): Boolean = ( - nextTestAction(body) { case false => genFail(reason) } - ) - def nextTestActionFailing(reason: String): Boolean = nextTestActionExpectTrue(reason, false) + /** Evaluate an action body and judge whether it passed. */ + def nextTestAction[T](body: => T)(eval: PartialFunction[T, TestState]): TestState = eval.applyOrElse(body, (_: T) => genPass) + /** If the action does not result in true, fail the action. */ + def nextTestActionExpectTrue(reason: String, body: => Boolean): TestState = nextTestAction(body) { case false => genFail(reason) } + /** Fail the action. */ + def nextTestActionFailing(reason: String): TestState = nextTestActionExpectTrue(reason, false) private def assembleTestCommand(outDir: File, logFile: File): List[String] = { // check whether there is a ".javaopts" file @@ -241,7 +217,7 @@ class Runner(val testFile: File, val suiteRunner: AbstractRunner) extends TestIn (pl buffer run) == 0 } - private def execTest(outDir: File, logFile: File): Boolean = { + private def execTest(outDir: File, logFile: File): TestState = { val cmd = assembleTestCommand(outDir, logFile) pushTranscript((cmd mkString s" \\$EOL ") + " > " + logFile.getName) @@ -252,7 +228,7 @@ class Runner(val testFile: File, val suiteRunner: AbstractRunner) extends TestIn } } - def execTestInProcess(classesDir: File, log: File): Boolean = { + def execTestInProcess(classesDir: File, log: File): TestState = { stopwatch.pause() suiteRunner.synchronized { stopwatch.start() @@ -287,25 +263,14 @@ class Runner(val testFile: File, val suiteRunner: AbstractRunner) extends TestIn TrapExit(() => run()) match { case Left((status, throwable)) if status != 0 => - setLastState(genFail("non-zero exit code")) - false + genFail("non-zero exit code") case _ => - setLastState(genPass()) - true + genPass } } } - override def toString = s"""Test($testIdent, lastState = $lastState)""" - - // result is unused - def newTestWriters() = { - val swr = new StringWriter - val wr = new PrintWriter(swr, true) - // diff = "" - - ((swr, wr)) - } + override def toString = s"Test($testIdent)" def fail(what: Any) = { suiteRunner.verbose("scalac: compilation of "+what+" failed\n") @@ -432,50 +397,34 @@ class Runner(val testFile: File, val suiteRunner: AbstractRunner) extends TestIn } } - def diffIsOk: Boolean = { + def diffIsOk: TestState = { // always normalize the log first normalizeLog() - val diff = currentDiff - // if diff is not empty, is update needed? - val updating: Option[Boolean] = ( - if (diff == "") None - else Some(config.optUpdateCheck) - ) pushTranscript(s"diff $checkFile $logFile") - nextTestAction(updating) { - case Some(true) => + currentDiff match { + case "" => genPass + case diff if config.optUpdateCheck => suiteRunner.verbose("Updating checkfile " + checkFile) checkFile writeAll file2String(logFile) genUpdated() - case Some(false) => + case diff => // Get a word-highlighted diff from git if we can find it val bestDiff = - if (updating.isEmpty) "" - else if (checkFile.canRead) - gitRunner match { - case None => diff - case _ => withTempFile(outFile, fileBase, filteredCheck) { f => - gitDiff(f, logFile) getOrElse diff - } - } - else diff + if (!checkFile.canRead) diff + else + gitRunner.flatMap(_ => withTempFile(outFile, fileBase, filteredCheck)(f => + gitDiff(f, logFile))).getOrElse(diff) _transcript append bestDiff genFail("output differs") - // TestState.fail("output differs", "output differs", - // genFail("output differs") - // TestState.Fail("output differs", bestDiff) - case None => genPass() // redundant default case - } getOrElse true + } } /** 1. Creates log file and output directory. * 2. Runs script function, providing log file and output directory as arguments. * 2b. or, just run the script without context and return a new context */ - def runInContext(body: => Boolean): (Boolean, LogContext) = { - val (swr, wr) = newTestWriters() - val succeeded = body - (succeeded, LogContext(logFile, swr, wr)) + def runInContext(body: => TestState): TestState = { + body } /** Grouped files in group order, and lex order within each group. */ @@ -562,9 +511,8 @@ class Runner(val testFile: File, val suiteRunner: AbstractRunner) extends TestIn lazy val result = { pushTranscript(description) ; attemptCompile(fs) } } - def compilationRounds(file: File): List[CompileRound] = ( - (groupedFiles(sources(file)) map mixedCompileGroup).flatten - ) + def compilationRounds(file: File): List[CompileRound] = + groupedFiles(sources(file)).map(mixedCompileGroup).flatten def mixedCompileGroup(allFiles: List[File]): List[CompileRound] = { val (scalaFiles, javaFiles) = allFiles partition (_.isScala) val round1 = if (scalaFiles.isEmpty) None else Some(ScalaAndJava(allFiles)) @@ -573,24 +521,35 @@ class Runner(val testFile: File, val suiteRunner: AbstractRunner) extends TestIn List(round1, round2).flatten } - def runNegTest() = runInContext { - val rounds = compilationRounds(testFile) - - // failing means Does Not Compile - val failing = rounds find (x => nextTestActionExpectTrue("compilation failed", x.isOk) == false) - - // which means passing if it checks and didn't crash the compiler + def runNegTest(): TestState = runInContext { + // pass if it checks and didn't crash the compiler // or, OK, we'll let you crash the compiler with a FatalError if you supply a check file def checked(r: CompileRound) = r.result match { - case Crash(_, t, _) if !checkFile.canRead || !t.isInstanceOf[FatalError] => false - case _ => diffIsOk + case crash @ Crash(_, t, _) if !checkFile.canRead || !t.isInstanceOf[FatalError] => crash + case dnc => diffIsOk } - failing map (checked) getOrElse nextTestActionFailing("expected compilation failure") + compilationRounds(testFile).find(!_.result.isOk).map(checked).getOrElse(genFail("expected compilation failure")) } + /* def runTestCommon(andAlso: => Boolean): (Boolean, LogContext) = runInContext { - compilationRounds(testFile).forall(x => nextTestActionExpectTrue("compilation failed", x.isOk)) && andAlso + compilationRounds(testFile).forall { + case r if r.result.isInstanceOf[Crash] => println("CRASH"); ??? + case x => nextTestActionExpectTrue("compilation failed", x.isOk) && andAlso + } + //compilationRounds(testFile).forall(x => nextTestActionExpectTrue("compilation failed", x.isOk)) && andAlso + } + */ + + def runTestCommon(andAlso: => TestState = genPass): TestState = runInContext { + // DirectCompiler already says compilation failed + //compilationRounds(testFile).foldLeft(genPass)((result, round) => if (result.isOk) round.result else result) + val res = compilationRounds(testFile).foldLeft(genPass) {(result, round) => + if (result.isOk) round.result else result + } + + if (res.isOk) andAlso else res } def extraClasspath = kind match { @@ -602,10 +561,9 @@ class Runner(val testFile: File, val suiteRunner: AbstractRunner) extends TestIn case _ => Array.empty[String] } - def runResidentTest() = { + def runResidentTest(): TestState = { // simulate resident compiler loop val prompt = "\nnsc> " - val (swr, wr) = newTestWriters() suiteRunner.verbose(s"$this running test $fileBase") val dir = parentFile @@ -636,7 +594,7 @@ class Runner(val testFile: File, val suiteRunner: AbstractRunner) extends TestIn val command = new CompilerCommand(argList, settings) object compiler extends Global(command.settings, reporter) - def resCompile(line: String): Boolean = { + def resCompile(line: String): TestState = { // suiteRunner.verbose("compiling "+line) val cmdArgs = (line split ' ').toList map (fs => new File(dir, fs).getAbsolutePath) // suiteRunner.verbose("cmdArgs: "+cmdArgs) @@ -653,20 +611,19 @@ class Runner(val testFile: File, val suiteRunner: AbstractRunner) extends TestIn } ) } - def loop(): Boolean = { + def loop(): TestState = { logWriter.print(prompt) resReader.readLine() match { - case null | "" => logWriter.close() ; true - case line => resCompile(line) && loop() + case null | "" => logWriter.close() ; genPass + case line => resCompile(line) andAlso loop() } } // res/t687.res depends on ignoring its compilation failure // and just looking at the diff, so I made them all do that // because this is long enough. - if (!Output.withRedirected(logWriter)(try loop() finally resReader.close())) - setLastState(genPass()) + val res = Output.withRedirected(logWriter)(try loop() finally resReader.close()) - (diffIsOk, LogContext(logFile, swr, wr)) + /*res andAlso*/ diffIsOk } def run(): (TestState, Long) = { @@ -674,25 +631,25 @@ class Runner(val testFile: File, val suiteRunner: AbstractRunner) extends TestIn logFile.delete() stopwatch.start() - if (kind == "neg" || (kind endsWith "-neg")) runNegTest() - else kind match { - case "pos" => runTestCommon(true) + val state = kind match { + case "pos" => runTestCommon() + case "neg" => runNegTest() case "res" => runResidentTest() case "scalap" => runScalapTest() case "script" => runScriptTest() + case k if k.endsWith("-neg") => runNegTest() case _ => runRunTest() } - - (lastState, stopwatch.stop) + (state, stopwatch.stop) } - private def runRunTest(): Unit = { + private def runRunTest(): TestState = { val argsFile = testFile changeExtension "javaopts" val javaopts = readOptionsFile(argsFile) val execInProcess = PartestDefaults.execInProcess && javaopts.isEmpty && !Set("specialized", "instrumented").contains(testFile.getParentFile.getName) def exec() = if (execInProcess) execTestInProcess(outDir, logFile) else execTest(outDir, logFile) - def noexec() = suiteRunner.config.optNoExec && { setLastState(genSkip("no-exec: tests compiled but not run")) ; true } - runTestCommon(noexec() || exec() && diffIsOk) + def noexec() = genSkip("no-exec: tests compiled but not run") + runTestCommon(if (suiteRunner.config.optNoExec) noexec() else exec().andAlso(diffIsOk)) } private def decompileClass(clazz: Class[_], isPackageObject: Boolean): String = { @@ -721,7 +678,7 @@ class Runner(val testFile: File, val suiteRunner: AbstractRunner) extends TestIn scalap.Main.decompileScala(bytes, isPackageObject) } - def runScalapTest() = runTestCommon { + def runScalapTest(): TestState = runTestCommon { val isPackageObject = testFile.getName startsWith "package" val className = testFile.getName.stripSuffix(".scala").capitalize + (if (!isPackageObject) "" else ".package") val loader = ScalaClassLoader.fromURLs(List(outDir.toURI.toURL), this.getClass.getClassLoader) @@ -729,22 +686,21 @@ class Runner(val testFile: File, val suiteRunner: AbstractRunner) extends TestIn diffIsOk } - def runScriptTest() = { + def runScriptTest(): TestState = { import scala.sys.process._ - val (swr, wr) = newTestWriters() val args = file2String(testFile changeExtension "args") val cmdFile = if (isWin) testFile changeExtension "bat" else testFile - val succeeded = (((cmdFile + " " + args) #> logFile !) == 0) && diffIsOk + val succeeded = (((cmdFile + " " + args) #> logFile !) == 0) + + val result = if (succeeded) genPass else genFail(s"script $cmdFile failed to run") - (succeeded, LogContext(logFile, swr, wr)) + result andAlso diffIsOk } - def cleanup(): Unit = { - if (lastState.isOk) - logFile.delete() - if (!suiteRunner.debug) - Directory(outDir).deleteRecursively() + def cleanup(state: TestState): Unit = { + if (state.isOk) logFile.delete() + if (!suiteRunner.debug) Directory(outDir).deleteRecursively() } // Colorize prompts according to pass/fail diff --git a/src/partest/scala/tools/partest/package.scala b/src/partest/scala/tools/partest/package.scala index 455cf065d15c..5b231f9d0b0f 100644 --- a/src/partest/scala/tools/partest/package.scala +++ b/src/partest/scala/tools/partest/package.scala @@ -51,11 +51,13 @@ package object partest { } implicit class FileOps(val f: File) { + import scala.collection.JavaConverters._ + private def sf = SFile(f) - def testIdent = { - f.toString split """[/\\]+""" takeRight 2 mkString "/" // e.g. pos/t1234 - } + // e.g. pos/t1234 + def withEnclosing: String = f.toPath.iterator.asScala.toList.takeRight(2).mkString("/") + def testIdent = withEnclosing def mapInPlace(mapFn: String => String)(filterFn: String => Boolean = _ => true): Unit = writeAll(fileLines filter filterFn map (x => mapFn(x) + EOL): _*) @@ -83,7 +85,7 @@ package object partest { def fileLines: List[String] = fileContents.linesIfNonEmpty.toList } - implicit class PathOps(p: Path) extends FileOps(p.jfile) { } + implicit class PathOps(p: Path) extends FileOps(p.jfile) implicit class Copier(val f: SFile) extends AnyVal { def copyTo(dest: Path): Unit = dest.toFile writeAll f.slurp(scala.io.Codec.UTF8) @@ -111,16 +113,11 @@ package object partest { implicit def temporaryPath2File(x: Path): File = x.jfile implicit def stringPathToJavaFile(path: String): File = new File(path) - implicit lazy val postfixOps = scala.language.postfixOps implicit lazy val implicitConversions = scala.language.implicitConversions def fileSeparator = java.io.File.separator def pathSeparator = java.io.File.pathSeparator - def pathToTestIdent(path: Path) = path.jfile.testIdent - - def canonicalizeSlashes(line: String) = line.replaceAll("""[/\\]+""", "/") - def words(s: String): List[String] = (s.trim split "\\s+").toList def timed[T](body: => T): (T, Long) = { diff --git a/test/files/res/t687.check b/test/files/res/t687.check index 5f72c98636a9..715ff02286ad 100644 --- a/test/files/res/t687.check +++ b/test/files/res/t687.check @@ -4,5 +4,5 @@ nsc> t687/QueryB.scala:3: error: name clash between defined and inherited member def equals(x$1: Any): Boolean in class Any and override def equals(o: Object): Boolean at line 3 have same type after erasure: (x$1: Object)Boolean - override def equals(o : Object) = false; + override def equals(o : Object) = false ^ diff --git a/test/files/res/t687/QueryA.scala b/test/files/res/t687/QueryA.scala index 72365c7e7f64..939a03b6dc54 100644 --- a/test/files/res/t687/QueryA.scala +++ b/test/files/res/t687/QueryA.scala @@ -1,4 +1,4 @@ -package t687; +package t687 trait Query { - override def equals(o : Any) = false; + override def equals(o : Any) = false } diff --git a/test/files/res/t687/QueryB.scala b/test/files/res/t687/QueryB.scala index 8f6f2d9ebf26..9fc9e457da87 100644 --- a/test/files/res/t687/QueryB.scala +++ b/test/files/res/t687/QueryB.scala @@ -1,4 +1,4 @@ -package t687; +package t687 trait Query { - override def equals(o : Object) = false; + override def equals(o : Object) = false } diff --git a/test/files/run/t7096.scala b/test/files/run/t7096.scala index 08317c1e4a51..cde675acb365 100644 --- a/test/files/run/t7096.scala +++ b/test/files/run/t7096.scala @@ -47,7 +47,7 @@ abstract class CompilerTest extends DirectTest { def symbols = classes ++ terms filterNot (_ eq NoSymbol) def terms = allMembers(pkg) filter (s => s.isTerm && !s.isConstructor) def tparams = classes flatMap (_.info.typeParams) - def tpes = symbols map (_.tpe) distinct + def tpes = symbols.map(_.tpe).distinct } } From 9ed2358cf6e32b5d357a279f26cbab8455228c41 Mon Sep 17 00:00:00 2001 From: Matthew de Detrich Date: Wed, 27 Jun 2018 23:42:40 +0200 Subject: [PATCH 022/143] Simplify newBuilder --- src/library/scala/collection/immutable/LinkedMap.scala | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/library/scala/collection/immutable/LinkedMap.scala b/src/library/scala/collection/immutable/LinkedMap.scala index d3c77bd2cbf3..ccd82bca04fb 100644 --- a/src/library/scala/collection/immutable/LinkedMap.scala +++ b/src/library/scala/collection/immutable/LinkedMap.scala @@ -36,8 +36,7 @@ object LinkedMap extends MapFactory[LinkedMap] { case _ => (newBuilder[K, V] ++= it).result() } - def newBuilder[K, V]: Builder[(K, V), LinkedMap[K, V]] = - new MapFactory.Delegate[LinkedMap](VectorMap).newBuilder + def newBuilder[K, V]: Builder[(K, V), LinkedMap[K, V]] = VectorMap.newBuilder @SerialVersionUID(3L) private object EmptyLinkedMap extends LinkedMap[Any, Nothing] { From 6dda47dcec419e7cf8156dbec665e3b2847be174 Mon Sep 17 00:00:00 2001 From: Som Snytt Date: Thu, 28 Jun 2018 06:06:11 -0700 Subject: [PATCH 023/143] [nomerge] Backport REPL big print fix --- src/repl/scala/tools/nsc/interpreter/IMain.scala | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/src/repl/scala/tools/nsc/interpreter/IMain.scala b/src/repl/scala/tools/nsc/interpreter/IMain.scala index 060a6044defe..fbc6e137d0c1 100644 --- a/src/repl/scala/tools/nsc/interpreter/IMain.scala +++ b/src/repl/scala/tools/nsc/interpreter/IMain.scala @@ -925,18 +925,30 @@ class IMain(initialSettings: Settings, protected val out: JPrintWriter) extends | %s | lazy val %s: _root_.java.lang.String = %s { | %s - | ("" """.stripMargin.format( lineRep.evalName, evalResult, lineRep.printName, executionWrapper, fullAccessPath ) val postamble = """ - | ) | } |} """.stripMargin val generate = (m: MemberHandler) => m resultExtractionCode Request.this + + override def apply(contributors: List[MemberHandler]): String = stringFromWriter { code => + code println preamble + if (contributors.lengthCompare(1) > 0) { + code.println("val sb = new _root_.scala.StringBuilder") + contributors foreach (x => code.println(s"""sb.append("" ${generate(x)})""")) + code.println("sb.toString") + } else { + code.print(""""" """) // start with empty string + contributors foreach (x => code.print(generate(x))) + code.println() + } + code println postamble + } } /** Compile the object file. Returns whether the compilation succeeded. From b56769288651a6cd134e444edaae22b37dd94f71 Mon Sep 17 00:00:00 2001 From: Jason Zaugg Date: Fri, 15 Jun 2018 13:45:13 +1000 Subject: [PATCH 024/143] Override corresponds in List to avoid iterator creation --- src/library/scala/collection/immutable/List.scala | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/library/scala/collection/immutable/List.scala b/src/library/scala/collection/immutable/List.scala index d54efa3e657f..5af050605489 100644 --- a/src/library/scala/collection/immutable/List.scala +++ b/src/library/scala/collection/immutable/List.scala @@ -382,6 +382,18 @@ sealed abstract class List[+A] None } + override def corresponds[B](that: collection.Seq[B])(p: (A, B) => Boolean): Boolean = { + var i = this + var j = that + while (!(i.isEmpty || j.isEmpty)) { + if (!p(i.head, j.head)) + return false + i = i.tail + j = j.tail + } + i.isEmpty && j.isEmpty + } + override protected[this] def className = "List" /** Builds a new list by applying a function to all elements of this list. From aee6ad2c0af6950b6a30773d709587457c2cbd30 Mon Sep 17 00:00:00 2001 From: Jason Zaugg Date: Fri, 15 Jun 2018 13:48:02 +1000 Subject: [PATCH 025/143] Reuse empty iterator in Nil.iterator --- src/library/scala/collection/immutable/List.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/library/scala/collection/immutable/List.scala b/src/library/scala/collection/immutable/List.scala index 5af050605489..f51ce8ca8947 100644 --- a/src/library/scala/collection/immutable/List.scala +++ b/src/library/scala/collection/immutable/List.scala @@ -245,7 +245,6 @@ sealed abstract class List[+A] h } } - final override def flatMap[B](f: A => IterableOnce[B]): List[B] = { if (this eq Nil) Nil else { var rest = this @@ -571,6 +570,7 @@ case object Nil extends List[Nothing] { override def last: Nothing = throw new NoSuchElementException("last of empty list") override def init: Nothing = throw new UnsupportedOperationException("init of empty list") override def knownSize: Int = 0 + override def iterator: Iterator[Nothing] = Iterator.empty } /** From f73c0cfa805c80eee5e4b8dfb6e7e6fc27df08dc Mon Sep 17 00:00:00 2001 From: Jason Zaugg Date: Mon, 18 Jun 2018 10:30:31 +1000 Subject: [PATCH 026/143] Placeholder for future optimization in ChampHashMap.concat --- src/library/scala/collection/immutable/ChampHashMap.scala | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/library/scala/collection/immutable/ChampHashMap.scala b/src/library/scala/collection/immutable/ChampHashMap.scala index f38a7d946000..0aea7598a804 100644 --- a/src/library/scala/collection/immutable/ChampHashMap.scala +++ b/src/library/scala/collection/immutable/ChampHashMap.scala @@ -82,6 +82,11 @@ final class ChampHashMap[K, +V] private[immutable] (private val rootNode: MapNod else this } + override def concat[V1 >: V](that: scala.Iterable[(K, V1)]): ChampHashMap[K, V1] = { + // TODO PERF We could avoid recomputing entry hash's when `that` is another `ChampHashMap` + super.concat(that) + } + override def tail: ChampHashMap[K, V] = this - head._1 override def init: ChampHashMap[K, V] = this - last._1 From 04c56189ccdb78ac8f69b0f6df13b407bac80b68 Mon Sep 17 00:00:00 2001 From: Jason Zaugg Date: Fri, 15 Jun 2018 15:34:36 +1000 Subject: [PATCH 027/143] Less boxing in iterators More overrides of isEmpty/knownSize/keysIterator/valuesIterator and more fast paths for empty maps. --- .../scala/collection/concurrent/TrieMap.scala | 3 +- .../collection/immutable/ChampHashMap.scala | 1 + .../scala/collection/immutable/Map.scala | 80 ++++++++++++++++++- .../scala/collection/mutable/AnyRefMap.scala | 19 ++++- .../scala/collection/mutable/HashMap.scala | 20 ++++- .../scala/collection/mutable/LongMap.scala | 4 + .../collection/mutable/OpenHashMap.scala | 20 ++++- .../collection/mutable/RedBlackTree.scala | 4 +- .../scala/collection/mutable/TreeMap.scala | 20 ++++- .../scala/SerializationStabilityTest.scala | 14 ++-- 10 files changed, 158 insertions(+), 27 deletions(-) diff --git a/src/library/scala/collection/concurrent/TrieMap.scala b/src/library/scala/collection/concurrent/TrieMap.scala index 7d452b8eb72b..de6f49f039ee 100644 --- a/src/library/scala/collection/concurrent/TrieMap.scala +++ b/src/library/scala/collection/concurrent/TrieMap.scala @@ -931,9 +931,10 @@ final class TrieMap[K, V] private (r: AnyRef, rtupd: AtomicReferenceFieldUpdater insertifhc(k, hc, v, INode.KEY_PRESENT) } - def iterator: Iterator[(K, V)] = + def iterator: Iterator[(K, V)] = { if (nonReadOnly) readOnlySnapshot().iterator else new TrieMapIterator(0, this) + } //////////////////////////////////////////////////////////////////////////// // diff --git a/src/library/scala/collection/immutable/ChampHashMap.scala b/src/library/scala/collection/immutable/ChampHashMap.scala index 0aea7598a804..95225440f27a 100644 --- a/src/library/scala/collection/immutable/ChampHashMap.scala +++ b/src/library/scala/collection/immutable/ChampHashMap.scala @@ -49,6 +49,7 @@ final class ChampHashMap[K, +V] private[immutable] (private val rootNode: MapNod if (isEmpty) Iterator.empty else new MapValueIterator[K, V](rootNode) } + protected[immutable] def reverseIterator: Iterator[(K, V)] = { if (isEmpty) Iterator.empty else new MapKeyValueTupleReverseIterator[K, V](rootNode) diff --git a/src/library/scala/collection/immutable/Map.scala b/src/library/scala/collection/immutable/Map.scala index e0ded744c9de..870469d17b78 100644 --- a/src/library/scala/collection/immutable/Map.scala +++ b/src/library/scala/collection/immutable/Map.scala @@ -199,6 +199,8 @@ object Map extends MapFactory[Map] { override def getOrElse [V1 >: V](key: K, default: => V1): V1 = if (key == key1) value1 else default def iterator = Iterator.single((key1, value1)) + override def keysIterator: Iterator[K] = Iterator.single(key1) + override def valuesIterator: Iterator[V] = Iterator.single(value1) def updated[V1 >: V](key: K, value: V1): Map[K, V1] = if (key == key1) new Map1(key1, value) else new Map2(key1, value1, key, value) @@ -225,7 +227,30 @@ object Map extends MapFactory[Map] { if (key == key1) value1 else if (key == key2) value2 else default - def iterator = ((key1, value1) :: (key2, value2) :: Nil).iterator + def iterator: Iterator[(K, V)] = new Map2Iterator[(K, V)] { + override protected def nextResult(k: K, v: V): (K, V) = (k, v) + } + override def keysIterator: Iterator[K] = new Map2Iterator[K] { + override protected def nextResult(k: K, v: V): K = k + } + override def valuesIterator: Iterator[V] = new Map2Iterator[V] { + override protected def nextResult(k: K, v: V): V = v + } + + private abstract class Map2Iterator[A] extends AbstractIterator[A] { + var i = 0 + override def hasNext: Boolean = i < 2 + override def next(): A = { + val result = i match { + case 0 => nextResult(key1, value1) + case 1 => nextResult(key2, value2) + case _ => Iterator.empty.next() + } + i += 1 + result + } + protected def nextResult(k: K, v: V @uncheckedVariance): A + } def updated[V1 >: V](key: K, value: V1): Map[K, V1] = if (key == key1) new Map2(key1, value, key2, value2) else if (key == key2) new Map2(key1, value1, key2, value) @@ -258,7 +283,31 @@ object Map extends MapFactory[Map] { else if (key == key2) value2 else if (key == key3) value3 else default - def iterator = ((key1, value1) :: (key2, value2) :: (key3, value3) :: Nil).iterator + def iterator: Iterator[(K, V)] = new Map3Iterator[(K, V)] { + override protected def nextResult(k: K, v: V): (K, V) = (k, v) + } + override def keysIterator: Iterator[K] = new Map3Iterator[K] { + override protected def nextResult(k: K, v: V): K = k + } + override def valuesIterator: Iterator[V] = new Map3Iterator[V] { + override protected def nextResult(k: K, v: V): V = v + } + + private abstract class Map3Iterator[A] extends AbstractIterator[A] { + var i = 0 + override def hasNext: Boolean = i < 3 + override def next(): A = { + val result = i match { + case 0 => nextResult(key1, value1) + case 1 => nextResult(key2, value2) + case 2 => nextResult(key3, value3) + case _ => Iterator.empty.next() + } + i += 1 + result + } + protected def nextResult(k: K, v: V @uncheckedVariance): A + } def updated[V1 >: V](key: K, value: V1): Map[K, V1] = if (key == key1) new Map3(key1, value, key2, value2, key3, value3) else if (key == key2) new Map3(key1, value1, key2, value, key3, value3) @@ -296,7 +345,32 @@ object Map extends MapFactory[Map] { else if (key == key3) value3 else if (key == key4) value4 else default - def iterator = ((key1, value1) :: (key2, value2) :: (key3, value3) :: (key4, value4) :: Nil).iterator + def iterator: Iterator[(K, V)] = new Map4Iterator[(K, V)] { + override protected def nextResult(k: K, v: V): (K, V) = (k, v) + } + override def keysIterator: Iterator[K] = new Map4Iterator[K] { + override protected def nextResult(k: K, v: V): K = k + } + override def valuesIterator: Iterator[V] = new Map4Iterator[V] { + override protected def nextResult(k: K, v: V): V = v + } + + private abstract class Map4Iterator[A] extends AbstractIterator[A] { + var i = 0 + override def hasNext: Boolean = i < 4 + override def next(): A = { + val result = i match { + case 0 => nextResult(key1, value1) + case 1 => nextResult(key2, value2) + case 2 => nextResult(key3, value3) + case 3 => nextResult(key4, value4) + case _ => Iterator.empty.next() + } + i += 1 + result + } + protected def nextResult(k: K, v: V @uncheckedVariance): A + } def updated[V1 >: V](key: K, value: V1): Map[K, V1] = if (key == key1) new Map4(key1, value, key2, value2, key3, value3, key4, value4) else if (key == key2) new Map4(key1, value1, key2, value, key3, value3, key4, value4) diff --git a/src/library/scala/collection/mutable/AnyRefMap.scala b/src/library/scala/collection/mutable/AnyRefMap.scala index 0eaf5eb6a125..9c5cfb3c5f12 100644 --- a/src/library/scala/collection/mutable/AnyRefMap.scala +++ b/src/library/scala/collection/mutable/AnyRefMap.scala @@ -299,7 +299,17 @@ class AnyRefMap[K <: AnyRef, V] private[collection] (defaultEntry: K => V, initi this } - def iterator: Iterator[(K, V)] = new AbstractIterator[(K, V)] { + def iterator: Iterator[(K, V)] = new AnyRefMapIterator[(K, V)] { + protected def nextResult(k: K, v: V) = (k, v) + } + override def keysIterator: Iterator[K] = new AnyRefMapIterator[K] { + protected def nextResult(k: K, v: V) = k + } + override def valuesIterator: Iterator[V] = new AnyRefMapIterator[V] { + protected def nextResult(k: K, v: V) = v + } + + private abstract class AnyRefMapIterator[A] extends AbstractIterator[A] { private[this] val hz = _hashes private[this] val kz = _keys private[this] val vz = _values @@ -316,16 +326,19 @@ class AnyRefMap[K <: AnyRef, V] private[collection] (defaultEntry: K => V, initi true } - def next(): (K, V) = { + def next(): A = { if (hasNext) { - val ans = (kz(index).asInstanceOf[K], vz(index).asInstanceOf[V]) + val ans = nextResult(kz(index).asInstanceOf[K], vz(index).asInstanceOf[V]) index += 1 ans } else throw new NoSuchElementException("next") } + + protected def nextResult(k: K, v: V): A } + override def foreach[U](f: ((K,V)) => U): Unit = { var i = 0 var e = _size diff --git a/src/library/scala/collection/mutable/HashMap.scala b/src/library/scala/collection/mutable/HashMap.scala index 13acebccdcd4..fbb11ba4b2e1 100644 --- a/src/library/scala/collection/mutable/HashMap.scala +++ b/src/library/scala/collection/mutable/HashMap.scala @@ -1,8 +1,7 @@ package scala package collection.mutable -import scala.collection.{Iterator, MapFactory, StrictOptimizedIterableOps} - +import scala.collection.{AbstractIterator, Iterator, MapFactory, StrictOptimizedIterableOps} import java.lang.String /** This class implements mutable maps using a hashtable. @@ -38,7 +37,22 @@ class HashMap[K, V] def createNewEntry(key: K, value: V): Entry = new Entry(key, value) } - def iterator: Iterator[(K, V)] = table.entriesIterator.map(e => (e.key, e.value)) + override def isEmpty: Boolean = table.size == 0 + override def knownSize: Int = table.size + + def iterator: Iterator[(K, V)] = { + if (isEmpty) Iterator.empty + else table.entriesIterator.map(e => (e.key, e.value)) + } + + override def keysIterator: Iterator[K] = { + if (isEmpty) Iterator.empty + else table.entriesIterator.map(_.key) + } + override def valuesIterator: Iterator[V] = { + if (isEmpty) Iterator.empty + else table.entriesIterator.map(_.value) + } def get(key: K): Option[V] = { val e = table.findEntry(key) diff --git a/src/library/scala/collection/mutable/LongMap.scala b/src/library/scala/collection/mutable/LongMap.scala index 403469e62701..c467542982c3 100644 --- a/src/library/scala/collection/mutable/LongMap.scala +++ b/src/library/scala/collection/mutable/LongMap.scala @@ -403,6 +403,10 @@ final class LongMap[V] private[collection] (defaultEntry: Long => V, initialBuff } } + // TODO override these for efficiency. See immutable.LongMap for how to organize the code. + override def keysIterator: Iterator[Long] = super.keysIterator + override def valuesIterator: Iterator[V] = super.valuesIterator + override def foreach[U](f: ((Long,V)) => U): Unit = { if ((extraKeys & 1) == 1) f((0L, zeroValue.asInstanceOf[V])) if ((extraKeys & 2) == 2) f((Long.MinValue, minValue.asInstanceOf[V])) diff --git a/src/library/scala/collection/mutable/OpenHashMap.scala b/src/library/scala/collection/mutable/OpenHashMap.scala index 3829c1e7f224..d3e640dd5729 100644 --- a/src/library/scala/collection/mutable/OpenHashMap.scala +++ b/src/library/scala/collection/mutable/OpenHashMap.scala @@ -219,9 +219,20 @@ class OpenHashMap[Key, Value](initialSize : Int) * * @return the iterator */ - def iterator: Iterator[(Key, Value)] = new AbstractIterator[(Key, Value)] { - var index = 0 - val initialModCount = modCount + def iterator: Iterator[(Key, Value)] = new OpenHashMapIterator[(Key, Value)] { + override protected def nextResult(node: Entry): (Key, Value) = (node.key, node.value.get) + } + + override def keysIterator: Iterator[Key] = new OpenHashMapIterator[Key] { + override protected def nextResult(node: Entry): Key = node.key + } + override def valuesIterator: Iterator[Value] = new OpenHashMapIterator[Value] { + override protected def nextResult(node: Entry): Value = node.value.get + } + + private abstract class OpenHashMapIterator[A] extends AbstractIterator[A] { + private[this] var index = 0 + private[this] val initialModCount = modCount private[this] def advance(): Unit = { if (initialModCount != modCount) throw new ConcurrentModificationException @@ -234,8 +245,9 @@ class OpenHashMap[Key, Value](initialSize : Int) advance() val result = table(index) index += 1 - (result.key, result.value.get) + nextResult(result) } + protected def nextResult(node: Entry): A } override def clone() = { diff --git a/src/library/scala/collection/mutable/RedBlackTree.scala b/src/library/scala/collection/mutable/RedBlackTree.scala index 52448346ab40..d127cebd4145 100644 --- a/src/library/scala/collection/mutable/RedBlackTree.scala +++ b/src/library/scala/collection/mutable/RedBlackTree.scala @@ -2,9 +2,7 @@ package scala package collection.mutable import scala.annotation.tailrec -import collection.AbstractIterator -import collection.Iterator - +import collection.{AbstractIterator, Iterator} import java.lang.String /** diff --git a/src/library/scala/collection/mutable/TreeMap.scala b/src/library/scala/collection/mutable/TreeMap.scala index ce22de4e616e..4f59339db7b0 100644 --- a/src/library/scala/collection/mutable/TreeMap.scala +++ b/src/library/scala/collection/mutable/TreeMap.scala @@ -34,7 +34,20 @@ sealed class TreeMap[K, V] private (tree: RB.Tree[K, V])(implicit val ordering: */ def this()(implicit ord: Ordering[K]) = this(RB.Tree.empty)(ord) - def iterator: Iterator[(K, V)] = RB.iterator(tree) + def iterator: Iterator[(K, V)] = { + if (isEmpty) Iterator.empty + else RB.iterator(tree) + } + + override def keysIterator: Iterator[K] = { + if (isEmpty) Iterator.empty + else RB.keysIterator(tree, None) + } + + override def valuesIterator: Iterator[V] = { + if (isEmpty) Iterator.empty + else RB.valuesIterator(tree, None) + } def keysIteratorFrom(start: K): Iterator[K] = RB.keysIterator(tree, Some(start)) @@ -133,12 +146,13 @@ sealed class TreeMap[K, V] private (tree: RB.Tree[K, V])(implicit val ordering: override def get(key: K) = if (isInsideViewBounds(key)) RB.get(tree, key) else None override def iterator = RB.iterator(tree, from, until) + override def keysIterator: Iterator[K] = RB.keysIterator(tree, from, until) + override def valuesIterator: Iterator[V] = RB.valuesIterator(tree, from, until) override def keysIteratorFrom(start: K) = RB.keysIterator(tree, pickLowerBound(Some(start)), until) override def iteratorFrom(start: K) = RB.iterator(tree, pickLowerBound(Some(start)), until) override def valuesIteratorFrom(start: K) = RB.valuesIterator(tree, pickLowerBound(Some(start)), until) - override def size = iterator.length - override def isEmpty = !iterator.hasNext + override def isEmpty = RB.size(tree) == 0 || !iterator.hasNext override def contains(key: K) = isInsideViewBounds(key) && RB.contains(tree, key) override def head = headOption.get diff --git a/test/junit/scala/SerializationStabilityTest.scala b/test/junit/scala/SerializationStabilityTest.scala index 0765cd644544..698fa4396740 100644 --- a/test/junit/scala/SerializationStabilityTest.scala +++ b/test/junit/scala/SerializationStabilityTest.scala @@ -81,7 +81,7 @@ object SerializationStability { } } - // Generated on 20180605-18:45:47 with Scala version 2.13.0-20180604-234247-8dd6ca5) + // Generated on 20180619-13:58:28 with Scala version 2.13.0-20180618-031324-c034244) def main(args: Array[String]): Unit = { overwrite.foreach(updateComment) def g = Thread.currentThread.getStackTrace @@ -132,10 +132,10 @@ object SerializationStability { check(g)(new collection.convert.Wrappers.MapWrapper(immutable.Map[Int, Int](1 -> 2, 2 -> 3, 3 -> 4)))("rO0ABXNyACxzY2FsYS5jb2xsZWN0aW9uLmNvbnZlcnQuV3JhcHBlcnMkTWFwV3JhcHBlcgAAAAAAAAADAgACTAAGJG91dGVydAAjTHNjYWxhL2NvbGxlY3Rpb24vY29udmVydC9XcmFwcGVycztMADhzY2FsYSRjb2xsZWN0aW9uJGNvbnZlcnQkV3JhcHBlcnMkTWFwV3JhcHBlciQkdW5kZXJseWluZ3QAFkxzY2FsYS9jb2xsZWN0aW9uL01hcDt4cHNyACJzY2FsYS5jb2xsZWN0aW9uLmNvbnZlcnQuV3JhcHBlcnMkAAAAAAAAAAMCABFMABhEaWN0aW9uYXJ5V3JhcHBlciRtb2R1bGV0ADZMc2NhbGEvY29sbGVjdGlvbi9jb252ZXJ0L1dyYXBwZXJzJERpY3Rpb25hcnlXcmFwcGVyJDtMABZJdGVyYWJsZVdyYXBwZXIkbW9kdWxldAA0THNjYWxhL2NvbGxlY3Rpb24vY29udmVydC9XcmFwcGVycyRJdGVyYWJsZVdyYXBwZXIkO0wAFkl0ZXJhdG9yV3JhcHBlciRtb2R1bGV0ADRMc2NhbGEvY29sbGVjdGlvbi9jb252ZXJ0L1dyYXBwZXJzJEl0ZXJhdG9yV3JhcHBlciQ7TAAZSkNvbGxlY3Rpb25XcmFwcGVyJG1vZHVsZXQAN0xzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkSkNvbGxlY3Rpb25XcmFwcGVyJDtMABxKQ29uY3VycmVudE1hcFdyYXBwZXIkbW9kdWxldAA6THNjYWxhL2NvbGxlY3Rpb24vY29udmVydC9XcmFwcGVycyRKQ29uY3VycmVudE1hcFdyYXBwZXIkO0wAGUpEaWN0aW9uYXJ5V3JhcHBlciRtb2R1bGV0ADdMc2NhbGEvY29sbGVjdGlvbi9jb252ZXJ0L1dyYXBwZXJzJEpEaWN0aW9uYXJ5V3JhcHBlciQ7TAAaSkVudW1lcmF0aW9uV3JhcHBlciRtb2R1bGV0ADhMc2NhbGEvY29sbGVjdGlvbi9jb252ZXJ0L1dyYXBwZXJzJEpFbnVtZXJhdGlvbldyYXBwZXIkO0wAF0pJdGVyYWJsZVdyYXBwZXIkbW9kdWxldAA1THNjYWxhL2NvbGxlY3Rpb24vY29udmVydC9XcmFwcGVycyRKSXRlcmFibGVXcmFwcGVyJDtMABdKSXRlcmF0b3JXcmFwcGVyJG1vZHVsZXQANUxzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkSkl0ZXJhdG9yV3JhcHBlciQ7TAATSkxpc3RXcmFwcGVyJG1vZHVsZXQAMUxzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkSkxpc3RXcmFwcGVyJDtMABlKUHJvcGVydGllc1dyYXBwZXIkbW9kdWxldAA3THNjYWxhL2NvbGxlY3Rpb24vY29udmVydC9XcmFwcGVycyRKUHJvcGVydGllc1dyYXBwZXIkO0wAEkpTZXRXcmFwcGVyJG1vZHVsZXQAMExzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkSlNldFdyYXBwZXIkO0wAG011dGFibGVCdWZmZXJXcmFwcGVyJG1vZHVsZXQAOUxzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkTXV0YWJsZUJ1ZmZlcldyYXBwZXIkO0wAGE11dGFibGVNYXBXcmFwcGVyJG1vZHVsZXQANkxzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkTXV0YWJsZU1hcFdyYXBwZXIkO0wAGE11dGFibGVTZXFXcmFwcGVyJG1vZHVsZXQANkxzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkTXV0YWJsZVNlcVdyYXBwZXIkO0wAGE11dGFibGVTZXRXcmFwcGVyJG1vZHVsZXQANkxzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkTXV0YWJsZVNldFdyYXBwZXIkO0wAEVNlcVdyYXBwZXIkbW9kdWxldAAvTHNjYWxhL2NvbGxlY3Rpb24vY29udmVydC9XcmFwcGVycyRTZXFXcmFwcGVyJDt4cHBwcHBwcHBwcHBwcHBwcHBwc3IAMnNjYWxhLmNvbGxlY3Rpb24uZ2VuZXJpYy5EZWZhdWx0U2VyaWFsaXphdGlvblByb3h5AAAAAAAAAAMDAAFMAAdmYWN0b3J5dAAaTHNjYWxhL2NvbGxlY3Rpb24vRmFjdG9yeTt4cHNyACVzY2FsYS5jb2xsZWN0aW9uLk1hcEZhY3RvcnkkVG9GYWN0b3J5AAAAAAAAAAMCAAFMAAdmYWN0b3J5dAAdTHNjYWxhL2NvbGxlY3Rpb24vTWFwRmFjdG9yeTt4cHNyAB9zY2FsYS5jb2xsZWN0aW9uLmltbXV0YWJsZS5NYXAkAAAAAAAAAAMDAAFaACtzY2FsYSRjb2xsZWN0aW9uJGltbXV0YWJsZSRNYXAkJHVzZUJhc2VsaW5leHB4dwQAAAADc3IADHNjYWxhLlR1cGxlMi6UZn1bkvn1AgACTAACXzF0ABJMamF2YS9sYW5nL09iamVjdDtMAAJfMnEAfgAgeHBzcgARamF2YS5sYW5nLkludGVnZXIS4qCk94GHOAIAAUkABXZhbHVleHIAEGphdmEubGFuZy5OdW1iZXKGrJUdC5TgiwIAAHhwAAAAAXNxAH4AIgAAAAJzcQB+AB9xAH4AJXNxAH4AIgAAAANzcQB+AB9xAH4AJ3NxAH4AIgAAAAR4") check(g)(new collection.convert.Wrappers.MapWrapper(immutable.Map[Int, Int](1 -> 2, 2 -> 3, 3 -> 4, 4 -> 5)))("rO0ABXNyACxzY2FsYS5jb2xsZWN0aW9uLmNvbnZlcnQuV3JhcHBlcnMkTWFwV3JhcHBlcgAAAAAAAAADAgACTAAGJG91dGVydAAjTHNjYWxhL2NvbGxlY3Rpb24vY29udmVydC9XcmFwcGVycztMADhzY2FsYSRjb2xsZWN0aW9uJGNvbnZlcnQkV3JhcHBlcnMkTWFwV3JhcHBlciQkdW5kZXJseWluZ3QAFkxzY2FsYS9jb2xsZWN0aW9uL01hcDt4cHNyACJzY2FsYS5jb2xsZWN0aW9uLmNvbnZlcnQuV3JhcHBlcnMkAAAAAAAAAAMCABFMABhEaWN0aW9uYXJ5V3JhcHBlciRtb2R1bGV0ADZMc2NhbGEvY29sbGVjdGlvbi9jb252ZXJ0L1dyYXBwZXJzJERpY3Rpb25hcnlXcmFwcGVyJDtMABZJdGVyYWJsZVdyYXBwZXIkbW9kdWxldAA0THNjYWxhL2NvbGxlY3Rpb24vY29udmVydC9XcmFwcGVycyRJdGVyYWJsZVdyYXBwZXIkO0wAFkl0ZXJhdG9yV3JhcHBlciRtb2R1bGV0ADRMc2NhbGEvY29sbGVjdGlvbi9jb252ZXJ0L1dyYXBwZXJzJEl0ZXJhdG9yV3JhcHBlciQ7TAAZSkNvbGxlY3Rpb25XcmFwcGVyJG1vZHVsZXQAN0xzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkSkNvbGxlY3Rpb25XcmFwcGVyJDtMABxKQ29uY3VycmVudE1hcFdyYXBwZXIkbW9kdWxldAA6THNjYWxhL2NvbGxlY3Rpb24vY29udmVydC9XcmFwcGVycyRKQ29uY3VycmVudE1hcFdyYXBwZXIkO0wAGUpEaWN0aW9uYXJ5V3JhcHBlciRtb2R1bGV0ADdMc2NhbGEvY29sbGVjdGlvbi9jb252ZXJ0L1dyYXBwZXJzJEpEaWN0aW9uYXJ5V3JhcHBlciQ7TAAaSkVudW1lcmF0aW9uV3JhcHBlciRtb2R1bGV0ADhMc2NhbGEvY29sbGVjdGlvbi9jb252ZXJ0L1dyYXBwZXJzJEpFbnVtZXJhdGlvbldyYXBwZXIkO0wAF0pJdGVyYWJsZVdyYXBwZXIkbW9kdWxldAA1THNjYWxhL2NvbGxlY3Rpb24vY29udmVydC9XcmFwcGVycyRKSXRlcmFibGVXcmFwcGVyJDtMABdKSXRlcmF0b3JXcmFwcGVyJG1vZHVsZXQANUxzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkSkl0ZXJhdG9yV3JhcHBlciQ7TAATSkxpc3RXcmFwcGVyJG1vZHVsZXQAMUxzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkSkxpc3RXcmFwcGVyJDtMABlKUHJvcGVydGllc1dyYXBwZXIkbW9kdWxldAA3THNjYWxhL2NvbGxlY3Rpb24vY29udmVydC9XcmFwcGVycyRKUHJvcGVydGllc1dyYXBwZXIkO0wAEkpTZXRXcmFwcGVyJG1vZHVsZXQAMExzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkSlNldFdyYXBwZXIkO0wAG011dGFibGVCdWZmZXJXcmFwcGVyJG1vZHVsZXQAOUxzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkTXV0YWJsZUJ1ZmZlcldyYXBwZXIkO0wAGE11dGFibGVNYXBXcmFwcGVyJG1vZHVsZXQANkxzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkTXV0YWJsZU1hcFdyYXBwZXIkO0wAGE11dGFibGVTZXFXcmFwcGVyJG1vZHVsZXQANkxzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkTXV0YWJsZVNlcVdyYXBwZXIkO0wAGE11dGFibGVTZXRXcmFwcGVyJG1vZHVsZXQANkxzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkTXV0YWJsZVNldFdyYXBwZXIkO0wAEVNlcVdyYXBwZXIkbW9kdWxldAAvTHNjYWxhL2NvbGxlY3Rpb24vY29udmVydC9XcmFwcGVycyRTZXFXcmFwcGVyJDt4cHBwcHBwcHBwcHBwcHBwcHBwc3IAMnNjYWxhLmNvbGxlY3Rpb24uZ2VuZXJpYy5EZWZhdWx0U2VyaWFsaXphdGlvblByb3h5AAAAAAAAAAMDAAFMAAdmYWN0b3J5dAAaTHNjYWxhL2NvbGxlY3Rpb24vRmFjdG9yeTt4cHNyACVzY2FsYS5jb2xsZWN0aW9uLk1hcEZhY3RvcnkkVG9GYWN0b3J5AAAAAAAAAAMCAAFMAAdmYWN0b3J5dAAdTHNjYWxhL2NvbGxlY3Rpb24vTWFwRmFjdG9yeTt4cHNyAB9zY2FsYS5jb2xsZWN0aW9uLmltbXV0YWJsZS5NYXAkAAAAAAAAAAMDAAFaACtzY2FsYSRjb2xsZWN0aW9uJGltbXV0YWJsZSRNYXAkJHVzZUJhc2VsaW5leHB4dwQAAAAEc3IADHNjYWxhLlR1cGxlMi6UZn1bkvn1AgACTAACXzF0ABJMamF2YS9sYW5nL09iamVjdDtMAAJfMnEAfgAgeHBzcgARamF2YS5sYW5nLkludGVnZXIS4qCk94GHOAIAAUkABXZhbHVleHIAEGphdmEubGFuZy5OdW1iZXKGrJUdC5TgiwIAAHhwAAAAAXNxAH4AIgAAAAJzcQB+AB9xAH4AJXNxAH4AIgAAAANzcQB+AB9xAH4AJ3NxAH4AIgAAAARzcQB+AB9xAH4AKXNxAH4AIgAAAAV4") check(g)(new collection.convert.Wrappers.MapWrapper(immutable.Map[Int, Int](1 -> 2, 2 -> 3, 3 -> 4, 4 -> 5, 5 -> 6)))("rO0ABXNyACxzY2FsYS5jb2xsZWN0aW9uLmNvbnZlcnQuV3JhcHBlcnMkTWFwV3JhcHBlcgAAAAAAAAADAgACTAAGJG91dGVydAAjTHNjYWxhL2NvbGxlY3Rpb24vY29udmVydC9XcmFwcGVycztMADhzY2FsYSRjb2xsZWN0aW9uJGNvbnZlcnQkV3JhcHBlcnMkTWFwV3JhcHBlciQkdW5kZXJseWluZ3QAFkxzY2FsYS9jb2xsZWN0aW9uL01hcDt4cHNyACJzY2FsYS5jb2xsZWN0aW9uLmNvbnZlcnQuV3JhcHBlcnMkAAAAAAAAAAMCABFMABhEaWN0aW9uYXJ5V3JhcHBlciRtb2R1bGV0ADZMc2NhbGEvY29sbGVjdGlvbi9jb252ZXJ0L1dyYXBwZXJzJERpY3Rpb25hcnlXcmFwcGVyJDtMABZJdGVyYWJsZVdyYXBwZXIkbW9kdWxldAA0THNjYWxhL2NvbGxlY3Rpb24vY29udmVydC9XcmFwcGVycyRJdGVyYWJsZVdyYXBwZXIkO0wAFkl0ZXJhdG9yV3JhcHBlciRtb2R1bGV0ADRMc2NhbGEvY29sbGVjdGlvbi9jb252ZXJ0L1dyYXBwZXJzJEl0ZXJhdG9yV3JhcHBlciQ7TAAZSkNvbGxlY3Rpb25XcmFwcGVyJG1vZHVsZXQAN0xzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkSkNvbGxlY3Rpb25XcmFwcGVyJDtMABxKQ29uY3VycmVudE1hcFdyYXBwZXIkbW9kdWxldAA6THNjYWxhL2NvbGxlY3Rpb24vY29udmVydC9XcmFwcGVycyRKQ29uY3VycmVudE1hcFdyYXBwZXIkO0wAGUpEaWN0aW9uYXJ5V3JhcHBlciRtb2R1bGV0ADdMc2NhbGEvY29sbGVjdGlvbi9jb252ZXJ0L1dyYXBwZXJzJEpEaWN0aW9uYXJ5V3JhcHBlciQ7TAAaSkVudW1lcmF0aW9uV3JhcHBlciRtb2R1bGV0ADhMc2NhbGEvY29sbGVjdGlvbi9jb252ZXJ0L1dyYXBwZXJzJEpFbnVtZXJhdGlvbldyYXBwZXIkO0wAF0pJdGVyYWJsZVdyYXBwZXIkbW9kdWxldAA1THNjYWxhL2NvbGxlY3Rpb24vY29udmVydC9XcmFwcGVycyRKSXRlcmFibGVXcmFwcGVyJDtMABdKSXRlcmF0b3JXcmFwcGVyJG1vZHVsZXQANUxzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkSkl0ZXJhdG9yV3JhcHBlciQ7TAATSkxpc3RXcmFwcGVyJG1vZHVsZXQAMUxzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkSkxpc3RXcmFwcGVyJDtMABlKUHJvcGVydGllc1dyYXBwZXIkbW9kdWxldAA3THNjYWxhL2NvbGxlY3Rpb24vY29udmVydC9XcmFwcGVycyRKUHJvcGVydGllc1dyYXBwZXIkO0wAEkpTZXRXcmFwcGVyJG1vZHVsZXQAMExzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkSlNldFdyYXBwZXIkO0wAG011dGFibGVCdWZmZXJXcmFwcGVyJG1vZHVsZXQAOUxzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkTXV0YWJsZUJ1ZmZlcldyYXBwZXIkO0wAGE11dGFibGVNYXBXcmFwcGVyJG1vZHVsZXQANkxzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkTXV0YWJsZU1hcFdyYXBwZXIkO0wAGE11dGFibGVTZXFXcmFwcGVyJG1vZHVsZXQANkxzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkTXV0YWJsZVNlcVdyYXBwZXIkO0wAGE11dGFibGVTZXRXcmFwcGVyJG1vZHVsZXQANkxzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkTXV0YWJsZVNldFdyYXBwZXIkO0wAEVNlcVdyYXBwZXIkbW9kdWxldAAvTHNjYWxhL2NvbGxlY3Rpb24vY29udmVydC9XcmFwcGVycyRTZXFXcmFwcGVyJDt4cHBwcHBwcHBwcHBwcHBwcHBwc3IAMnNjYWxhLmNvbGxlY3Rpb24uZ2VuZXJpYy5EZWZhdWx0U2VyaWFsaXphdGlvblByb3h5AAAAAAAAAAMDAAFMAAdmYWN0b3J5dAAaTHNjYWxhL2NvbGxlY3Rpb24vRmFjdG9yeTt4cHNyACVzY2FsYS5jb2xsZWN0aW9uLk1hcEZhY3RvcnkkVG9GYWN0b3J5AAAAAAAAAAMCAAFMAAdmYWN0b3J5dAAdTHNjYWxhL2NvbGxlY3Rpb24vTWFwRmFjdG9yeTt4cHNyAChzY2FsYS5jb2xsZWN0aW9uLmltbXV0YWJsZS5DaGFtcEhhc2hNYXAkAAAAAAAAAAMDAAFMAAhFbXB0eU1hcHQAKUxzY2FsYS9jb2xsZWN0aW9uL2ltbXV0YWJsZS9DaGFtcEhhc2hNYXA7eHB4dwQAAAAFc3IADHNjYWxhLlR1cGxlMi6UZn1bkvn1AgACTAACXzF0ABJMamF2YS9sYW5nL09iamVjdDtMAAJfMnEAfgAheHBzcgARamF2YS5sYW5nLkludGVnZXIS4qCk94GHOAIAAUkABXZhbHVleHIAEGphdmEubGFuZy5OdW1iZXKGrJUdC5TgiwIAAHhwAAAABXNxAH4AIwAAAAZzcQB+ACBzcQB+ACMAAAABc3EAfgAjAAAAAnNxAH4AIHEAfgApc3EAfgAjAAAAA3NxAH4AIHEAfgArc3EAfgAjAAAABHNxAH4AIHEAfgAtcQB+ACV4") - check(g)(new collection.convert.Wrappers.MapWrapper(mutable.Map()))("rO0ABXNyACxzY2FsYS5jb2xsZWN0aW9uLmNvbnZlcnQuV3JhcHBlcnMkTWFwV3JhcHBlcgAAAAAAAAADAgACTAAGJG91dGVydAAjTHNjYWxhL2NvbGxlY3Rpb24vY29udmVydC9XcmFwcGVycztMADhzY2FsYSRjb2xsZWN0aW9uJGNvbnZlcnQkV3JhcHBlcnMkTWFwV3JhcHBlciQkdW5kZXJseWluZ3QAFkxzY2FsYS9jb2xsZWN0aW9uL01hcDt4cHNyACJzY2FsYS5jb2xsZWN0aW9uLmNvbnZlcnQuV3JhcHBlcnMkAAAAAAAAAAMCABFMABhEaWN0aW9uYXJ5V3JhcHBlciRtb2R1bGV0ADZMc2NhbGEvY29sbGVjdGlvbi9jb252ZXJ0L1dyYXBwZXJzJERpY3Rpb25hcnlXcmFwcGVyJDtMABZJdGVyYWJsZVdyYXBwZXIkbW9kdWxldAA0THNjYWxhL2NvbGxlY3Rpb24vY29udmVydC9XcmFwcGVycyRJdGVyYWJsZVdyYXBwZXIkO0wAFkl0ZXJhdG9yV3JhcHBlciRtb2R1bGV0ADRMc2NhbGEvY29sbGVjdGlvbi9jb252ZXJ0L1dyYXBwZXJzJEl0ZXJhdG9yV3JhcHBlciQ7TAAZSkNvbGxlY3Rpb25XcmFwcGVyJG1vZHVsZXQAN0xzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkSkNvbGxlY3Rpb25XcmFwcGVyJDtMABxKQ29uY3VycmVudE1hcFdyYXBwZXIkbW9kdWxldAA6THNjYWxhL2NvbGxlY3Rpb24vY29udmVydC9XcmFwcGVycyRKQ29uY3VycmVudE1hcFdyYXBwZXIkO0wAGUpEaWN0aW9uYXJ5V3JhcHBlciRtb2R1bGV0ADdMc2NhbGEvY29sbGVjdGlvbi9jb252ZXJ0L1dyYXBwZXJzJEpEaWN0aW9uYXJ5V3JhcHBlciQ7TAAaSkVudW1lcmF0aW9uV3JhcHBlciRtb2R1bGV0ADhMc2NhbGEvY29sbGVjdGlvbi9jb252ZXJ0L1dyYXBwZXJzJEpFbnVtZXJhdGlvbldyYXBwZXIkO0wAF0pJdGVyYWJsZVdyYXBwZXIkbW9kdWxldAA1THNjYWxhL2NvbGxlY3Rpb24vY29udmVydC9XcmFwcGVycyRKSXRlcmFibGVXcmFwcGVyJDtMABdKSXRlcmF0b3JXcmFwcGVyJG1vZHVsZXQANUxzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkSkl0ZXJhdG9yV3JhcHBlciQ7TAATSkxpc3RXcmFwcGVyJG1vZHVsZXQAMUxzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkSkxpc3RXcmFwcGVyJDtMABlKUHJvcGVydGllc1dyYXBwZXIkbW9kdWxldAA3THNjYWxhL2NvbGxlY3Rpb24vY29udmVydC9XcmFwcGVycyRKUHJvcGVydGllc1dyYXBwZXIkO0wAEkpTZXRXcmFwcGVyJG1vZHVsZXQAMExzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkSlNldFdyYXBwZXIkO0wAG011dGFibGVCdWZmZXJXcmFwcGVyJG1vZHVsZXQAOUxzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkTXV0YWJsZUJ1ZmZlcldyYXBwZXIkO0wAGE11dGFibGVNYXBXcmFwcGVyJG1vZHVsZXQANkxzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkTXV0YWJsZU1hcFdyYXBwZXIkO0wAGE11dGFibGVTZXFXcmFwcGVyJG1vZHVsZXQANkxzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkTXV0YWJsZVNlcVdyYXBwZXIkO0wAGE11dGFibGVTZXRXcmFwcGVyJG1vZHVsZXQANkxzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkTXV0YWJsZVNldFdyYXBwZXIkO0wAEVNlcVdyYXBwZXIkbW9kdWxldAAvTHNjYWxhL2NvbGxlY3Rpb24vY29udmVydC9XcmFwcGVycyRTZXFXcmFwcGVyJDt4cHBwcHBwcHBwcHBwcHBwcHBwc3IAMnNjYWxhLmNvbGxlY3Rpb24uZ2VuZXJpYy5EZWZhdWx0U2VyaWFsaXphdGlvblByb3h5AAAAAAAAAAMDAAFMAAdmYWN0b3J5dAAaTHNjYWxhL2NvbGxlY3Rpb24vRmFjdG9yeTt4cHNyACVzY2FsYS5jb2xsZWN0aW9uLk1hcEZhY3RvcnkkVG9GYWN0b3J5AAAAAAAAAAMCAAFMAAdmYWN0b3J5dAAdTHNjYWxhL2NvbGxlY3Rpb24vTWFwRmFjdG9yeTt4cHNyACFzY2FsYS5jb2xsZWN0aW9uLm11dGFibGUuSGFzaE1hcCQAAAAAAAAAAwIAAHhwdwT/////c3IAJnNjYWxhLmNvbGxlY3Rpb24uZ2VuZXJpYy5TZXJpYWxpemVFbmQkAAAAAAAAAAMCAAB4cHg=") - check(g)(new collection.convert.Wrappers.MapWrapper(mutable.Map[Int, Int](1 -> 2, 2 -> 3, 3 -> 4)))("rO0ABXNyACxzY2FsYS5jb2xsZWN0aW9uLmNvbnZlcnQuV3JhcHBlcnMkTWFwV3JhcHBlcgAAAAAAAAADAgACTAAGJG91dGVydAAjTHNjYWxhL2NvbGxlY3Rpb24vY29udmVydC9XcmFwcGVycztMADhzY2FsYSRjb2xsZWN0aW9uJGNvbnZlcnQkV3JhcHBlcnMkTWFwV3JhcHBlciQkdW5kZXJseWluZ3QAFkxzY2FsYS9jb2xsZWN0aW9uL01hcDt4cHNyACJzY2FsYS5jb2xsZWN0aW9uLmNvbnZlcnQuV3JhcHBlcnMkAAAAAAAAAAMCABFMABhEaWN0aW9uYXJ5V3JhcHBlciRtb2R1bGV0ADZMc2NhbGEvY29sbGVjdGlvbi9jb252ZXJ0L1dyYXBwZXJzJERpY3Rpb25hcnlXcmFwcGVyJDtMABZJdGVyYWJsZVdyYXBwZXIkbW9kdWxldAA0THNjYWxhL2NvbGxlY3Rpb24vY29udmVydC9XcmFwcGVycyRJdGVyYWJsZVdyYXBwZXIkO0wAFkl0ZXJhdG9yV3JhcHBlciRtb2R1bGV0ADRMc2NhbGEvY29sbGVjdGlvbi9jb252ZXJ0L1dyYXBwZXJzJEl0ZXJhdG9yV3JhcHBlciQ7TAAZSkNvbGxlY3Rpb25XcmFwcGVyJG1vZHVsZXQAN0xzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkSkNvbGxlY3Rpb25XcmFwcGVyJDtMABxKQ29uY3VycmVudE1hcFdyYXBwZXIkbW9kdWxldAA6THNjYWxhL2NvbGxlY3Rpb24vY29udmVydC9XcmFwcGVycyRKQ29uY3VycmVudE1hcFdyYXBwZXIkO0wAGUpEaWN0aW9uYXJ5V3JhcHBlciRtb2R1bGV0ADdMc2NhbGEvY29sbGVjdGlvbi9jb252ZXJ0L1dyYXBwZXJzJEpEaWN0aW9uYXJ5V3JhcHBlciQ7TAAaSkVudW1lcmF0aW9uV3JhcHBlciRtb2R1bGV0ADhMc2NhbGEvY29sbGVjdGlvbi9jb252ZXJ0L1dyYXBwZXJzJEpFbnVtZXJhdGlvbldyYXBwZXIkO0wAF0pJdGVyYWJsZVdyYXBwZXIkbW9kdWxldAA1THNjYWxhL2NvbGxlY3Rpb24vY29udmVydC9XcmFwcGVycyRKSXRlcmFibGVXcmFwcGVyJDtMABdKSXRlcmF0b3JXcmFwcGVyJG1vZHVsZXQANUxzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkSkl0ZXJhdG9yV3JhcHBlciQ7TAATSkxpc3RXcmFwcGVyJG1vZHVsZXQAMUxzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkSkxpc3RXcmFwcGVyJDtMABlKUHJvcGVydGllc1dyYXBwZXIkbW9kdWxldAA3THNjYWxhL2NvbGxlY3Rpb24vY29udmVydC9XcmFwcGVycyRKUHJvcGVydGllc1dyYXBwZXIkO0wAEkpTZXRXcmFwcGVyJG1vZHVsZXQAMExzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkSlNldFdyYXBwZXIkO0wAG011dGFibGVCdWZmZXJXcmFwcGVyJG1vZHVsZXQAOUxzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkTXV0YWJsZUJ1ZmZlcldyYXBwZXIkO0wAGE11dGFibGVNYXBXcmFwcGVyJG1vZHVsZXQANkxzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkTXV0YWJsZU1hcFdyYXBwZXIkO0wAGE11dGFibGVTZXFXcmFwcGVyJG1vZHVsZXQANkxzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkTXV0YWJsZVNlcVdyYXBwZXIkO0wAGE11dGFibGVTZXRXcmFwcGVyJG1vZHVsZXQANkxzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkTXV0YWJsZVNldFdyYXBwZXIkO0wAEVNlcVdyYXBwZXIkbW9kdWxldAAvTHNjYWxhL2NvbGxlY3Rpb24vY29udmVydC9XcmFwcGVycyRTZXFXcmFwcGVyJDt4cHBwcHBwcHBwcHBwcHBwcHBwc3IAMnNjYWxhLmNvbGxlY3Rpb24uZ2VuZXJpYy5EZWZhdWx0U2VyaWFsaXphdGlvblByb3h5AAAAAAAAAAMDAAFMAAdmYWN0b3J5dAAaTHNjYWxhL2NvbGxlY3Rpb24vRmFjdG9yeTt4cHNyACVzY2FsYS5jb2xsZWN0aW9uLk1hcEZhY3RvcnkkVG9GYWN0b3J5AAAAAAAAAAMCAAFMAAdmYWN0b3J5dAAdTHNjYWxhL2NvbGxlY3Rpb24vTWFwRmFjdG9yeTt4cHNyACFzY2FsYS5jb2xsZWN0aW9uLm11dGFibGUuSGFzaE1hcCQAAAAAAAAAAwIAAHhwdwT/////c3IADHNjYWxhLlR1cGxlMi6UZn1bkvn1AgACTAACXzF0ABJMamF2YS9sYW5nL09iamVjdDtMAAJfMnEAfgAgeHBzcgARamF2YS5sYW5nLkludGVnZXIS4qCk94GHOAIAAUkABXZhbHVleHIAEGphdmEubGFuZy5OdW1iZXKGrJUdC5TgiwIAAHhwAAAAAnNxAH4AIgAAAANzcQB+AB9zcQB+ACIAAAABcQB+ACRzcQB+AB9xAH4AJXNxAH4AIgAAAARzcgAmc2NhbGEuY29sbGVjdGlvbi5nZW5lcmljLlNlcmlhbGl6ZUVuZCQAAAAAAAAAAwIAAHhweA==") - check(g)(new collection.convert.Wrappers.MutableMapWrapper(mutable.Map()))("rO0ABXNyADNzY2FsYS5jb2xsZWN0aW9uLmNvbnZlcnQuV3JhcHBlcnMkTXV0YWJsZU1hcFdyYXBwZXIAAAAAAAAAAwIAAUwACnVuZGVybHlpbmd0AB5Mc2NhbGEvY29sbGVjdGlvbi9tdXRhYmxlL01hcDt4cgAsc2NhbGEuY29sbGVjdGlvbi5jb252ZXJ0LldyYXBwZXJzJE1hcFdyYXBwZXIAAAAAAAAAAwIAAkwABiRvdXRlcnQAI0xzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnM7TAA4c2NhbGEkY29sbGVjdGlvbiRjb252ZXJ0JFdyYXBwZXJzJE1hcFdyYXBwZXIkJHVuZGVybHlpbmd0ABZMc2NhbGEvY29sbGVjdGlvbi9NYXA7eHBzcgAic2NhbGEuY29sbGVjdGlvbi5jb252ZXJ0LldyYXBwZXJzJAAAAAAAAAADAgARTAAYRGljdGlvbmFyeVdyYXBwZXIkbW9kdWxldAA2THNjYWxhL2NvbGxlY3Rpb24vY29udmVydC9XcmFwcGVycyREaWN0aW9uYXJ5V3JhcHBlciQ7TAAWSXRlcmFibGVXcmFwcGVyJG1vZHVsZXQANExzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkSXRlcmFibGVXcmFwcGVyJDtMABZJdGVyYXRvcldyYXBwZXIkbW9kdWxldAA0THNjYWxhL2NvbGxlY3Rpb24vY29udmVydC9XcmFwcGVycyRJdGVyYXRvcldyYXBwZXIkO0wAGUpDb2xsZWN0aW9uV3JhcHBlciRtb2R1bGV0ADdMc2NhbGEvY29sbGVjdGlvbi9jb252ZXJ0L1dyYXBwZXJzJEpDb2xsZWN0aW9uV3JhcHBlciQ7TAAcSkNvbmN1cnJlbnRNYXBXcmFwcGVyJG1vZHVsZXQAOkxzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkSkNvbmN1cnJlbnRNYXBXcmFwcGVyJDtMABlKRGljdGlvbmFyeVdyYXBwZXIkbW9kdWxldAA3THNjYWxhL2NvbGxlY3Rpb24vY29udmVydC9XcmFwcGVycyRKRGljdGlvbmFyeVdyYXBwZXIkO0wAGkpFbnVtZXJhdGlvbldyYXBwZXIkbW9kdWxldAA4THNjYWxhL2NvbGxlY3Rpb24vY29udmVydC9XcmFwcGVycyRKRW51bWVyYXRpb25XcmFwcGVyJDtMABdKSXRlcmFibGVXcmFwcGVyJG1vZHVsZXQANUxzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkSkl0ZXJhYmxlV3JhcHBlciQ7TAAXSkl0ZXJhdG9yV3JhcHBlciRtb2R1bGV0ADVMc2NhbGEvY29sbGVjdGlvbi9jb252ZXJ0L1dyYXBwZXJzJEpJdGVyYXRvcldyYXBwZXIkO0wAE0pMaXN0V3JhcHBlciRtb2R1bGV0ADFMc2NhbGEvY29sbGVjdGlvbi9jb252ZXJ0L1dyYXBwZXJzJEpMaXN0V3JhcHBlciQ7TAAZSlByb3BlcnRpZXNXcmFwcGVyJG1vZHVsZXQAN0xzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkSlByb3BlcnRpZXNXcmFwcGVyJDtMABJKU2V0V3JhcHBlciRtb2R1bGV0ADBMc2NhbGEvY29sbGVjdGlvbi9jb252ZXJ0L1dyYXBwZXJzJEpTZXRXcmFwcGVyJDtMABtNdXRhYmxlQnVmZmVyV3JhcHBlciRtb2R1bGV0ADlMc2NhbGEvY29sbGVjdGlvbi9jb252ZXJ0L1dyYXBwZXJzJE11dGFibGVCdWZmZXJXcmFwcGVyJDtMABhNdXRhYmxlTWFwV3JhcHBlciRtb2R1bGV0ADZMc2NhbGEvY29sbGVjdGlvbi9jb252ZXJ0L1dyYXBwZXJzJE11dGFibGVNYXBXcmFwcGVyJDtMABhNdXRhYmxlU2VxV3JhcHBlciRtb2R1bGV0ADZMc2NhbGEvY29sbGVjdGlvbi9jb252ZXJ0L1dyYXBwZXJzJE11dGFibGVTZXFXcmFwcGVyJDtMABhNdXRhYmxlU2V0V3JhcHBlciRtb2R1bGV0ADZMc2NhbGEvY29sbGVjdGlvbi9jb252ZXJ0L1dyYXBwZXJzJE11dGFibGVTZXRXcmFwcGVyJDtMABFTZXFXcmFwcGVyJG1vZHVsZXQAL0xzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkU2VxV3JhcHBlciQ7eHBwcHBwcHBwcHBwcHBwcHBwcHNyADJzY2FsYS5jb2xsZWN0aW9uLmdlbmVyaWMuRGVmYXVsdFNlcmlhbGl6YXRpb25Qcm94eQAAAAAAAAADAwABTAAHZmFjdG9yeXQAGkxzY2FsYS9jb2xsZWN0aW9uL0ZhY3Rvcnk7eHBzcgAlc2NhbGEuY29sbGVjdGlvbi5NYXBGYWN0b3J5JFRvRmFjdG9yeQAAAAAAAAADAgABTAAHZmFjdG9yeXQAHUxzY2FsYS9jb2xsZWN0aW9uL01hcEZhY3Rvcnk7eHBzcgAhc2NhbGEuY29sbGVjdGlvbi5tdXRhYmxlLkhhc2hNYXAkAAAAAAAAAAMCAAB4cHcE/////3NyACZzY2FsYS5jb2xsZWN0aW9uLmdlbmVyaWMuU2VyaWFsaXplRW5kJAAAAAAAAAADAgAAeHB4cQB+ABs=") - check(g)(new collection.convert.Wrappers.MutableMapWrapper(mutable.Map[Int, Int](1 -> 2, 2 -> 3, 3 -> 4)))("rO0ABXNyADNzY2FsYS5jb2xsZWN0aW9uLmNvbnZlcnQuV3JhcHBlcnMkTXV0YWJsZU1hcFdyYXBwZXIAAAAAAAAAAwIAAUwACnVuZGVybHlpbmd0AB5Mc2NhbGEvY29sbGVjdGlvbi9tdXRhYmxlL01hcDt4cgAsc2NhbGEuY29sbGVjdGlvbi5jb252ZXJ0LldyYXBwZXJzJE1hcFdyYXBwZXIAAAAAAAAAAwIAAkwABiRvdXRlcnQAI0xzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnM7TAA4c2NhbGEkY29sbGVjdGlvbiRjb252ZXJ0JFdyYXBwZXJzJE1hcFdyYXBwZXIkJHVuZGVybHlpbmd0ABZMc2NhbGEvY29sbGVjdGlvbi9NYXA7eHBzcgAic2NhbGEuY29sbGVjdGlvbi5jb252ZXJ0LldyYXBwZXJzJAAAAAAAAAADAgARTAAYRGljdGlvbmFyeVdyYXBwZXIkbW9kdWxldAA2THNjYWxhL2NvbGxlY3Rpb24vY29udmVydC9XcmFwcGVycyREaWN0aW9uYXJ5V3JhcHBlciQ7TAAWSXRlcmFibGVXcmFwcGVyJG1vZHVsZXQANExzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkSXRlcmFibGVXcmFwcGVyJDtMABZJdGVyYXRvcldyYXBwZXIkbW9kdWxldAA0THNjYWxhL2NvbGxlY3Rpb24vY29udmVydC9XcmFwcGVycyRJdGVyYXRvcldyYXBwZXIkO0wAGUpDb2xsZWN0aW9uV3JhcHBlciRtb2R1bGV0ADdMc2NhbGEvY29sbGVjdGlvbi9jb252ZXJ0L1dyYXBwZXJzJEpDb2xsZWN0aW9uV3JhcHBlciQ7TAAcSkNvbmN1cnJlbnRNYXBXcmFwcGVyJG1vZHVsZXQAOkxzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkSkNvbmN1cnJlbnRNYXBXcmFwcGVyJDtMABlKRGljdGlvbmFyeVdyYXBwZXIkbW9kdWxldAA3THNjYWxhL2NvbGxlY3Rpb24vY29udmVydC9XcmFwcGVycyRKRGljdGlvbmFyeVdyYXBwZXIkO0wAGkpFbnVtZXJhdGlvbldyYXBwZXIkbW9kdWxldAA4THNjYWxhL2NvbGxlY3Rpb24vY29udmVydC9XcmFwcGVycyRKRW51bWVyYXRpb25XcmFwcGVyJDtMABdKSXRlcmFibGVXcmFwcGVyJG1vZHVsZXQANUxzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkSkl0ZXJhYmxlV3JhcHBlciQ7TAAXSkl0ZXJhdG9yV3JhcHBlciRtb2R1bGV0ADVMc2NhbGEvY29sbGVjdGlvbi9jb252ZXJ0L1dyYXBwZXJzJEpJdGVyYXRvcldyYXBwZXIkO0wAE0pMaXN0V3JhcHBlciRtb2R1bGV0ADFMc2NhbGEvY29sbGVjdGlvbi9jb252ZXJ0L1dyYXBwZXJzJEpMaXN0V3JhcHBlciQ7TAAZSlByb3BlcnRpZXNXcmFwcGVyJG1vZHVsZXQAN0xzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkSlByb3BlcnRpZXNXcmFwcGVyJDtMABJKU2V0V3JhcHBlciRtb2R1bGV0ADBMc2NhbGEvY29sbGVjdGlvbi9jb252ZXJ0L1dyYXBwZXJzJEpTZXRXcmFwcGVyJDtMABtNdXRhYmxlQnVmZmVyV3JhcHBlciRtb2R1bGV0ADlMc2NhbGEvY29sbGVjdGlvbi9jb252ZXJ0L1dyYXBwZXJzJE11dGFibGVCdWZmZXJXcmFwcGVyJDtMABhNdXRhYmxlTWFwV3JhcHBlciRtb2R1bGV0ADZMc2NhbGEvY29sbGVjdGlvbi9jb252ZXJ0L1dyYXBwZXJzJE11dGFibGVNYXBXcmFwcGVyJDtMABhNdXRhYmxlU2VxV3JhcHBlciRtb2R1bGV0ADZMc2NhbGEvY29sbGVjdGlvbi9jb252ZXJ0L1dyYXBwZXJzJE11dGFibGVTZXFXcmFwcGVyJDtMABhNdXRhYmxlU2V0V3JhcHBlciRtb2R1bGV0ADZMc2NhbGEvY29sbGVjdGlvbi9jb252ZXJ0L1dyYXBwZXJzJE11dGFibGVTZXRXcmFwcGVyJDtMABFTZXFXcmFwcGVyJG1vZHVsZXQAL0xzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkU2VxV3JhcHBlciQ7eHBwcHBwcHBwcHBwcHBwcHBwcHNyADJzY2FsYS5jb2xsZWN0aW9uLmdlbmVyaWMuRGVmYXVsdFNlcmlhbGl6YXRpb25Qcm94eQAAAAAAAAADAwABTAAHZmFjdG9yeXQAGkxzY2FsYS9jb2xsZWN0aW9uL0ZhY3Rvcnk7eHBzcgAlc2NhbGEuY29sbGVjdGlvbi5NYXBGYWN0b3J5JFRvRmFjdG9yeQAAAAAAAAADAgABTAAHZmFjdG9yeXQAHUxzY2FsYS9jb2xsZWN0aW9uL01hcEZhY3Rvcnk7eHBzcgAhc2NhbGEuY29sbGVjdGlvbi5tdXRhYmxlLkhhc2hNYXAkAAAAAAAAAAMCAAB4cHcE/////3NyAAxzY2FsYS5UdXBsZTIulGZ9W5L59QIAAkwAAl8xdAASTGphdmEvbGFuZy9PYmplY3Q7TAACXzJxAH4AInhwc3IAEWphdmEubGFuZy5JbnRlZ2VyEuKgpPeBhzgCAAFJAAV2YWx1ZXhyABBqYXZhLmxhbmcuTnVtYmVyhqyVHQuU4IsCAAB4cAAAAAJzcQB+ACQAAAADc3EAfgAhc3EAfgAkAAAAAXEAfgAmc3EAfgAhcQB+ACdzcQB+ACQAAAAEc3IAJnNjYWxhLmNvbGxlY3Rpb24uZ2VuZXJpYy5TZXJpYWxpemVFbmQkAAAAAAAAAAMCAAB4cHhxAH4AGw==") + check(g)(new collection.convert.Wrappers.MapWrapper(mutable.Map()))("rO0ABXNyACxzY2FsYS5jb2xsZWN0aW9uLmNvbnZlcnQuV3JhcHBlcnMkTWFwV3JhcHBlcgAAAAAAAAADAgACTAAGJG91dGVydAAjTHNjYWxhL2NvbGxlY3Rpb24vY29udmVydC9XcmFwcGVycztMADhzY2FsYSRjb2xsZWN0aW9uJGNvbnZlcnQkV3JhcHBlcnMkTWFwV3JhcHBlciQkdW5kZXJseWluZ3QAFkxzY2FsYS9jb2xsZWN0aW9uL01hcDt4cHNyACJzY2FsYS5jb2xsZWN0aW9uLmNvbnZlcnQuV3JhcHBlcnMkAAAAAAAAAAMCABFMABhEaWN0aW9uYXJ5V3JhcHBlciRtb2R1bGV0ADZMc2NhbGEvY29sbGVjdGlvbi9jb252ZXJ0L1dyYXBwZXJzJERpY3Rpb25hcnlXcmFwcGVyJDtMABZJdGVyYWJsZVdyYXBwZXIkbW9kdWxldAA0THNjYWxhL2NvbGxlY3Rpb24vY29udmVydC9XcmFwcGVycyRJdGVyYWJsZVdyYXBwZXIkO0wAFkl0ZXJhdG9yV3JhcHBlciRtb2R1bGV0ADRMc2NhbGEvY29sbGVjdGlvbi9jb252ZXJ0L1dyYXBwZXJzJEl0ZXJhdG9yV3JhcHBlciQ7TAAZSkNvbGxlY3Rpb25XcmFwcGVyJG1vZHVsZXQAN0xzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkSkNvbGxlY3Rpb25XcmFwcGVyJDtMABxKQ29uY3VycmVudE1hcFdyYXBwZXIkbW9kdWxldAA6THNjYWxhL2NvbGxlY3Rpb24vY29udmVydC9XcmFwcGVycyRKQ29uY3VycmVudE1hcFdyYXBwZXIkO0wAGUpEaWN0aW9uYXJ5V3JhcHBlciRtb2R1bGV0ADdMc2NhbGEvY29sbGVjdGlvbi9jb252ZXJ0L1dyYXBwZXJzJEpEaWN0aW9uYXJ5V3JhcHBlciQ7TAAaSkVudW1lcmF0aW9uV3JhcHBlciRtb2R1bGV0ADhMc2NhbGEvY29sbGVjdGlvbi9jb252ZXJ0L1dyYXBwZXJzJEpFbnVtZXJhdGlvbldyYXBwZXIkO0wAF0pJdGVyYWJsZVdyYXBwZXIkbW9kdWxldAA1THNjYWxhL2NvbGxlY3Rpb24vY29udmVydC9XcmFwcGVycyRKSXRlcmFibGVXcmFwcGVyJDtMABdKSXRlcmF0b3JXcmFwcGVyJG1vZHVsZXQANUxzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkSkl0ZXJhdG9yV3JhcHBlciQ7TAATSkxpc3RXcmFwcGVyJG1vZHVsZXQAMUxzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkSkxpc3RXcmFwcGVyJDtMABlKUHJvcGVydGllc1dyYXBwZXIkbW9kdWxldAA3THNjYWxhL2NvbGxlY3Rpb24vY29udmVydC9XcmFwcGVycyRKUHJvcGVydGllc1dyYXBwZXIkO0wAEkpTZXRXcmFwcGVyJG1vZHVsZXQAMExzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkSlNldFdyYXBwZXIkO0wAG011dGFibGVCdWZmZXJXcmFwcGVyJG1vZHVsZXQAOUxzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkTXV0YWJsZUJ1ZmZlcldyYXBwZXIkO0wAGE11dGFibGVNYXBXcmFwcGVyJG1vZHVsZXQANkxzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkTXV0YWJsZU1hcFdyYXBwZXIkO0wAGE11dGFibGVTZXFXcmFwcGVyJG1vZHVsZXQANkxzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkTXV0YWJsZVNlcVdyYXBwZXIkO0wAGE11dGFibGVTZXRXcmFwcGVyJG1vZHVsZXQANkxzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkTXV0YWJsZVNldFdyYXBwZXIkO0wAEVNlcVdyYXBwZXIkbW9kdWxldAAvTHNjYWxhL2NvbGxlY3Rpb24vY29udmVydC9XcmFwcGVycyRTZXFXcmFwcGVyJDt4cHBwcHBwcHBwcHBwcHBwcHBwc3IAMnNjYWxhLmNvbGxlY3Rpb24uZ2VuZXJpYy5EZWZhdWx0U2VyaWFsaXphdGlvblByb3h5AAAAAAAAAAMDAAFMAAdmYWN0b3J5dAAaTHNjYWxhL2NvbGxlY3Rpb24vRmFjdG9yeTt4cHNyACVzY2FsYS5jb2xsZWN0aW9uLk1hcEZhY3RvcnkkVG9GYWN0b3J5AAAAAAAAAAMCAAFMAAdmYWN0b3J5dAAdTHNjYWxhL2NvbGxlY3Rpb24vTWFwRmFjdG9yeTt4cHNyACFzY2FsYS5jb2xsZWN0aW9uLm11dGFibGUuSGFzaE1hcCQAAAAAAAAAAwIAAHhwdwQAAAAAeA==") + check(g)(new collection.convert.Wrappers.MapWrapper(mutable.Map[Int, Int](1 -> 2, 2 -> 3, 3 -> 4)))("rO0ABXNyACxzY2FsYS5jb2xsZWN0aW9uLmNvbnZlcnQuV3JhcHBlcnMkTWFwV3JhcHBlcgAAAAAAAAADAgACTAAGJG91dGVydAAjTHNjYWxhL2NvbGxlY3Rpb24vY29udmVydC9XcmFwcGVycztMADhzY2FsYSRjb2xsZWN0aW9uJGNvbnZlcnQkV3JhcHBlcnMkTWFwV3JhcHBlciQkdW5kZXJseWluZ3QAFkxzY2FsYS9jb2xsZWN0aW9uL01hcDt4cHNyACJzY2FsYS5jb2xsZWN0aW9uLmNvbnZlcnQuV3JhcHBlcnMkAAAAAAAAAAMCABFMABhEaWN0aW9uYXJ5V3JhcHBlciRtb2R1bGV0ADZMc2NhbGEvY29sbGVjdGlvbi9jb252ZXJ0L1dyYXBwZXJzJERpY3Rpb25hcnlXcmFwcGVyJDtMABZJdGVyYWJsZVdyYXBwZXIkbW9kdWxldAA0THNjYWxhL2NvbGxlY3Rpb24vY29udmVydC9XcmFwcGVycyRJdGVyYWJsZVdyYXBwZXIkO0wAFkl0ZXJhdG9yV3JhcHBlciRtb2R1bGV0ADRMc2NhbGEvY29sbGVjdGlvbi9jb252ZXJ0L1dyYXBwZXJzJEl0ZXJhdG9yV3JhcHBlciQ7TAAZSkNvbGxlY3Rpb25XcmFwcGVyJG1vZHVsZXQAN0xzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkSkNvbGxlY3Rpb25XcmFwcGVyJDtMABxKQ29uY3VycmVudE1hcFdyYXBwZXIkbW9kdWxldAA6THNjYWxhL2NvbGxlY3Rpb24vY29udmVydC9XcmFwcGVycyRKQ29uY3VycmVudE1hcFdyYXBwZXIkO0wAGUpEaWN0aW9uYXJ5V3JhcHBlciRtb2R1bGV0ADdMc2NhbGEvY29sbGVjdGlvbi9jb252ZXJ0L1dyYXBwZXJzJEpEaWN0aW9uYXJ5V3JhcHBlciQ7TAAaSkVudW1lcmF0aW9uV3JhcHBlciRtb2R1bGV0ADhMc2NhbGEvY29sbGVjdGlvbi9jb252ZXJ0L1dyYXBwZXJzJEpFbnVtZXJhdGlvbldyYXBwZXIkO0wAF0pJdGVyYWJsZVdyYXBwZXIkbW9kdWxldAA1THNjYWxhL2NvbGxlY3Rpb24vY29udmVydC9XcmFwcGVycyRKSXRlcmFibGVXcmFwcGVyJDtMABdKSXRlcmF0b3JXcmFwcGVyJG1vZHVsZXQANUxzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkSkl0ZXJhdG9yV3JhcHBlciQ7TAATSkxpc3RXcmFwcGVyJG1vZHVsZXQAMUxzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkSkxpc3RXcmFwcGVyJDtMABlKUHJvcGVydGllc1dyYXBwZXIkbW9kdWxldAA3THNjYWxhL2NvbGxlY3Rpb24vY29udmVydC9XcmFwcGVycyRKUHJvcGVydGllc1dyYXBwZXIkO0wAEkpTZXRXcmFwcGVyJG1vZHVsZXQAMExzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkSlNldFdyYXBwZXIkO0wAG011dGFibGVCdWZmZXJXcmFwcGVyJG1vZHVsZXQAOUxzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkTXV0YWJsZUJ1ZmZlcldyYXBwZXIkO0wAGE11dGFibGVNYXBXcmFwcGVyJG1vZHVsZXQANkxzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkTXV0YWJsZU1hcFdyYXBwZXIkO0wAGE11dGFibGVTZXFXcmFwcGVyJG1vZHVsZXQANkxzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkTXV0YWJsZVNlcVdyYXBwZXIkO0wAGE11dGFibGVTZXRXcmFwcGVyJG1vZHVsZXQANkxzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkTXV0YWJsZVNldFdyYXBwZXIkO0wAEVNlcVdyYXBwZXIkbW9kdWxldAAvTHNjYWxhL2NvbGxlY3Rpb24vY29udmVydC9XcmFwcGVycyRTZXFXcmFwcGVyJDt4cHBwcHBwcHBwcHBwcHBwcHBwc3IAMnNjYWxhLmNvbGxlY3Rpb24uZ2VuZXJpYy5EZWZhdWx0U2VyaWFsaXphdGlvblByb3h5AAAAAAAAAAMDAAFMAAdmYWN0b3J5dAAaTHNjYWxhL2NvbGxlY3Rpb24vRmFjdG9yeTt4cHNyACVzY2FsYS5jb2xsZWN0aW9uLk1hcEZhY3RvcnkkVG9GYWN0b3J5AAAAAAAAAAMCAAFMAAdmYWN0b3J5dAAdTHNjYWxhL2NvbGxlY3Rpb24vTWFwRmFjdG9yeTt4cHNyACFzY2FsYS5jb2xsZWN0aW9uLm11dGFibGUuSGFzaE1hcCQAAAAAAAAAAwIAAHhwdwQAAAADc3IADHNjYWxhLlR1cGxlMi6UZn1bkvn1AgACTAACXzF0ABJMamF2YS9sYW5nL09iamVjdDtMAAJfMnEAfgAgeHBzcgARamF2YS5sYW5nLkludGVnZXIS4qCk94GHOAIAAUkABXZhbHVleHIAEGphdmEubGFuZy5OdW1iZXKGrJUdC5TgiwIAAHhwAAAAAnNxAH4AIgAAAANzcQB+AB9zcQB+ACIAAAABcQB+ACRzcQB+AB9xAH4AJXNxAH4AIgAAAAR4") + check(g)(new collection.convert.Wrappers.MutableMapWrapper(mutable.Map()))("rO0ABXNyADNzY2FsYS5jb2xsZWN0aW9uLmNvbnZlcnQuV3JhcHBlcnMkTXV0YWJsZU1hcFdyYXBwZXIAAAAAAAAAAwIAAUwACnVuZGVybHlpbmd0AB5Mc2NhbGEvY29sbGVjdGlvbi9tdXRhYmxlL01hcDt4cgAsc2NhbGEuY29sbGVjdGlvbi5jb252ZXJ0LldyYXBwZXJzJE1hcFdyYXBwZXIAAAAAAAAAAwIAAkwABiRvdXRlcnQAI0xzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnM7TAA4c2NhbGEkY29sbGVjdGlvbiRjb252ZXJ0JFdyYXBwZXJzJE1hcFdyYXBwZXIkJHVuZGVybHlpbmd0ABZMc2NhbGEvY29sbGVjdGlvbi9NYXA7eHBzcgAic2NhbGEuY29sbGVjdGlvbi5jb252ZXJ0LldyYXBwZXJzJAAAAAAAAAADAgARTAAYRGljdGlvbmFyeVdyYXBwZXIkbW9kdWxldAA2THNjYWxhL2NvbGxlY3Rpb24vY29udmVydC9XcmFwcGVycyREaWN0aW9uYXJ5V3JhcHBlciQ7TAAWSXRlcmFibGVXcmFwcGVyJG1vZHVsZXQANExzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkSXRlcmFibGVXcmFwcGVyJDtMABZJdGVyYXRvcldyYXBwZXIkbW9kdWxldAA0THNjYWxhL2NvbGxlY3Rpb24vY29udmVydC9XcmFwcGVycyRJdGVyYXRvcldyYXBwZXIkO0wAGUpDb2xsZWN0aW9uV3JhcHBlciRtb2R1bGV0ADdMc2NhbGEvY29sbGVjdGlvbi9jb252ZXJ0L1dyYXBwZXJzJEpDb2xsZWN0aW9uV3JhcHBlciQ7TAAcSkNvbmN1cnJlbnRNYXBXcmFwcGVyJG1vZHVsZXQAOkxzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkSkNvbmN1cnJlbnRNYXBXcmFwcGVyJDtMABlKRGljdGlvbmFyeVdyYXBwZXIkbW9kdWxldAA3THNjYWxhL2NvbGxlY3Rpb24vY29udmVydC9XcmFwcGVycyRKRGljdGlvbmFyeVdyYXBwZXIkO0wAGkpFbnVtZXJhdGlvbldyYXBwZXIkbW9kdWxldAA4THNjYWxhL2NvbGxlY3Rpb24vY29udmVydC9XcmFwcGVycyRKRW51bWVyYXRpb25XcmFwcGVyJDtMABdKSXRlcmFibGVXcmFwcGVyJG1vZHVsZXQANUxzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkSkl0ZXJhYmxlV3JhcHBlciQ7TAAXSkl0ZXJhdG9yV3JhcHBlciRtb2R1bGV0ADVMc2NhbGEvY29sbGVjdGlvbi9jb252ZXJ0L1dyYXBwZXJzJEpJdGVyYXRvcldyYXBwZXIkO0wAE0pMaXN0V3JhcHBlciRtb2R1bGV0ADFMc2NhbGEvY29sbGVjdGlvbi9jb252ZXJ0L1dyYXBwZXJzJEpMaXN0V3JhcHBlciQ7TAAZSlByb3BlcnRpZXNXcmFwcGVyJG1vZHVsZXQAN0xzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkSlByb3BlcnRpZXNXcmFwcGVyJDtMABJKU2V0V3JhcHBlciRtb2R1bGV0ADBMc2NhbGEvY29sbGVjdGlvbi9jb252ZXJ0L1dyYXBwZXJzJEpTZXRXcmFwcGVyJDtMABtNdXRhYmxlQnVmZmVyV3JhcHBlciRtb2R1bGV0ADlMc2NhbGEvY29sbGVjdGlvbi9jb252ZXJ0L1dyYXBwZXJzJE11dGFibGVCdWZmZXJXcmFwcGVyJDtMABhNdXRhYmxlTWFwV3JhcHBlciRtb2R1bGV0ADZMc2NhbGEvY29sbGVjdGlvbi9jb252ZXJ0L1dyYXBwZXJzJE11dGFibGVNYXBXcmFwcGVyJDtMABhNdXRhYmxlU2VxV3JhcHBlciRtb2R1bGV0ADZMc2NhbGEvY29sbGVjdGlvbi9jb252ZXJ0L1dyYXBwZXJzJE11dGFibGVTZXFXcmFwcGVyJDtMABhNdXRhYmxlU2V0V3JhcHBlciRtb2R1bGV0ADZMc2NhbGEvY29sbGVjdGlvbi9jb252ZXJ0L1dyYXBwZXJzJE11dGFibGVTZXRXcmFwcGVyJDtMABFTZXFXcmFwcGVyJG1vZHVsZXQAL0xzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkU2VxV3JhcHBlciQ7eHBwcHBwcHBwcHBwcHBwcHBwcHNyADJzY2FsYS5jb2xsZWN0aW9uLmdlbmVyaWMuRGVmYXVsdFNlcmlhbGl6YXRpb25Qcm94eQAAAAAAAAADAwABTAAHZmFjdG9yeXQAGkxzY2FsYS9jb2xsZWN0aW9uL0ZhY3Rvcnk7eHBzcgAlc2NhbGEuY29sbGVjdGlvbi5NYXBGYWN0b3J5JFRvRmFjdG9yeQAAAAAAAAADAgABTAAHZmFjdG9yeXQAHUxzY2FsYS9jb2xsZWN0aW9uL01hcEZhY3Rvcnk7eHBzcgAhc2NhbGEuY29sbGVjdGlvbi5tdXRhYmxlLkhhc2hNYXAkAAAAAAAAAAMCAAB4cHcEAAAAAHhxAH4AGw==") + check(g)(new collection.convert.Wrappers.MutableMapWrapper(mutable.Map[Int, Int](1 -> 2, 2 -> 3, 3 -> 4)))("rO0ABXNyADNzY2FsYS5jb2xsZWN0aW9uLmNvbnZlcnQuV3JhcHBlcnMkTXV0YWJsZU1hcFdyYXBwZXIAAAAAAAAAAwIAAUwACnVuZGVybHlpbmd0AB5Mc2NhbGEvY29sbGVjdGlvbi9tdXRhYmxlL01hcDt4cgAsc2NhbGEuY29sbGVjdGlvbi5jb252ZXJ0LldyYXBwZXJzJE1hcFdyYXBwZXIAAAAAAAAAAwIAAkwABiRvdXRlcnQAI0xzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnM7TAA4c2NhbGEkY29sbGVjdGlvbiRjb252ZXJ0JFdyYXBwZXJzJE1hcFdyYXBwZXIkJHVuZGVybHlpbmd0ABZMc2NhbGEvY29sbGVjdGlvbi9NYXA7eHBzcgAic2NhbGEuY29sbGVjdGlvbi5jb252ZXJ0LldyYXBwZXJzJAAAAAAAAAADAgARTAAYRGljdGlvbmFyeVdyYXBwZXIkbW9kdWxldAA2THNjYWxhL2NvbGxlY3Rpb24vY29udmVydC9XcmFwcGVycyREaWN0aW9uYXJ5V3JhcHBlciQ7TAAWSXRlcmFibGVXcmFwcGVyJG1vZHVsZXQANExzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkSXRlcmFibGVXcmFwcGVyJDtMABZJdGVyYXRvcldyYXBwZXIkbW9kdWxldAA0THNjYWxhL2NvbGxlY3Rpb24vY29udmVydC9XcmFwcGVycyRJdGVyYXRvcldyYXBwZXIkO0wAGUpDb2xsZWN0aW9uV3JhcHBlciRtb2R1bGV0ADdMc2NhbGEvY29sbGVjdGlvbi9jb252ZXJ0L1dyYXBwZXJzJEpDb2xsZWN0aW9uV3JhcHBlciQ7TAAcSkNvbmN1cnJlbnRNYXBXcmFwcGVyJG1vZHVsZXQAOkxzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkSkNvbmN1cnJlbnRNYXBXcmFwcGVyJDtMABlKRGljdGlvbmFyeVdyYXBwZXIkbW9kdWxldAA3THNjYWxhL2NvbGxlY3Rpb24vY29udmVydC9XcmFwcGVycyRKRGljdGlvbmFyeVdyYXBwZXIkO0wAGkpFbnVtZXJhdGlvbldyYXBwZXIkbW9kdWxldAA4THNjYWxhL2NvbGxlY3Rpb24vY29udmVydC9XcmFwcGVycyRKRW51bWVyYXRpb25XcmFwcGVyJDtMABdKSXRlcmFibGVXcmFwcGVyJG1vZHVsZXQANUxzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkSkl0ZXJhYmxlV3JhcHBlciQ7TAAXSkl0ZXJhdG9yV3JhcHBlciRtb2R1bGV0ADVMc2NhbGEvY29sbGVjdGlvbi9jb252ZXJ0L1dyYXBwZXJzJEpJdGVyYXRvcldyYXBwZXIkO0wAE0pMaXN0V3JhcHBlciRtb2R1bGV0ADFMc2NhbGEvY29sbGVjdGlvbi9jb252ZXJ0L1dyYXBwZXJzJEpMaXN0V3JhcHBlciQ7TAAZSlByb3BlcnRpZXNXcmFwcGVyJG1vZHVsZXQAN0xzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkSlByb3BlcnRpZXNXcmFwcGVyJDtMABJKU2V0V3JhcHBlciRtb2R1bGV0ADBMc2NhbGEvY29sbGVjdGlvbi9jb252ZXJ0L1dyYXBwZXJzJEpTZXRXcmFwcGVyJDtMABtNdXRhYmxlQnVmZmVyV3JhcHBlciRtb2R1bGV0ADlMc2NhbGEvY29sbGVjdGlvbi9jb252ZXJ0L1dyYXBwZXJzJE11dGFibGVCdWZmZXJXcmFwcGVyJDtMABhNdXRhYmxlTWFwV3JhcHBlciRtb2R1bGV0ADZMc2NhbGEvY29sbGVjdGlvbi9jb252ZXJ0L1dyYXBwZXJzJE11dGFibGVNYXBXcmFwcGVyJDtMABhNdXRhYmxlU2VxV3JhcHBlciRtb2R1bGV0ADZMc2NhbGEvY29sbGVjdGlvbi9jb252ZXJ0L1dyYXBwZXJzJE11dGFibGVTZXFXcmFwcGVyJDtMABhNdXRhYmxlU2V0V3JhcHBlciRtb2R1bGV0ADZMc2NhbGEvY29sbGVjdGlvbi9jb252ZXJ0L1dyYXBwZXJzJE11dGFibGVTZXRXcmFwcGVyJDtMABFTZXFXcmFwcGVyJG1vZHVsZXQAL0xzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkU2VxV3JhcHBlciQ7eHBwcHBwcHBwcHBwcHBwcHBwcHNyADJzY2FsYS5jb2xsZWN0aW9uLmdlbmVyaWMuRGVmYXVsdFNlcmlhbGl6YXRpb25Qcm94eQAAAAAAAAADAwABTAAHZmFjdG9yeXQAGkxzY2FsYS9jb2xsZWN0aW9uL0ZhY3Rvcnk7eHBzcgAlc2NhbGEuY29sbGVjdGlvbi5NYXBGYWN0b3J5JFRvRmFjdG9yeQAAAAAAAAADAgABTAAHZmFjdG9yeXQAHUxzY2FsYS9jb2xsZWN0aW9uL01hcEZhY3Rvcnk7eHBzcgAhc2NhbGEuY29sbGVjdGlvbi5tdXRhYmxlLkhhc2hNYXAkAAAAAAAAAAMCAAB4cHcEAAAAA3NyAAxzY2FsYS5UdXBsZTIulGZ9W5L59QIAAkwAAl8xdAASTGphdmEvbGFuZy9PYmplY3Q7TAACXzJxAH4AInhwc3IAEWphdmEubGFuZy5JbnRlZ2VyEuKgpPeBhzgCAAFJAAV2YWx1ZXhyABBqYXZhLmxhbmcuTnVtYmVyhqyVHQuU4IsCAAB4cAAAAAJzcQB+ACQAAAADc3EAfgAhc3EAfgAkAAAAAXEAfgAmc3EAfgAhcQB+ACdzcQB+ACQAAAAEeHEAfgAb") check(g)(immutable.BitSet(1, 2, 3))( "rO0ABXNyADRzY2FsYS5jb2xsZWN0aW9uLmltbXV0YWJsZS5CaXRTZXQkU2VyaWFsaXphdGlvblByb3h5AAAAAAAAAAMCAAB4cgAqc2NhbGEuY29sbGVjdGlvbi5CaXRTZXQkU2VyaWFsaXphdGlvblByb3h5AAAAAAAAAAMDAAB4cHcMAAAAAQAAAAAAAAAOeA==") check(g)(immutable.HashMap())( "rO0ABXNyADJzY2FsYS5jb2xsZWN0aW9uLmdlbmVyaWMuRGVmYXVsdFNlcmlhbGl6YXRpb25Qcm94eQAAAAAAAAADAwABTAAHZmFjdG9yeXQAGkxzY2FsYS9jb2xsZWN0aW9uL0ZhY3Rvcnk7eHBzcgAlc2NhbGEuY29sbGVjdGlvbi5NYXBGYWN0b3J5JFRvRmFjdG9yeQAAAAAAAAADAgABTAAHZmFjdG9yeXQAHUxzY2FsYS9jb2xsZWN0aW9uL01hcEZhY3Rvcnk7eHBzcgAjc2NhbGEuY29sbGVjdGlvbi5pbW11dGFibGUuSGFzaE1hcCQAAAAAAAAAAwMAAUwADWRlZmF1bHRNZXJnZXJ0ACtMc2NhbGEvY29sbGVjdGlvbi9pbW11dGFibGUvSGFzaE1hcCRNZXJnZXI7eHB4dwT/////c3IAJnNjYWxhLmNvbGxlY3Rpb24uZ2VuZXJpYy5TZXJpYWxpemVFbmQkAAAAAAAAAAMCAAB4cHg=") @@ -191,8 +191,8 @@ object SerializationStability { //check(g)(mutable.ArrayStack(1, 2, 3))( "rO0ABXNyACNzY2FsYS5jb2xsZWN0aW9uLm11dGFibGUuQXJyYXlTdGFja3bdxXbcnLBeAgACSQAqc2NhbGEkY29sbGVjdGlvbiRtdXRhYmxlJEFycmF5U3RhY2skJGluZGV4WwAqc2NhbGEkY29sbGVjdGlvbiRtdXRhYmxlJEFycmF5U3RhY2skJHRhYmxldAATW0xqYXZhL2xhbmcvT2JqZWN0O3hwAAAAA3VyABNbTGphdmEubGFuZy5PYmplY3Q7kM5YnxBzKWwCAAB4cAAAAANzcgARamF2YS5sYW5nLkludGVnZXIS4qCk94GHOAIAAUkABXZhbHVleHIAEGphdmEubGFuZy5OdW1iZXKGrJUdC5TgiwIAAHhwAAAAA3NxAH4ABQAAAAJzcQB+AAUAAAAB") //check(g)(mutable.DoubleLinkedList(1, 2, 3))( "rO0ABXNyAClzY2FsYS5jb2xsZWN0aW9uLm11dGFibGUuRG91YmxlTGlua2VkTGlzdI73LKsKRr1RAgADTAAEZWxlbXQAEkxqYXZhL2xhbmcvT2JqZWN0O0wABG5leHR0ACtMc2NhbGEvY29sbGVjdGlvbi9tdXRhYmxlL0RvdWJsZUxpbmtlZExpc3Q7TAAEcHJldnEAfgACeHBzcgARamF2YS5sYW5nLkludGVnZXIS4qCk94GHOAIAAUkABXZhbHVleHIAEGphdmEubGFuZy5OdW1iZXKGrJUdC5TgiwIAAHhwAAAAAXNxAH4AAHNxAH4ABAAAAAJzcQB+AABzcQB+AAQAAAADc3EAfgAAcHEAfgALcQB+AAlxAH4AB3EAfgADcA==") - check(g)(mutable.HashMap())( "rO0ABXNyADJzY2FsYS5jb2xsZWN0aW9uLmdlbmVyaWMuRGVmYXVsdFNlcmlhbGl6YXRpb25Qcm94eQAAAAAAAAADAwABTAAHZmFjdG9yeXQAGkxzY2FsYS9jb2xsZWN0aW9uL0ZhY3Rvcnk7eHBzcgAlc2NhbGEuY29sbGVjdGlvbi5NYXBGYWN0b3J5JFRvRmFjdG9yeQAAAAAAAAADAgABTAAHZmFjdG9yeXQAHUxzY2FsYS9jb2xsZWN0aW9uL01hcEZhY3Rvcnk7eHBzcgAhc2NhbGEuY29sbGVjdGlvbi5tdXRhYmxlLkhhc2hNYXAkAAAAAAAAAAMCAAB4cHcE/////3NyACZzY2FsYS5jb2xsZWN0aW9uLmdlbmVyaWMuU2VyaWFsaXplRW5kJAAAAAAAAAADAgAAeHB4") - check(g)(mutable.HashMap(1 -> 1))( "rO0ABXNyADJzY2FsYS5jb2xsZWN0aW9uLmdlbmVyaWMuRGVmYXVsdFNlcmlhbGl6YXRpb25Qcm94eQAAAAAAAAADAwABTAAHZmFjdG9yeXQAGkxzY2FsYS9jb2xsZWN0aW9uL0ZhY3Rvcnk7eHBzcgAlc2NhbGEuY29sbGVjdGlvbi5NYXBGYWN0b3J5JFRvRmFjdG9yeQAAAAAAAAADAgABTAAHZmFjdG9yeXQAHUxzY2FsYS9jb2xsZWN0aW9uL01hcEZhY3Rvcnk7eHBzcgAhc2NhbGEuY29sbGVjdGlvbi5tdXRhYmxlLkhhc2hNYXAkAAAAAAAAAAMCAAB4cHcE/////3NyAAxzY2FsYS5UdXBsZTIulGZ9W5L59QIAAkwAAl8xdAASTGphdmEvbGFuZy9PYmplY3Q7TAACXzJxAH4ACXhwc3IAEWphdmEubGFuZy5JbnRlZ2VyEuKgpPeBhzgCAAFJAAV2YWx1ZXhyABBqYXZhLmxhbmcuTnVtYmVyhqyVHQuU4IsCAAB4cAAAAAFxAH4ADXNyACZzY2FsYS5jb2xsZWN0aW9uLmdlbmVyaWMuU2VyaWFsaXplRW5kJAAAAAAAAAADAgAAeHB4") + check(g)(mutable.HashMap())( "rO0ABXNyADJzY2FsYS5jb2xsZWN0aW9uLmdlbmVyaWMuRGVmYXVsdFNlcmlhbGl6YXRpb25Qcm94eQAAAAAAAAADAwABTAAHZmFjdG9yeXQAGkxzY2FsYS9jb2xsZWN0aW9uL0ZhY3Rvcnk7eHBzcgAlc2NhbGEuY29sbGVjdGlvbi5NYXBGYWN0b3J5JFRvRmFjdG9yeQAAAAAAAAADAgABTAAHZmFjdG9yeXQAHUxzY2FsYS9jb2xsZWN0aW9uL01hcEZhY3Rvcnk7eHBzcgAhc2NhbGEuY29sbGVjdGlvbi5tdXRhYmxlLkhhc2hNYXAkAAAAAAAAAAMCAAB4cHcEAAAAAHg=") + check(g)(mutable.HashMap(1 -> 1))( "rO0ABXNyADJzY2FsYS5jb2xsZWN0aW9uLmdlbmVyaWMuRGVmYXVsdFNlcmlhbGl6YXRpb25Qcm94eQAAAAAAAAADAwABTAAHZmFjdG9yeXQAGkxzY2FsYS9jb2xsZWN0aW9uL0ZhY3Rvcnk7eHBzcgAlc2NhbGEuY29sbGVjdGlvbi5NYXBGYWN0b3J5JFRvRmFjdG9yeQAAAAAAAAADAgABTAAHZmFjdG9yeXQAHUxzY2FsYS9jb2xsZWN0aW9uL01hcEZhY3Rvcnk7eHBzcgAhc2NhbGEuY29sbGVjdGlvbi5tdXRhYmxlLkhhc2hNYXAkAAAAAAAAAAMCAAB4cHcEAAAAAXNyAAxzY2FsYS5UdXBsZTIulGZ9W5L59QIAAkwAAl8xdAASTGphdmEvbGFuZy9PYmplY3Q7TAACXzJxAH4ACXhwc3IAEWphdmEubGFuZy5JbnRlZ2VyEuKgpPeBhzgCAAFJAAV2YWx1ZXhyABBqYXZhLmxhbmcuTnVtYmVyhqyVHQuU4IsCAAB4cAAAAAFxAH4ADXg=") check(g)(mutable.HashSet(1, 2, 3))( "rO0ABXNyADJzY2FsYS5jb2xsZWN0aW9uLmdlbmVyaWMuRGVmYXVsdFNlcmlhbGl6YXRpb25Qcm94eQAAAAAAAAADAwABTAAHZmFjdG9yeXQAGkxzY2FsYS9jb2xsZWN0aW9uL0ZhY3Rvcnk7eHBzcgAqc2NhbGEuY29sbGVjdGlvbi5JdGVyYWJsZUZhY3RvcnkkVG9GYWN0b3J5AAAAAAAAAAMCAAFMAAdmYWN0b3J5dAAiTHNjYWxhL2NvbGxlY3Rpb24vSXRlcmFibGVGYWN0b3J5O3hwc3IAIXNjYWxhLmNvbGxlY3Rpb24ubXV0YWJsZS5IYXNoU2V0JAAAAAAAAAADAgAAeHB3BAAAAANzcgARamF2YS5sYW5nLkludGVnZXIS4qCk94GHOAIAAUkABXZhbHVleHIAEGphdmEubGFuZy5OdW1iZXKGrJUdC5TgiwIAAHhwAAAAAXNxAH4ACAAAAAJzcQB+AAgAAAADeA==") check(g)(mutable.TreeMap[Int, Int]())( "rO0ABXNyADJzY2FsYS5jb2xsZWN0aW9uLmdlbmVyaWMuRGVmYXVsdFNlcmlhbGl6YXRpb25Qcm94eQAAAAAAAAADAwABTAAHZmFjdG9yeXQAGkxzY2FsYS9jb2xsZWN0aW9uL0ZhY3Rvcnk7eHBzcgArc2NhbGEuY29sbGVjdGlvbi5Tb3J0ZWRNYXBGYWN0b3J5JFRvRmFjdG9yeQAAAAAAAAADAgACTAALZXZpZGVuY2UkNDB0ABVMc2NhbGEvbWF0aC9PcmRlcmluZztMAAdmYWN0b3J5dAAjTHNjYWxhL2NvbGxlY3Rpb24vU29ydGVkTWFwRmFjdG9yeTt4cHNyABhzY2FsYS5tYXRoLk9yZGVyaW5nJEludCSzOU33V6xBtgIAAHhwc3IAIXNjYWxhLmNvbGxlY3Rpb24ubXV0YWJsZS5UcmVlTWFwJAAAAAAAAAADAgAAeHB3BP////9zcgAmc2NhbGEuY29sbGVjdGlvbi5nZW5lcmljLlNlcmlhbGl6ZUVuZCQAAAAAAAAAAwIAAHhweA==") check(g)(mutable.TreeMap(1 -> 1, 3 -> 6))( "rO0ABXNyADJzY2FsYS5jb2xsZWN0aW9uLmdlbmVyaWMuRGVmYXVsdFNlcmlhbGl6YXRpb25Qcm94eQAAAAAAAAADAwABTAAHZmFjdG9yeXQAGkxzY2FsYS9jb2xsZWN0aW9uL0ZhY3Rvcnk7eHBzcgArc2NhbGEuY29sbGVjdGlvbi5Tb3J0ZWRNYXBGYWN0b3J5JFRvRmFjdG9yeQAAAAAAAAADAgACTAALZXZpZGVuY2UkNDB0ABVMc2NhbGEvbWF0aC9PcmRlcmluZztMAAdmYWN0b3J5dAAjTHNjYWxhL2NvbGxlY3Rpb24vU29ydGVkTWFwRmFjdG9yeTt4cHNyABhzY2FsYS5tYXRoLk9yZGVyaW5nJEludCSzOU33V6xBtgIAAHhwc3IAIXNjYWxhLmNvbGxlY3Rpb24ubXV0YWJsZS5UcmVlTWFwJAAAAAAAAAADAgAAeHB3BP////9zcgAMc2NhbGEuVHVwbGUyLpRmfVuS+fUCAAJMAAJfMXQAEkxqYXZhL2xhbmcvT2JqZWN0O0wAAl8ycQB+AAx4cHNyABFqYXZhLmxhbmcuSW50ZWdlchLioKT3gYc4AgABSQAFdmFsdWV4cgAQamF2YS5sYW5nLk51bWJlcoaslR0LlOCLAgAAeHAAAAABcQB+ABBzcQB+AAtzcQB+AA4AAAADc3EAfgAOAAAABnNyACZzY2FsYS5jb2xsZWN0aW9uLmdlbmVyaWMuU2VyaWFsaXplRW5kJAAAAAAAAAADAgAAeHB4") From 874092e72fbb2a9410325f15e49a53f1f610ea2c Mon Sep 17 00:00:00 2001 From: Jason Zaugg Date: Fri, 15 Jun 2018 14:03:03 +1000 Subject: [PATCH 028/143] Override and use isEmpty / knownSize more widely Adds fast path for known-empty source collections in immutable.*Factory.from Implements knownSize partially for some lazy collections where the underlying collection is empty. --- src/compiler/scala/tools/nsc/io/Jar.scala | 1 + src/library/scala/Enumeration.scala | 2 + src/library/scala/collection/Iterator.scala | 1 + src/library/scala/collection/LazyZipOps.scala | 18 +++++++ src/library/scala/collection/Map.scala | 2 + src/library/scala/collection/MapView.scala | 4 ++ src/library/scala/collection/View.scala | 34 +++++++++++++ .../scala/collection/concurrent/TrieMap.scala | 2 +- .../scala/collection/convert/Wrappers.scala | 16 +++++-- .../collection/generic/IsIterableLike.scala | 6 +++ .../collection/immutable/ChampHashSet.scala | 1 + .../scala/collection/immutable/HashMap.scala | 11 +++-- .../scala/collection/immutable/HashSet.scala | 12 +++-- .../scala/collection/immutable/IntMap.scala | 2 +- .../scala/collection/immutable/LazyList.scala | 1 + .../scala/collection/immutable/List.scala | 1 + .../scala/collection/immutable/ListMap.scala | 3 +- .../scala/collection/immutable/ListSet.scala | 9 +++- .../scala/collection/immutable/LongMap.scala | 2 +- .../scala/collection/immutable/Map.scala | 8 ++++ .../scala/collection/immutable/Queue.scala | 7 ++- .../scala/collection/immutable/Set.scala | 7 +++ .../scala/collection/immutable/TreeMap.scala | 1 + .../scala/collection/immutable/Vector.scala | 3 ++ .../scala/collection/mutable/AnyRefMap.scala | 2 + .../collection/mutable/LinkedHashMap.scala | 3 +- .../collection/mutable/LinkedHashSet.scala | 3 +- .../scala/collection/mutable/ListMap.scala | 3 +- .../scala/collection/mutable/LongMap.scala | 2 + .../scala/collection/mutable/Map.scala | 3 +- .../collection/mutable/OpenHashMap.scala | 3 +- .../collection/mutable/PriorityQueue.scala | 1 + .../scala/collection/mutable/TreeMap.scala | 5 +- .../scala/collection/mutable/TreeSet.scala | 7 +-- src/library/scala/runtime/Tuple2Zipped.scala | 4 +- src/library/scala/runtime/Tuple3Zipped.scala | 4 +- src/library/scala/sys/SystemProperties.scala | 1 + .../reflect/internal/util/WeakHashSet.scala | 1 + .../scala/reflect/io/AbstractFile.scala | 2 +- .../scala/SerializationStabilityTest.scala | 48 +++++++++---------- 40 files changed, 190 insertions(+), 56 deletions(-) diff --git a/src/compiler/scala/tools/nsc/io/Jar.scala b/src/compiler/scala/tools/nsc/io/Jar.scala index cc8917a44c13..5cd68b99218b 100644 --- a/src/compiler/scala/tools/nsc/io/Jar.scala +++ b/src/compiler/scala/tools/nsc/io/Jar.scala @@ -77,6 +77,7 @@ class Jar(file: File) extends AbstractIterable[JarEntry] { Iterator continually in.getNextJarEntry() takeWhile (_ != null) foreach f } override def iterator: Iterator[JarEntry] = this.toList.iterator + override def isEmpty: Boolean = iterator.isEmpty override def toString = "" + file } diff --git a/src/library/scala/Enumeration.scala b/src/library/scala/Enumeration.scala index 26e3fa6c066a..7f7139e47c09 100644 --- a/src/library/scala/Enumeration.scala +++ b/src/library/scala/Enumeration.scala @@ -279,6 +279,8 @@ abstract class Enumeration (initial: Int) extends Serializable { new ValueSet(nnIds.rangeImpl(from.map(_.id - bottomId), until.map(_.id - bottomId))) override def empty = ValueSet.empty + override def knownSize: Int = nnIds.size + override def isEmpty: Boolean = nnIds.isEmpty def contains(v: Value) = nnIds contains (v.id - bottomId) def incl (value: Value) = new ValueSet(nnIds + (value.id - bottomId)) def excl (value: Value) = new ValueSet(nnIds - (value.id - bottomId)) diff --git a/src/library/scala/collection/Iterator.scala b/src/library/scala/collection/Iterator.scala index 05e2655ac182..79fa4682ac6d 100644 --- a/src/library/scala/collection/Iterator.scala +++ b/src/library/scala/collection/Iterator.scala @@ -92,6 +92,7 @@ trait Iterator[+A] extends IterableOnce[A] with IterableOnceOps[A, Iterator, Ite @throws[NoSuchElementException] def next(): A def iterator = this + override def isEmpty: Boolean = !hasNext /** Wraps the value of `next()` in an option. * diff --git a/src/library/scala/collection/LazyZipOps.scala b/src/library/scala/collection/LazyZipOps.scala index 86c74e14b244..d1e60b3d0a14 100644 --- a/src/library/scala/collection/LazyZipOps.scala +++ b/src/library/scala/collection/LazyZipOps.scala @@ -46,6 +46,7 @@ final class LazyZip2[El1, El2, C1 <: Iterable[El1]] private[collection](coll1: C def next() = f(elems1.next(), elems2.next()) } override def knownSize: Int = coll1.knownSize min coll2.knownSize + override def isEmpty: Boolean = coll1.isEmpty || coll2.isEmpty }) } @@ -63,6 +64,8 @@ final class LazyZip2[El1, El2, C1 <: Iterable[El1]] private[collection](coll1: C def hasNext = current.hasNext def next() = current.next() } + override def knownSize: Int = if (coll1.knownSize == 0 || coll2.knownSize == 0) 0 else super.knownSize + override def isEmpty: Boolean = coll1.isEmpty || coll2.isEmpty }) } @@ -89,6 +92,8 @@ final class LazyZip2[El1, El2, C1 <: Iterable[El1]] private[collection](coll1: C } else Iterator.empty.next() } } + override def knownSize: Int = if (coll1.knownSize == 0 || coll2.knownSize == 0) 0 else super.knownSize + override def isEmpty: Boolean = iterator.hasNext }) } @@ -119,6 +124,7 @@ final class LazyZip2[El1, El2, C1 <: Iterable[El1]] private[collection](coll1: C def next() = (elems1.next(), elems2.next()) } override def knownSize: Int = coll1.knownSize min coll2.knownSize + override def isEmpty: Boolean = coll1.isEmpty || coll2.isEmpty } override def toString = s"$coll1.lazyZip($coll2)" @@ -154,6 +160,7 @@ final class LazyZip3[El1, El2, El3, C1 <: Iterable[El1]] private[collection](col def next() = f(elems1.next(), elems2.next(), elems3.next()) } override def knownSize: Int = coll1.knownSize min coll2.knownSize min coll3.knownSize + override def isEmpty: Boolean = coll1.isEmpty || coll2.isEmpty || coll3.isEmpty }) } @@ -172,6 +179,8 @@ final class LazyZip3[El1, El2, El3, C1 <: Iterable[El1]] private[collection](col def hasNext = current.hasNext def next() = current.next() } + override def knownSize: Int = if (coll1.knownSize == 0 || coll2.knownSize == 0 || coll3.knownSize == 0) 0 else super.knownSize + override def isEmpty: Boolean = iterator.isEmpty }) } @@ -200,6 +209,8 @@ final class LazyZip3[El1, El2, El3, C1 <: Iterable[El1]] private[collection](col } else Iterator.empty.next() } } + override def knownSize: Int = if (coll1.knownSize == 0 || coll2.knownSize == 0 || coll3.knownSize == 0) 0 else super.knownSize + override def isEmpty: Boolean = iterator.isEmpty }) } @@ -235,6 +246,7 @@ final class LazyZip3[El1, El2, El3, C1 <: Iterable[El1]] private[collection](col def next() = (elems1.next(), elems2.next(), elems3.next()) } override def knownSize: Int = coll1.knownSize min coll2.knownSize min coll3.knownSize + override def isEmpty: Boolean = coll1.isEmpty || coll2.isEmpty || coll3.isEmpty } override def toString = s"$coll1.lazyZip($coll2).lazyZip($coll3)" @@ -263,6 +275,7 @@ final class LazyZip4[El1, El2, El3, El4, C1 <: Iterable[El1]] private[collection def next() = f(elems1.next(), elems2.next(), elems3.next(), elems4.next()) } override def knownSize: Int = coll1.knownSize min coll2.knownSize min coll3.knownSize min coll4.knownSize + override def isEmpty: Boolean = coll1.isEmpty || coll2.isEmpty || coll3.isEmpty || coll4.isEmpty }) } @@ -282,6 +295,8 @@ final class LazyZip4[El1, El2, El3, El4, C1 <: Iterable[El1]] private[collection def hasNext = current.hasNext def next() = current.next() } + override def knownSize: Int = if (coll1.knownSize == 0 || coll2.knownSize == 0 || coll3.knownSize == 0 || coll4.knownSize == 0) 0 else super.knownSize + override def isEmpty: Boolean = iterator.isEmpty }) } @@ -312,6 +327,8 @@ final class LazyZip4[El1, El2, El3, El4, C1 <: Iterable[El1]] private[collection } else Iterator.empty.next() } } + override def knownSize: Int = if (coll1.knownSize == 0 || coll2.knownSize == 0 || coll3.knownSize == 0 || coll4.knownSize == 0) 0 else super.knownSize + override def isEmpty: Boolean = iterator.isEmpty }) } @@ -350,6 +367,7 @@ final class LazyZip4[El1, El2, El3, El4, C1 <: Iterable[El1]] private[collection def next() = (elems1.next(), elems2.next(), elems3.next(), elems4.next()) } override def knownSize: Int = coll1.knownSize min coll2.knownSize min coll3.knownSize min coll4.knownSize + override def isEmpty: Boolean = coll1.isEmpty || coll2.isEmpty || coll3.isEmpty || coll4.isEmpty } override def toString = s"$coll1.lazyZip($coll2).lazyZip($coll3).lazyZip($coll4)" diff --git a/src/library/scala/collection/Map.scala b/src/library/scala/collection/Map.scala index 6c44389e4cf9..9179eed6bcce 100644 --- a/src/library/scala/collection/Map.scala +++ b/src/library/scala/collection/Map.scala @@ -151,6 +151,8 @@ trait MapOps[K, +V, +CC[_, _] <: IterableOps[_, AnyConstr, _], +C] def iterator: Iterator[K] = MapOps.this.keysIterator def contains(key: K): Boolean = MapOps.this.contains(key) override def size: Int = MapOps.this.size + override def knownSize: Int = MapOps.this.knownSize + override def isEmpty: Boolean = MapOps.this.isEmpty } /** Collects all keys of this map in an iterable collection. diff --git a/src/library/scala/collection/MapView.scala b/src/library/scala/collection/MapView.scala index 42f1243c5a92..648f0e8c3f4a 100644 --- a/src/library/scala/collection/MapView.scala +++ b/src/library/scala/collection/MapView.scala @@ -27,6 +27,7 @@ object MapView { def get(key: K): Option[V] = underlying.get(key) def iterator: Iterator[(K, V)] = underlying.iterator override def knownSize: Int = underlying.knownSize + override def isEmpty: Boolean = underlying.isEmpty } @SerialVersionUID(3L) @@ -34,12 +35,15 @@ object MapView { def iterator: Iterator[(K, W)] = underlying.iterator.map(kv => (kv._1, f(kv._2))) def get(key: K): Option[W] = underlying.get(key).map(f) override def knownSize: Int = underlying.knownSize + override def isEmpty: Boolean = underlying.isEmpty } @SerialVersionUID(3L) class FilterKeys[K, +V](underlying: SomeMapOps[K, V], p: K => Boolean) extends AbstractMapView[K, V] { def iterator: Iterator[(K, V)] = underlying.iterator.filter { case (k, _) => p(k) } def get(key: K): Option[V] = if (p(key)) underlying.get(key) else None + override def knownSize: Int = if (underlying.knownSize == 0) 0 else super.knownSize + override def isEmpty: Boolean = iterator.isEmpty } @SerialVersionUID(3L) diff --git a/src/library/scala/collection/View.scala b/src/library/scala/collection/View.scala index 65753d679e56..5f15b15948e7 100644 --- a/src/library/scala/collection/View.scala +++ b/src/library/scala/collection/View.scala @@ -46,6 +46,8 @@ object View extends IterableFactory[View] { */ def fromIteratorProvider[A](it: () => Iterator[A]): View[A] = new AbstractView[A] { def iterator = it() + override def knownSize: Int = iterator.knownSize + override def isEmpty: Boolean = iterator.isEmpty } /** @@ -73,6 +75,7 @@ object View extends IterableFactory[View] { case object Empty extends AbstractView[Nothing] { def iterator = Iterator.empty override def knownSize = 0 + override def isEmpty: Boolean = true } /** A view with exactly one element */ @@ -89,6 +92,7 @@ object View extends IterableFactory[View] { def hasNext: Boolean = notConsumed } override def knownSize: Int = 1 + override def isEmpty: Boolean = false } /** A view with given elements */ @@ -96,6 +100,7 @@ object View extends IterableFactory[View] { class Elems[A](xs: A*) extends AbstractView[A] { def iterator = xs.iterator override def knownSize = xs.knownSize + override def isEmpty: Boolean = xs.isEmpty } /** A view containing the results of some element computation a number of times. */ @@ -103,6 +108,7 @@ object View extends IterableFactory[View] { class Fill[A](n: Int)(elem: => A) extends AbstractView[A] { def iterator = Iterator.fill(n)(elem) override def knownSize: Int = 0 max n + override def isEmpty: Boolean = n <= 0 } /** A view containing values of a given function over a range of integer values starting from 0. */ @@ -110,6 +116,7 @@ object View extends IterableFactory[View] { class Tabulate[A](n: Int)(f: Int => A) extends AbstractView[A] { def iterator: Iterator[A] = Iterator.tabulate(n)(f) override def knownSize: Int = 0 max n + override def isEmpty: Boolean = n <= 0 } /** A view containing repeated applications of a function to a start value */ @@ -117,6 +124,7 @@ object View extends IterableFactory[View] { class Iterate[A](start: A, len: Int)(f: A => A) extends AbstractView[A] { def iterator: Iterator[A] = Iterator.iterate(start)(f).take(len) override def knownSize: Int = 0 max len + override def isEmpty: Boolean = len <= 0 } /** An `IterableOps` whose collection type and collection type constructor are unknown */ @@ -126,6 +134,8 @@ object View extends IterableFactory[View] { @SerialVersionUID(3L) class Filter[A](val underlying: SomeIterableOps[A], val p: A => Boolean, val isFlipped: Boolean) extends AbstractView[A] { def iterator = underlying.iterator.filterImpl(p, isFlipped) + override def knownSize: Int = if (underlying.knownSize == 0) 0 else super.knownSize + override def isEmpty: Boolean = iterator.isEmpty } object Filter { @@ -140,6 +150,8 @@ object View extends IterableFactory[View] { @SerialVersionUID(3L) class DistinctBy[A, B](underlying: SomeIterableOps[A], f: A => B) extends AbstractView[A] { def iterator: Iterator[A] = underlying.iterator.distinctBy(f) + override def knownSize: Int = if (underlying.knownSize == 0) 0 else super.knownSize + override def isEmpty: Boolean = underlying.isEmpty } /** A view that partitions an underlying collection into two views */ @@ -161,6 +173,8 @@ object View extends IterableFactory[View] { @SerialVersionUID(3L) class Partitioned[A](partition: Partition[A], cond: Boolean) extends AbstractView[A] { def iterator = partition.underlying.iterator.filter(x => partition.p(x) == cond) + override def knownSize: Int = if (partition.underlying.knownSize == 0) 0 else super.knownSize + override def isEmpty: Boolean = iterator.isEmpty } /** A view that drops leading elements of the underlying collection. */ @@ -170,11 +184,14 @@ object View extends IterableFactory[View] { protected val normN = n max 0 override def knownSize = if (underlying.knownSize >= 0) (underlying.knownSize - normN) max 0 else -1 + override def isEmpty: Boolean = iterator.isEmpty } @SerialVersionUID(3L) class DropWhile[A](underlying: SomeIterableOps[A], p: A => Boolean) extends AbstractView[A] { def iterator = underlying.iterator.dropWhile(p) + override def knownSize: Int = if (underlying.knownSize == 0) 0 else super.knownSize + override def isEmpty: Boolean = iterator.isEmpty } /** A view that takes leading elements of the underlying collection. */ @@ -184,11 +201,14 @@ object View extends IterableFactory[View] { protected val normN = n max 0 override def knownSize = if (underlying.knownSize >= 0) underlying.knownSize min normN else -1 + override def isEmpty: Boolean = iterator.isEmpty } @SerialVersionUID(3L) class TakeWhile[A](underlying: SomeIterableOps[A], p: A => Boolean) extends AbstractView[A] { def iterator: Iterator[A] = underlying.iterator.takeWhile(p) + override def knownSize: Int = if (underlying.knownSize == 0) 0 else super.knownSize + override def isEmpty: Boolean = iterator.isEmpty } @SerialVersionUID(3L) @@ -196,6 +216,7 @@ object View extends IterableFactory[View] { def iterator: Iterator[B] = underlying.iterator.scanLeft(z)(op) override def knownSize: Int = if (underlying.knownSize >= 0) underlying.knownSize + 1 else -1 + override def isEmpty: Boolean = iterator.isEmpty } /** A view that maps elements of the underlying collection. */ @@ -203,12 +224,15 @@ object View extends IterableFactory[View] { class Map[+A, +B](underlying: SomeIterableOps[A], f: A => B) extends AbstractView[B] { def iterator = underlying.iterator.map(f) override def knownSize = underlying.knownSize + override def isEmpty: Boolean = underlying.isEmpty } /** A view that flatmaps elements of the underlying collection. */ @SerialVersionUID(3L) class FlatMap[A, B](underlying: SomeIterableOps[A], f: A => IterableOnce[B]) extends AbstractView[B] { def iterator = underlying.iterator.flatMap(f) + override def knownSize: Int = if (underlying.knownSize == 0) 0 else super.knownSize + override def isEmpty: Boolean = iterator.isEmpty } /** A view that concatenates elements of the prefix collection or iterator with the elements @@ -220,6 +244,7 @@ object View extends IterableFactory[View] { override def knownSize = if (prefix.knownSize >= 0 && suffix.knownSize >= 0) prefix.knownSize + suffix.knownSize else -1 + override def isEmpty: Boolean = prefix.isEmpty && suffix.isEmpty } /** A view that zips elements of the underlying collection with the elements @@ -229,6 +254,7 @@ object View extends IterableFactory[View] { class Zip[A, B](underlying: SomeIterableOps[A], other: Iterable[B]) extends AbstractView[(A, B)] { def iterator = underlying.iterator.zip(other) override def knownSize = underlying.knownSize min other.knownSize + override def isEmpty: Boolean = underlying.isEmpty || other.isEmpty } /** A view that zips elements of the underlying collection with the elements @@ -245,6 +271,7 @@ object View extends IterableFactory[View] { if(s2 == -1) -1 else s1 max s2 } } + override def isEmpty: Boolean = underlying.isEmpty && other.isEmpty } /** A view that appends an element to its elements */ @@ -252,6 +279,7 @@ object View extends IterableFactory[View] { class Appended[A](underlying: SomeIterableOps[A], elem: A) extends AbstractView[A] { def iterator: Iterator[A] = new Concat(underlying, new View.Single(elem)).iterator override def knownSize: Int = if (underlying.knownSize >= 0) underlying.knownSize + 1 else -1 + override def isEmpty: Boolean = false } /** A view that prepends an element to its elements */ @@ -259,6 +287,7 @@ object View extends IterableFactory[View] { class Prepended[+A](elem: A, underlying: SomeIterableOps[A]) extends AbstractView[A] { def iterator: Iterator[A] = new Concat(new View.Single(elem), underlying).iterator override def knownSize: Int = if (underlying.knownSize >= 0) underlying.knownSize + 1 else -1 + override def isEmpty: Boolean = false } @SerialVersionUID(3L) @@ -274,17 +303,21 @@ object View extends IterableFactory[View] { def hasNext: Boolean = it.hasNext } override def knownSize: Int = underlying.knownSize + override def isEmpty: Boolean = iterator.isEmpty } @SerialVersionUID(3L) private[collection] class Patched[A](underlying: SomeIterableOps[A], from: Int, other: IterableOnce[A], replaced: Int) extends AbstractView[A] { def iterator: Iterator[A] = underlying.iterator.patch(from, other.iterator, replaced) + override def knownSize: Int = if (underlying.knownSize == 0) 0 else super.knownSize + override def isEmpty: Boolean = iterator.isEmpty } @SerialVersionUID(3L) class ZipWithIndex[A](underlying: SomeIterableOps[A]) extends AbstractView[(A, Int)] { def iterator: Iterator[(A, Int)] = underlying.iterator.zipWithIndex override def knownSize: Int = underlying.knownSize + override def isEmpty: Boolean = underlying.isEmpty } @SerialVersionUID(3L) @@ -316,6 +349,7 @@ object View extends IterableFactory[View] { def hasNext: Boolean = it.hasNext || i < len } override def knownSize: Int = if (underlying.knownSize >= 0) underlying.knownSize max len else -1 + override def isEmpty: Boolean = underlying.isEmpty && len <= 0 } // scalac generates a `readReplace` method to discard the deserialized state (see https://github.com/scala/bug/issues/10412). diff --git a/src/library/scala/collection/concurrent/TrieMap.scala b/src/library/scala/collection/concurrent/TrieMap.scala index de6f49f039ee..a9f97b96491a 100644 --- a/src/library/scala/collection/concurrent/TrieMap.scala +++ b/src/library/scala/collection/concurrent/TrieMap.scala @@ -971,7 +971,7 @@ final class TrieMap[K, V] private (r: AnyRef, rtupd: AtomicReferenceFieldUpdater override def size: Int = if (nonReadOnly) readOnlySnapshot().size else cachedSize() - + override def isEmpty: Boolean = size == 0 override protected[this] def className = "TrieMap" } diff --git a/src/library/scala/collection/convert/Wrappers.scala b/src/library/scala/collection/convert/Wrappers.scala index b2689478d618..557a2064ae96 100644 --- a/src/library/scala/collection/convert/Wrappers.scala +++ b/src/library/scala/collection/convert/Wrappers.scala @@ -59,12 +59,14 @@ private[collection] trait Wrappers { case class JIterableWrapper[A](underlying: jl.Iterable[A]) extends AbstractIterable[A] { def iterator = underlying.iterator.asScala override def iterableFactory = mutable.ArrayBuffer + override def isEmpty: Boolean = !underlying.iterator().hasNext } @SerialVersionUID(3L) case class JCollectionWrapper[A](underlying: ju.Collection[A]) extends AbstractIterable[A] { def iterator = underlying.iterator.asScala override def size = underlying.size + override def knownSize: Int = if (underlying.isEmpty) 0 else super.knownSize override def isEmpty = underlying.isEmpty override def iterableFactory = mutable.ArrayBuffer } @@ -95,6 +97,7 @@ private[collection] trait Wrappers { @SerialVersionUID(3L) case class JListWrapper[A](underlying: ju.List[A]) extends mutable.AbstractBuffer[A] with SeqOps[A, mutable.Buffer, mutable.Buffer[A]] { def length = underlying.size + override def knownSize: Int = if (underlying.isEmpty) 0 else super.knownSize override def isEmpty = underlying.isEmpty override def iterator: Iterator[A] = underlying.iterator.asScala def apply(i: Int) = underlying.get(i) @@ -188,7 +191,8 @@ private[collection] trait Wrappers { case class JSetWrapper[A](underlying: ju.Set[A]) extends mutable.AbstractSet[A] with mutable.SetOps[A, mutable.Set, mutable.Set[A]] { override def size = underlying.size - + override def isEmpty: Boolean = underlying.isEmpty + override def knownSize: Int = if (underlying.isEmpty) 0 else super.knownSize def iterator = underlying.iterator.asScala def contains(elem: A): Boolean = underlying.contains(elem) @@ -355,6 +359,8 @@ private[collection] trait Wrappers { class JMapWrapper[A, B](val underlying : ju.Map[A, B]) extends AbstractJMapWrapper[A, B] { + override def isEmpty: Boolean = underlying.isEmpty + override def knownSize: Int = if (underlying.isEmpty) 0 else super.knownSize override def empty = new JMapWrapper(new ju.HashMap[A, B]) } @@ -392,6 +398,8 @@ private[collection] trait Wrappers { override def get(k: A) = Option(underlying get k) + override def isEmpty: Boolean = underlying.isEmpty + override def knownSize: Int = if (underlying.isEmpty) 0 else super.knownSize override def empty = new JConcurrentMapWrapper(new juc.ConcurrentHashMap[A, B]) def putIfAbsent(k: A, v: B): Option[B] = Option(underlying.putIfAbsent(k, v)) @@ -435,6 +443,8 @@ private[collection] trait Wrappers { @SerialVersionUID(3L) case class JDictionaryWrapper[A, B](underlying: ju.Dictionary[A, B]) extends mutable.AbstractMap[A, B] { override def size: Int = underlying.size + override def isEmpty: Boolean = underlying.isEmpty + override def knownSize: Int = if (underlying.isEmpty) 0 else super.knownSize def get(k: A) = Option(underlying get k) @@ -446,7 +456,6 @@ private[collection] trait Wrappers { override def update(k: A, v: B): Unit = { underlying.put(k, v) } override def remove(k: A): Option[B] = Option(underlying remove k) - def iterator = enumerationAsScalaIterator(underlying.keys) map (k => (k, underlying get k)) override def clear() = iterator.foreach(entry => underlying.remove(entry._1)) @@ -459,7 +468,8 @@ private[collection] trait Wrappers { with mutable.MapOps[String, String, mutable.Map, mutable.Map[String, String]] { override def size = underlying.size - + override def isEmpty: Boolean = underlying.isEmpty + override def knownSize: Int = size def get(k: String) = { val v = underlying get k if (v != null) Some(v.asInstanceOf[String]) else None diff --git a/src/library/scala/collection/generic/IsIterableLike.scala b/src/library/scala/collection/generic/IsIterableLike.scala index 72efffac69c3..2465177b834e 100644 --- a/src/library/scala/collection/generic/IsIterableLike.scala +++ b/src/library/scala/collection/generic/IsIterableLike.scala @@ -117,6 +117,9 @@ object IsIterableLike { def iterableFactory: IterableFactory[Iterable] = Iterable protected[this] def newSpecificBuilder(): mutable.Builder[Char, String] = new StringBuilder def iterator(): Iterator[Char] = s.iterator() + override def isEmpty: Boolean = s.isEmpty + override def knownSize: Int = s.length + override def size: Int = s.length } } @@ -130,6 +133,9 @@ object IsIterableLike { def iterableFactory: IterableFactory[Iterable] = Iterable protected def newSpecificBuilder: mutable.Builder[A, Array[A]] = Array.newBuilder def iterator: Iterator[A] = a.iterator + override def isEmpty: Boolean = a.length == 0 + override def knownSize: Int = a.length + override def size: Int = a.length } } diff --git a/src/library/scala/collection/immutable/ChampHashSet.scala b/src/library/scala/collection/immutable/ChampHashSet.scala index 2d45e9713a77..d35ac301d6eb 100644 --- a/src/library/scala/collection/immutable/ChampHashSet.scala +++ b/src/library/scala/collection/immutable/ChampHashSet.scala @@ -590,6 +590,7 @@ object ChampHashSet extends IterableFactory[ChampHashSet] { def from[A](source: collection.IterableOnce[A]): ChampHashSet[A] = source match { + case _ if source.knownSize == 0 => empty[A] case hs: ChampHashSet[A] => hs case _ => (newBuilder[A] ++= source).result() } diff --git a/src/library/scala/collection/immutable/HashMap.scala b/src/library/scala/collection/immutable/HashMap.scala index 05eaab7ba3ff..1f6e41822be1 100644 --- a/src/library/scala/collection/immutable/HashMap.scala +++ b/src/library/scala/collection/immutable/HashMap.scala @@ -173,6 +173,8 @@ object HashMap extends MapFactory[HashMap] { private object EmptyHashMap extends HashMap[Any, Nothing] { + override def isEmpty: Boolean = true + override def knownSize: Int = 0 protected def updated0[V1 >: Nothing](key: Any, hash: Int, level: Int, value: V1, kv: (Any, V1), merger: Merger[Any, V1]): HashMap[Any, V1] = new HashMap.HashMap1(key, hash, value, kv) @@ -203,14 +205,14 @@ object HashMap extends MapFactory[HashMap] { } final class HashMap1[K, +V](private[collection] val key: K, private[collection] val hash: Int, private[collection] val value: V, private[collection] var kv: (K, V@uV)) extends HashMap[K, V] { - + override def isEmpty: Boolean = false def iterator: Iterator[(K, V)] = Iterator.single(ensurePair) def get0(key: K, hash: Int, level: Int): Option[V] = if (hash == this.hash && key == this.key) Some(value) else None override def size = 1 - + override def knownSize: Int = 1 private[collection] def getKey = key private[collection] def getHash = hash private[collection] def computeHashFor(k: K) = computeHash(k) @@ -259,7 +261,7 @@ object HashMap extends MapFactory[HashMap] { // assert(kvs.size > 1) override def size: Int = kvs.size - + override def isEmpty: Boolean = false protected def get0(key: K, hash: Int, level: Int): Option[V] = if (hash == this.hash) kvs.get(key) else None @@ -335,7 +337,8 @@ object HashMap extends MapFactory[HashMap] { // assert(elems.length > 1 || (elems.length == 1 && elems(0).isInstanceOf[HashTrieMap[_,_]])) override def size: Int = size0 - + override def isEmpty: Boolean = false + override def knownSize: Int = size protected def get0(key: K, hash: Int, level: Int): Option[V] = { // Note: this code is duplicated with `contains0` val index = (hash >>> level) & 0x1f diff --git a/src/library/scala/collection/immutable/HashSet.scala b/src/library/scala/collection/immutable/HashSet.scala index c8f7951e443a..a2ef86ab4c94 100644 --- a/src/library/scala/collection/immutable/HashSet.scala +++ b/src/library/scala/collection/immutable/HashSet.scala @@ -170,7 +170,8 @@ object HashSet extends IterableFactory[HashSet] { private object EmptyHashSet extends HashSet[Any] { def iterator: Iterator[Any] = Iterator.empty - + override def isEmpty: Boolean = true + override def knownSize: Int = 0 override def foreach[U](f: Any => U): Unit = () override def head: Any = throw new NoSuchElementException("Empty Set") @@ -214,7 +215,8 @@ object HashSet extends IterableFactory[HashSet] { } private[immutable] final class HashSet1[A](private[HashSet] val key: A, private[HashSet] val hash: Int) extends LeafHashSet[A] { - + override def isEmpty: Boolean = false + override def knownSize: Int = 1 def iterator: Iterator[A] = Iterator.single(key) override def foreach[U](f: A => U): Unit = f(key) @@ -295,7 +297,7 @@ object HashSet extends IterableFactory[HashSet] { } private[immutable] final class HashSetCollision1[A](private[HashSet] val hash: Int, val ks: ListSet[A]) extends LeafHashSet[A] { - + override def isEmpty: Boolean = false override def size = ks.size def iterator: Iterator[A] = ks.iterator @@ -498,9 +500,9 @@ object HashSet extends IterableFactory[HashSet] { assert(Integer.bitCount(bitmap) == elems.length) // assertion has to remain disabled until SI-6197 is solved // assert(elems.length > 1 || (elems.length == 1 && elems(0).isInstanceOf[HashTrieSet[_]])) - override def size = size0 - + override def isEmpty: Boolean = false + override def knownSize: Int = size def iterator: Iterator[A] = new TrieIterator[A](elems.asInstanceOf[Array[Iterable[A]]]) { final override def getElem(cc: AnyRef): A = cc.asInstanceOf[HashSet1[A]].key } diff --git a/src/library/scala/collection/immutable/IntMap.scala b/src/library/scala/collection/immutable/IntMap.scala index a939fe900fb2..ec85e85a9ad9 100644 --- a/src/library/scala/collection/immutable/IntMap.scala +++ b/src/library/scala/collection/immutable/IntMap.scala @@ -261,7 +261,7 @@ sealed abstract class IntMap[+T] extends AbstractMap[Int, T] override protected[this] def className = "IntMap" override def isEmpty = this == IntMap.Nil - + override def knownSize: Int = if (isEmpty) 0 else super.knownSize override def filter(f: ((Int, T)) => Boolean): IntMap[T] = this match { case IntMap.Bin(prefix, mask, left, right) => { val (newleft, newright) = (left.filter(f), right.filter(f)) diff --git a/src/library/scala/collection/immutable/LazyList.scala b/src/library/scala/collection/immutable/LazyList.scala index d27be6c81964..84019f873c26 100644 --- a/src/library/scala/collection/immutable/LazyList.scala +++ b/src/library/scala/collection/immutable/LazyList.scala @@ -683,6 +683,7 @@ object LazyList extends LazyListFactory[LazyList] { } def from[A](coll: collection.IterableOnce[A]): LazyList[A] = coll match { + case _ if coll.knownSize == 0 => empty[A] case coll: LazyList[A] => coll case _ => fromIterator(coll.iterator) } diff --git a/src/library/scala/collection/immutable/List.scala b/src/library/scala/collection/immutable/List.scala index f51ce8ca8947..ad7324d67e33 100644 --- a/src/library/scala/collection/immutable/List.scala +++ b/src/library/scala/collection/immutable/List.scala @@ -582,6 +582,7 @@ case object Nil extends List[Nothing] { object List extends StrictOptimizedSeqFactory[List] { def from[B](coll: collection.IterableOnce[B]): List[B] = coll match { + case _ if coll.knownSize == 0 => empty[B] case coll: List[B] => coll case _ => ListBuffer.from(coll).toList } diff --git a/src/library/scala/collection/immutable/ListMap.scala b/src/library/scala/collection/immutable/ListMap.scala index 47f7dc56e706..f0e361cd8b3e 100644 --- a/src/library/scala/collection/immutable/ListMap.scala +++ b/src/library/scala/collection/immutable/ListMap.scala @@ -51,6 +51,7 @@ sealed class ListMap[K, +V] override def isEmpty: Boolean = true + override def knownSize: Int = 0 def get(key: K): Option[V] = None def updated[B1 >: V](key: K, value: B1): ListMap[K, B1] = new Node[B1](key, value) @@ -86,7 +87,7 @@ sealed class ListMap[K, +V] else sizeInternal(cur.next, acc + 1) override def isEmpty: Boolean = false - + override def knownSize: Int = -1 @throws[NoSuchElementException] override def apply(k: K): V1 = applyInternal(this, k) diff --git a/src/library/scala/collection/immutable/ListSet.scala b/src/library/scala/collection/immutable/ListSet.scala index 32b1247b9d15..1bfcb9ec0881 100644 --- a/src/library/scala/collection/immutable/ListSet.scala +++ b/src/library/scala/collection/immutable/ListSet.scala @@ -6,6 +6,7 @@ import java.io.{ObjectInputStream, ObjectOutputStream} import mutable.{Builder, ImmutableBuilder} import scala.annotation.tailrec +import scala.collection.immutable.List.empty /** * This class implements immutable sets using a list-based data structure. List set iterators and @@ -36,6 +37,7 @@ sealed class ListSet[A] override protected[this] def className: String = "ListSet" override def size: Int = 0 + override def knownSize: Int = 0 override def isEmpty: Boolean = true def contains(elem: A): Boolean = false @@ -64,7 +66,7 @@ sealed class ListSet[A] protected class Node(override protected val elem: A) extends ListSet[A] { override def size = sizeInternal(this, 0) - + override def knownSize: Int = -1 @tailrec private[this] def sizeInternal(n: ListSet[A], acc: Int): Int = if (n.isEmpty) acc else sizeInternal(n.next, acc + 1) @@ -109,11 +111,14 @@ object ListSet extends IterableFactory[ListSet] { def from[E](it: scala.collection.IterableOnce[E]): ListSet[E] = it match { + case _ if it.knownSize == 0 => empty[E] case ls: ListSet[E] => ls case _ => (newBuilder[E] ++= it).result() } - private object EmptyListSet extends ListSet[Any] + private object EmptyListSet extends ListSet[Any] { + override def knownSize: Int = 0 + } private[collection] def emptyInstance: ListSet[Any] = EmptyListSet def empty[A]: ListSet[A] = EmptyListSet.asInstanceOf[ListSet[A]] diff --git a/src/library/scala/collection/immutable/LongMap.scala b/src/library/scala/collection/immutable/LongMap.scala index be52ebd66f34..2aebc48de049 100644 --- a/src/library/scala/collection/immutable/LongMap.scala +++ b/src/library/scala/collection/immutable/LongMap.scala @@ -256,7 +256,7 @@ sealed abstract class LongMap[+T] extends AbstractMap[Long, T] override protected[this] def className = "LongMap" override def isEmpty = this == LongMap.Nil - + override def knownSize: Int = if (isEmpty) 0 else super.knownSize override def filter(f: ((Long, T)) => Boolean): LongMap[T] = this match { case LongMap.Bin(prefix, mask, left, right) => { val (newleft, newright) = (left.filter(f), right.filter(f)) diff --git a/src/library/scala/collection/immutable/Map.scala b/src/library/scala/collection/immutable/Map.scala index 870469d17b78..e132051985b1 100644 --- a/src/library/scala/collection/immutable/Map.scala +++ b/src/library/scala/collection/immutable/Map.scala @@ -148,6 +148,8 @@ object Map extends MapFactory[Map] { def iterator: Iterator[(K, V)] = underlying.iterator + override def isEmpty: Boolean = underlying.isEmpty + override def mapFactory: MapFactory[Map] = underlying.mapFactory def remove(key: K): WithDefault[K, V] = new WithDefault[K, V](underlying.remove(key), defaultValue) @@ -168,6 +170,7 @@ object Map extends MapFactory[Map] { def from[K, V](it: collection.IterableOnce[(K, V)]): Map[K, V] = it match { + case it: Iterable[_] if it.isEmpty => empty[K, V] case m: Map[K, V] => m case _ => (newBuilder[K, V] ++= it).result() } @@ -180,6 +183,7 @@ object Map extends MapFactory[Map] { private object EmptyMap extends AbstractMap[Any, Nothing] { override def size: Int = 0 override def knownSize: Int = 0 + override def isEmpty: Boolean = true override def apply(key: Any) = throw new NoSuchElementException("key not found: " + key) override def contains(key: Any) = false def get(key: Any): Option[Nothing] = None @@ -192,6 +196,7 @@ object Map extends MapFactory[Map] { final class Map1[K, +V](key1: K, value1: V) extends AbstractMap[K, V] with StrictOptimizedIterableOps[(K, V), Iterable, Map[K, V]] { override def size: Int = 1 override def knownSize: Int = 1 + override def isEmpty: Boolean = false override def apply(key: K) = if (key == key1) value1 else throw new NoSuchElementException("key not found: " + key) override def contains(key: K) = key == key1 def get(key: K): Option[V] = @@ -214,6 +219,7 @@ object Map extends MapFactory[Map] { final class Map2[K, +V](key1: K, value1: V, key2: K, value2: V) extends AbstractMap[K, V] with StrictOptimizedIterableOps[(K, V), Iterable, Map[K, V]] { override def size: Int = 2 override def knownSize: Int = 2 + override def isEmpty: Boolean = false override def apply(key: K) = if (key == key1) value1 else if (key == key2) value2 @@ -267,6 +273,7 @@ object Map extends MapFactory[Map] { class Map3[K, +V](key1: K, value1: V, key2: K, value2: V, key3: K, value3: V) extends AbstractMap[K, V] with StrictOptimizedIterableOps[(K, V), Iterable, Map[K, V]] { override def size: Int = 3 override def knownSize: Int = 3 + override def isEmpty: Boolean = false override def apply(key: K) = if (key == key1) value1 else if (key == key2) value2 @@ -326,6 +333,7 @@ object Map extends MapFactory[Map] { final class Map4[K, +V](key1: K, value1: V, key2: K, value2: V, key3: K, value3: V, key4: K, value4: V) extends AbstractMap[K, V] with StrictOptimizedIterableOps[(K, V), Iterable, Map[K, V]] { override def size: Int = 4 override def knownSize: Int = 4 + override def isEmpty: Boolean = false override def apply(key: K) = if (key == key1) value1 else if (key == key2) value2 diff --git a/src/library/scala/collection/immutable/Queue.scala b/src/library/scala/collection/immutable/Queue.scala index f4b9c3262dec..32fd8cf121fd 100644 --- a/src/library/scala/collection/immutable/Queue.scala +++ b/src/library/scala/collection/immutable/Queue.scala @@ -11,6 +11,7 @@ package immutable import java.io.{ObjectInputStream, ObjectOutputStream} +import scala.collection.immutable.List.empty import scala.collection.mutable.{Builder, ListBuffer} /** `Queue` objects implement data structures that allow to @@ -175,7 +176,11 @@ sealed class Queue[+A] protected(protected val in: List[A], protected val out: L object Queue extends StrictOptimizedSeqFactory[Queue] { def newBuilder[A]: Builder[A, Queue[A]] = new ListBuffer[A] mapResult (x => new Queue[A](Nil, x.toList)) - def from[A](source: IterableOnce[A]): Queue[A] = new Queue[A](Nil, ListBuffer.from(source).toList) + def from[A](source: IterableOnce[A]): Queue[A] = source match { + case _ if source.knownSize == 0 => empty[A] + case q: Queue[A] => q + case _ => new Queue[A](Nil, ListBuffer.from(source).toList) + } def empty[A]: Queue[A] = EmptyQueue override def apply[A](xs: A*): Queue[A] = new Queue[A](Nil, xs.toList) diff --git a/src/library/scala/collection/immutable/Set.scala b/src/library/scala/collection/immutable/Set.scala index 81bf96b92d6f..f95468e21c4d 100644 --- a/src/library/scala/collection/immutable/Set.scala +++ b/src/library/scala/collection/immutable/Set.scala @@ -4,6 +4,7 @@ package immutable import java.io.{ObjectInputStream, ObjectOutputStream} +import scala.collection.immutable.List.empty import scala.collection.mutable.{Builder, ImmutableBuilder} import scala.language.higherKinds @@ -85,6 +86,7 @@ object Set extends IterableFactory[Set] { def from[E](it: collection.IterableOnce[E]): Set[E] = it match { + case _ if it.knownSize == 0 => empty[E] // We want `SortedSet` (and subclasses, such as `BitSet`) to // rebuild themselves to avoid element type widening issues case _: SortedSet[E] => (newBuilder[E] ++= it).result() @@ -101,6 +103,7 @@ object Set extends IterableFactory[Set] { private object EmptySet extends AbstractSet[Any] { override def size: Int = 0 override def isEmpty = true + override def knownSize: Int = size def contains(elem: Any): Boolean = false def incl(elem: Any): Set[Any] = new Set1(elem) def excl(elem: Any): Set[Any] = this @@ -113,6 +116,7 @@ object Set extends IterableFactory[Set] { final class Set1[A] private[collection] (elem1: A) extends AbstractSet[A] with StrictOptimizedIterableOps[A, Set, Set[A]] { override def size: Int = 1 override def isEmpty = false + override def knownSize: Int = size def contains(elem: A): Boolean = elem == elem1 def incl(elem: A): Set[A] = if (contains(elem)) this @@ -135,6 +139,7 @@ object Set extends IterableFactory[Set] { final class Set2[A] private[collection] (elem1: A, elem2: A) extends AbstractSet[A] with StrictOptimizedIterableOps[A, Set, Set[A]] { override def size: Int = 2 override def isEmpty = false + override def knownSize: Int = size def contains(elem: A): Boolean = elem == elem1 || elem == elem2 def incl(elem: A): Set[A] = if (contains(elem)) this @@ -166,6 +171,7 @@ object Set extends IterableFactory[Set] { final class Set3[A] private[collection] (elem1: A, elem2: A, elem3: A) extends AbstractSet[A] with StrictOptimizedIterableOps[A, Set, Set[A]] { override def size: Int = 3 override def isEmpty = false + override def knownSize: Int = size def contains(elem: A): Boolean = elem == elem1 || elem == elem2 || elem == elem3 def incl(elem: A): Set[A] = @@ -200,6 +206,7 @@ object Set extends IterableFactory[Set] { final class Set4[A] private[collection] (elem1: A, elem2: A, elem3: A, elem4: A) extends AbstractSet[A] with StrictOptimizedIterableOps[A, Set, Set[A]] { override def size: Int = 4 override def isEmpty = false + override def knownSize: Int = size def contains(elem: A): Boolean = elem == elem1 || elem == elem2 || elem == elem3 || elem == elem4 def incl(elem: A): Set[A] = diff --git a/src/library/scala/collection/immutable/TreeMap.scala b/src/library/scala/collection/immutable/TreeMap.scala index bbfe5742e131..ef42a6983217 100644 --- a/src/library/scala/collection/immutable/TreeMap.scala +++ b/src/library/scala/collection/immutable/TreeMap.scala @@ -82,6 +82,7 @@ final class TreeMap[K, +V] private (tree: RB.Tree[K, V])(implicit val ordering: override def foreach[U](f: ((K, V)) => U): Unit = RB.foreach(tree, f) override def size: Int = RB.count(tree) + override def knownSize: Int = size override def isEmpty = size == 0 diff --git a/src/library/scala/collection/immutable/Vector.scala b/src/library/scala/collection/immutable/Vector.scala index 39d0c238ca25..6c70a84357cc 100644 --- a/src/library/scala/collection/immutable/Vector.scala +++ b/src/library/scala/collection/immutable/Vector.scala @@ -6,6 +6,8 @@ import java.io.{ObjectInputStream, ObjectOutputStream} import scala.collection.mutable.{Builder, ReusableBuilder} import scala.annotation.unchecked.uncheckedVariance +import scala.collection.immutable.List.empty +import scala.collection.immutable.Set.empty /** $factoryInfo * @define Coll `Vector` @@ -18,6 +20,7 @@ object Vector extends StrictOptimizedSeqFactory[Vector] { def from[E](it: collection.IterableOnce[E]): Vector[E] = it match { + case _ if it.knownSize == 0 => empty[E] case v: Vector[E] => v case _ => (newBuilder ++= it).result() } diff --git a/src/library/scala/collection/mutable/AnyRefMap.scala b/src/library/scala/collection/mutable/AnyRefMap.scala index 9c5cfb3c5f12..14fd43aa8eee 100644 --- a/src/library/scala/collection/mutable/AnyRefMap.scala +++ b/src/library/scala/collection/mutable/AnyRefMap.scala @@ -86,6 +86,8 @@ class AnyRefMap[K <: AnyRef, V] private[collection] (defaultEntry: K => V, initi override protected def newSpecificBuilder: Builder[(K, V), AnyRefMap[K,V]] = new AnyRefMapBuilder override def size: Int = _size + override def knownSize: Int = size + override def isEmpty: Boolean = _size == 0 override def empty: AnyRefMap[K,V] = new AnyRefMap(defaultEntry) private def imbalanced: Boolean = diff --git a/src/library/scala/collection/mutable/LinkedHashMap.scala b/src/library/scala/collection/mutable/LinkedHashMap.scala index d19acc86d083..fec413721850 100644 --- a/src/library/scala/collection/mutable/LinkedHashMap.scala +++ b/src/library/scala/collection/mutable/LinkedHashMap.scala @@ -82,7 +82,8 @@ class LinkedHashMap[K, V] override def empty = LinkedHashMap.empty[K, V] override def size = table.tableSize - + override def knownSize: Int = size + override def isEmpty: Boolean = table.tableSize == 0 def get(key: K): Option[V] = { val e = table.findEntry(key) if (e == null) None diff --git a/src/library/scala/collection/mutable/LinkedHashSet.scala b/src/library/scala/collection/mutable/LinkedHashSet.scala index 48d03eeffc00..cc67c8f56d02 100644 --- a/src/library/scala/collection/mutable/LinkedHashSet.scala +++ b/src/library/scala/collection/mutable/LinkedHashSet.scala @@ -59,7 +59,8 @@ class LinkedHashSet[A] } override def size: Int = table.tableSize - + override def knownSize: Int = size + override def isEmpty: Boolean = size == 0 def contains(elem: A): Boolean = table.findEntry(elem) ne null def addOne(elem: A): this.type = { diff --git a/src/library/scala/collection/mutable/ListMap.scala b/src/library/scala/collection/mutable/ListMap.scala index 324c315367a2..7842c75e9963 100644 --- a/src/library/scala/collection/mutable/ListMap.scala +++ b/src/library/scala/collection/mutable/ListMap.scala @@ -52,7 +52,8 @@ class ListMap[K, V] final override def clear(): Unit = { elems = List(); siz = 0 } final override def size: Int = siz - + override def knownSize: Int = size + override def isEmpty: Boolean = size == 0 override protected[this] def stringPrefix = "ListMap" } diff --git a/src/library/scala/collection/mutable/LongMap.scala b/src/library/scala/collection/mutable/LongMap.scala index c467542982c3..66c49af84162 100644 --- a/src/library/scala/collection/mutable/LongMap.scala +++ b/src/library/scala/collection/mutable/LongMap.scala @@ -83,6 +83,8 @@ final class LongMap[V] private[collection] (defaultEntry: Long => V, initialBuff } override def size: Int = _size + (extraKeys+1)/2 + override def knownSize: Int = size + override def isEmpty: Boolean = size == 0 override def empty: LongMap[V] = new LongMap() private def imbalanced: Boolean = diff --git a/src/library/scala/collection/mutable/Map.scala b/src/library/scala/collection/mutable/Map.scala index d217c2274112..bd8e92ae0ba2 100644 --- a/src/library/scala/collection/mutable/Map.scala +++ b/src/library/scala/collection/mutable/Map.scala @@ -187,7 +187,8 @@ object Map extends MapFactory.Delegate[Map](HashMap) { override def default(key: K): V = defaultValue(key) def iterator: scala.collection.Iterator[(K, V)] = underlying.iterator - + override def isEmpty: Boolean = underlying.isEmpty + override def knownSize: Int = underlying.knownSize override def mapFactory: MapFactory[Map] = underlying.mapFactory override def clear(): Unit = underlying.clear() diff --git a/src/library/scala/collection/mutable/OpenHashMap.scala b/src/library/scala/collection/mutable/OpenHashMap.scala index d3e640dd5729..4b7cddb87801 100644 --- a/src/library/scala/collection/mutable/OpenHashMap.scala +++ b/src/library/scala/collection/mutable/OpenHashMap.scala @@ -90,8 +90,9 @@ class OpenHashMap[Key, Value](initialSize : Int) private[this] var modCount = 0 override def size = _size + override def knownSize: Int = size private[this] def size_=(s : Int): Unit = _size = s - + override def isEmpty: Boolean = _size == 0 /** Returns a mangled hash code of the provided key. */ protected def hashOf(key: Key) = { var h = key.## diff --git a/src/library/scala/collection/mutable/PriorityQueue.scala b/src/library/scala/collection/mutable/PriorityQueue.scala index aad134e0dc7e..cf8b1a15e4c3 100644 --- a/src/library/scala/collection/mutable/PriorityQueue.scala +++ b/src/library/scala/collection/mutable/PriorityQueue.scala @@ -73,6 +73,7 @@ sealed class PriorityQueue[A](implicit val ord: Ordering[A]) resarr.p_size0 += 1 // we do not use array(0) def length: Int = resarr.length - 1 // adjust length accordingly override def size: Int = length + override def knownSize: Int = length override def isEmpty: Boolean = resarr.p_size0 < 2 override protected def fromSpecificIterable(coll: scala.collection.Iterable[A]): PriorityQueue[A] = PriorityQueue.from(coll) diff --git a/src/library/scala/collection/mutable/TreeMap.scala b/src/library/scala/collection/mutable/TreeMap.scala index 4f59339db7b0..bd4ead7b4d9a 100644 --- a/src/library/scala/collection/mutable/TreeMap.scala +++ b/src/library/scala/collection/mutable/TreeMap.scala @@ -82,7 +82,7 @@ sealed class TreeMap[K, V] private (tree: RB.Tree[K, V])(implicit val ordering: override def foreach[U](f: ((K, V)) => U): Unit = RB.foreach(tree, f) override def size: Int = RB.size(tree) - + override def knownSize: Int = size override def isEmpty: Boolean = RB.isEmpty(tree) override def contains(key: K): Boolean = RB.contains(tree, key) @@ -151,7 +151,8 @@ sealed class TreeMap[K, V] private (tree: RB.Tree[K, V])(implicit val ordering: override def keysIteratorFrom(start: K) = RB.keysIterator(tree, pickLowerBound(Some(start)), until) override def iteratorFrom(start: K) = RB.iterator(tree, pickLowerBound(Some(start)), until) override def valuesIteratorFrom(start: K) = RB.valuesIterator(tree, pickLowerBound(Some(start)), until) - override def size = iterator.length + override def size = if (RB.size(tree) == 0) 0 else iterator.length + override def knownSize: Int = if (RB.size(tree) == 0) 0 else -1 override def isEmpty = RB.size(tree) == 0 || !iterator.hasNext override def contains(key: K) = isInsideViewBounds(key) && RB.contains(tree, key) diff --git a/src/library/scala/collection/mutable/TreeSet.scala b/src/library/scala/collection/mutable/TreeSet.scala index bb42d9bc6c47..be236c14019c 100644 --- a/src/library/scala/collection/mutable/TreeSet.scala +++ b/src/library/scala/collection/mutable/TreeSet.scala @@ -65,7 +65,7 @@ sealed class TreeSet[A] private (tree: RB.Tree[A, Null])(implicit val ordering: override protected[this] def className: String = "TreeSet" override def size: Int = RB.size(tree) - + override def knownSize: Int = size override def isEmpty: Boolean = RB.isEmpty(tree) override def head: A = RB.minKey(tree).get @@ -129,8 +129,9 @@ sealed class TreeSet[A] private (tree: RB.Tree[A, Null])(implicit val ordering: override def iterator = RB.keysIterator(tree, from, until) override def iteratorFrom(start: A) = RB.keysIterator(tree, pickLowerBound(Some(start)), until) - override def size = iterator.length - override def isEmpty = !iterator.hasNext + override def size = if (RB.size(tree) == 0) 0 else iterator.length + override def knownSize: Int = if (RB.size(tree) == 0) 0 else -1 + override def isEmpty = RB.size(tree) == 0 || !iterator.hasNext override def head = headOption.get override def headOption = { diff --git a/src/library/scala/runtime/Tuple2Zipped.scala b/src/library/scala/runtime/Tuple2Zipped.scala index b9370ed0fb3e..22555d4a4afd 100644 --- a/src/library/scala/runtime/Tuple2Zipped.scala +++ b/src/library/scala/runtime/Tuple2Zipped.scala @@ -23,11 +23,13 @@ import scala.language.implicitConversions */ trait ZippedIterable2[+El1, +El2] extends Any { def iterator: Iterator[(El1, El2)] + def isEmpty: Boolean } object ZippedIterable2 { implicit def zippedIterable2ToIterable[El1, El2](zz: ZippedIterable2[El1, El2]): Iterable[(El1, El2)] = { new scala.collection.AbstractIterable[(El1, El2)] { def iterator: Iterator[(El1, El2)] = zz.iterator + override def isEmpty: Boolean = zz.isEmpty } } } @@ -101,7 +103,7 @@ final class Tuple2Zipped[El1, It1 <: Iterable[El1], El2, It2 <: Iterable[El2]](p !exists((x, y) => !p(x, y)) def iterator: Iterator[(El1, El2)] = coll1.iterator.zip(coll2.iterator) - + override def isEmpty: Boolean = coll1.isEmpty || coll2.isEmpty def foreach[U](f: (El1, El2) => U): Unit = { val elems2 = coll2.iterator diff --git a/src/library/scala/runtime/Tuple3Zipped.scala b/src/library/scala/runtime/Tuple3Zipped.scala index 01ab2f3d5ae2..87a684500c45 100644 --- a/src/library/scala/runtime/Tuple3Zipped.scala +++ b/src/library/scala/runtime/Tuple3Zipped.scala @@ -21,11 +21,13 @@ import scala.language.implicitConversions */ trait ZippedIterable3[+El1, +El2, +El3] extends Any { def iterator: Iterator[(El1, El2, El3)] + def isEmpty: Boolean } object ZippedIterable3 { implicit def zippedIterable3ToIterable[El1, El2, El3](zz: ZippedIterable3[El1, El2, El3]): Iterable[(El1, El2, El3)] = { new scala.collection.AbstractIterable[(El1, El2, El3)] { def iterator: Iterator[(El1, El2, El3)] = zz.iterator + override def isEmpty: Boolean = zz.isEmpty } } } @@ -111,7 +113,7 @@ final class Tuple3Zipped[El1, It1 <: Iterable[El1], El2, It2 <: Iterable[El2], E !exists((x, y, z) => !p(x, y, z)) def iterator: Iterator[(El1, El2, El3)] = coll1.iterator.zip(coll2.iterator).zip(coll3.iterator).map { case ((a, b), c) => (a, b, c)} - + override def isEmpty: Boolean = coll1.isEmpty || coll2.isEmpty || coll3.isEmpty def foreach[U](f: (El1, El2, El3) => U): Unit = { val elems2 = coll2.iterator val elems3 = coll3.iterator diff --git a/src/library/scala/sys/SystemProperties.scala b/src/library/scala/sys/SystemProperties.scala index db079cb1f53f..0475a979623f 100644 --- a/src/library/scala/sys/SystemProperties.scala +++ b/src/library/scala/sys/SystemProperties.scala @@ -38,6 +38,7 @@ extends mutable.AbstractMap[String, String] { names map (k => (k, ps getProperty k)) filter (_._2 ne null) } getOrElse Iterator.empty + override def isEmpty: Boolean = iterator.isEmpty def names: Iterator[String] = wrapAccess ( System.getProperties().stringPropertyNames().asScala.iterator ) getOrElse Iterator.empty diff --git a/src/reflect/scala/reflect/internal/util/WeakHashSet.scala b/src/reflect/scala/reflect/internal/util/WeakHashSet.scala index d430c02c3429..3a1fdc4fbf8d 100644 --- a/src/reflect/scala/reflect/internal/util/WeakHashSet.scala +++ b/src/reflect/scala/reflect/internal/util/WeakHashSet.scala @@ -270,6 +270,7 @@ final class WeakHashSet[A <: AnyRef](val initialCapacity: Int, val loadFactor: D count } + override def isEmpty: Boolean = size == 0 override def foreach[U](f: A => U): Unit = iterator foreach f // It has the `()` because iterator runs `removeStaleEntries()` diff --git a/src/reflect/scala/reflect/io/AbstractFile.scala b/src/reflect/scala/reflect/io/AbstractFile.scala index 24b0cd846bc4..889d36d690fa 100644 --- a/src/reflect/scala/reflect/io/AbstractFile.scala +++ b/src/reflect/scala/reflect/io/AbstractFile.scala @@ -191,7 +191,7 @@ abstract class AbstractFile extends AbstractIterable[AbstractFile] { /** Returns all abstract subfiles of this abstract directory. */ def iterator: Iterator[AbstractFile] - + override def isEmpty: Boolean = iterator.isEmpty /** Returns the abstract file in this abstract directory with the specified * name. If there is no such file, returns `null`. The argument * `directory` tells whether to look for a directory or diff --git a/test/junit/scala/SerializationStabilityTest.scala b/test/junit/scala/SerializationStabilityTest.scala index 698fa4396740..ac31fa1b5878 100644 --- a/test/junit/scala/SerializationStabilityTest.scala +++ b/test/junit/scala/SerializationStabilityTest.scala @@ -81,7 +81,7 @@ object SerializationStability { } } - // Generated on 20180619-13:58:28 with Scala version 2.13.0-20180618-031324-c034244) + // Generated on 20180619-14:05:35 with Scala version 2.13.0-20180618-031324-c034244) def main(args: Array[String]): Unit = { overwrite.foreach(updateComment) def g = Thread.currentThread.getStackTrace @@ -120,8 +120,8 @@ object SerializationStability { // TODO scala/bug#8576 unstable under -Xcheckinit check(g)(collection.convert.Wrappers)( "rO0ABXNyACJzY2FsYS5jb2xsZWN0aW9uLmNvbnZlcnQuV3JhcHBlcnMkAAAAAAAAAAMCABFMABhEaWN0aW9uYXJ5V3JhcHBlciRtb2R1bGV0ADZMc2NhbGEvY29sbGVjdGlvbi9jb252ZXJ0L1dyYXBwZXJzJERpY3Rpb25hcnlXcmFwcGVyJDtMABZJdGVyYWJsZVdyYXBwZXIkbW9kdWxldAA0THNjYWxhL2NvbGxlY3Rpb24vY29udmVydC9XcmFwcGVycyRJdGVyYWJsZVdyYXBwZXIkO0wAFkl0ZXJhdG9yV3JhcHBlciRtb2R1bGV0ADRMc2NhbGEvY29sbGVjdGlvbi9jb252ZXJ0L1dyYXBwZXJzJEl0ZXJhdG9yV3JhcHBlciQ7TAAZSkNvbGxlY3Rpb25XcmFwcGVyJG1vZHVsZXQAN0xzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkSkNvbGxlY3Rpb25XcmFwcGVyJDtMABxKQ29uY3VycmVudE1hcFdyYXBwZXIkbW9kdWxldAA6THNjYWxhL2NvbGxlY3Rpb24vY29udmVydC9XcmFwcGVycyRKQ29uY3VycmVudE1hcFdyYXBwZXIkO0wAGUpEaWN0aW9uYXJ5V3JhcHBlciRtb2R1bGV0ADdMc2NhbGEvY29sbGVjdGlvbi9jb252ZXJ0L1dyYXBwZXJzJEpEaWN0aW9uYXJ5V3JhcHBlciQ7TAAaSkVudW1lcmF0aW9uV3JhcHBlciRtb2R1bGV0ADhMc2NhbGEvY29sbGVjdGlvbi9jb252ZXJ0L1dyYXBwZXJzJEpFbnVtZXJhdGlvbldyYXBwZXIkO0wAF0pJdGVyYWJsZVdyYXBwZXIkbW9kdWxldAA1THNjYWxhL2NvbGxlY3Rpb24vY29udmVydC9XcmFwcGVycyRKSXRlcmFibGVXcmFwcGVyJDtMABdKSXRlcmF0b3JXcmFwcGVyJG1vZHVsZXQANUxzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkSkl0ZXJhdG9yV3JhcHBlciQ7TAATSkxpc3RXcmFwcGVyJG1vZHVsZXQAMUxzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkSkxpc3RXcmFwcGVyJDtMABlKUHJvcGVydGllc1dyYXBwZXIkbW9kdWxldAA3THNjYWxhL2NvbGxlY3Rpb24vY29udmVydC9XcmFwcGVycyRKUHJvcGVydGllc1dyYXBwZXIkO0wAEkpTZXRXcmFwcGVyJG1vZHVsZXQAMExzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkSlNldFdyYXBwZXIkO0wAG011dGFibGVCdWZmZXJXcmFwcGVyJG1vZHVsZXQAOUxzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkTXV0YWJsZUJ1ZmZlcldyYXBwZXIkO0wAGE11dGFibGVNYXBXcmFwcGVyJG1vZHVsZXQANkxzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkTXV0YWJsZU1hcFdyYXBwZXIkO0wAGE11dGFibGVTZXFXcmFwcGVyJG1vZHVsZXQANkxzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkTXV0YWJsZVNlcVdyYXBwZXIkO0wAGE11dGFibGVTZXRXcmFwcGVyJG1vZHVsZXQANkxzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkTXV0YWJsZVNldFdyYXBwZXIkO0wAEVNlcVdyYXBwZXIkbW9kdWxldAAvTHNjYWxhL2NvbGxlY3Rpb24vY29udmVydC9XcmFwcGVycyRTZXFXcmFwcGVyJDt4cHBwcHBwcHBwcHBwcHBwcHBw") - check(g)(new collection.convert.Wrappers.SetWrapper(immutable.Set()))("rO0ABXNyACxzY2FsYS5jb2xsZWN0aW9uLmNvbnZlcnQuV3JhcHBlcnMkU2V0V3JhcHBlcgAAAAAAAAADAgACTAAGJG91dGVydAAjTHNjYWxhL2NvbGxlY3Rpb24vY29udmVydC9XcmFwcGVycztMADhzY2FsYSRjb2xsZWN0aW9uJGNvbnZlcnQkV3JhcHBlcnMkU2V0V3JhcHBlciQkdW5kZXJseWluZ3QAFkxzY2FsYS9jb2xsZWN0aW9uL1NldDt4cHNyACJzY2FsYS5jb2xsZWN0aW9uLmNvbnZlcnQuV3JhcHBlcnMkAAAAAAAAAAMCABFMABhEaWN0aW9uYXJ5V3JhcHBlciRtb2R1bGV0ADZMc2NhbGEvY29sbGVjdGlvbi9jb252ZXJ0L1dyYXBwZXJzJERpY3Rpb25hcnlXcmFwcGVyJDtMABZJdGVyYWJsZVdyYXBwZXIkbW9kdWxldAA0THNjYWxhL2NvbGxlY3Rpb24vY29udmVydC9XcmFwcGVycyRJdGVyYWJsZVdyYXBwZXIkO0wAFkl0ZXJhdG9yV3JhcHBlciRtb2R1bGV0ADRMc2NhbGEvY29sbGVjdGlvbi9jb252ZXJ0L1dyYXBwZXJzJEl0ZXJhdG9yV3JhcHBlciQ7TAAZSkNvbGxlY3Rpb25XcmFwcGVyJG1vZHVsZXQAN0xzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkSkNvbGxlY3Rpb25XcmFwcGVyJDtMABxKQ29uY3VycmVudE1hcFdyYXBwZXIkbW9kdWxldAA6THNjYWxhL2NvbGxlY3Rpb24vY29udmVydC9XcmFwcGVycyRKQ29uY3VycmVudE1hcFdyYXBwZXIkO0wAGUpEaWN0aW9uYXJ5V3JhcHBlciRtb2R1bGV0ADdMc2NhbGEvY29sbGVjdGlvbi9jb252ZXJ0L1dyYXBwZXJzJEpEaWN0aW9uYXJ5V3JhcHBlciQ7TAAaSkVudW1lcmF0aW9uV3JhcHBlciRtb2R1bGV0ADhMc2NhbGEvY29sbGVjdGlvbi9jb252ZXJ0L1dyYXBwZXJzJEpFbnVtZXJhdGlvbldyYXBwZXIkO0wAF0pJdGVyYWJsZVdyYXBwZXIkbW9kdWxldAA1THNjYWxhL2NvbGxlY3Rpb24vY29udmVydC9XcmFwcGVycyRKSXRlcmFibGVXcmFwcGVyJDtMABdKSXRlcmF0b3JXcmFwcGVyJG1vZHVsZXQANUxzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkSkl0ZXJhdG9yV3JhcHBlciQ7TAATSkxpc3RXcmFwcGVyJG1vZHVsZXQAMUxzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkSkxpc3RXcmFwcGVyJDtMABlKUHJvcGVydGllc1dyYXBwZXIkbW9kdWxldAA3THNjYWxhL2NvbGxlY3Rpb24vY29udmVydC9XcmFwcGVycyRKUHJvcGVydGllc1dyYXBwZXIkO0wAEkpTZXRXcmFwcGVyJG1vZHVsZXQAMExzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkSlNldFdyYXBwZXIkO0wAG011dGFibGVCdWZmZXJXcmFwcGVyJG1vZHVsZXQAOUxzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkTXV0YWJsZUJ1ZmZlcldyYXBwZXIkO0wAGE11dGFibGVNYXBXcmFwcGVyJG1vZHVsZXQANkxzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkTXV0YWJsZU1hcFdyYXBwZXIkO0wAGE11dGFibGVTZXFXcmFwcGVyJG1vZHVsZXQANkxzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkTXV0YWJsZVNlcVdyYXBwZXIkO0wAGE11dGFibGVTZXRXcmFwcGVyJG1vZHVsZXQANkxzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkTXV0YWJsZVNldFdyYXBwZXIkO0wAEVNlcVdyYXBwZXIkbW9kdWxldAAvTHNjYWxhL2NvbGxlY3Rpb24vY29udmVydC9XcmFwcGVycyRTZXFXcmFwcGVyJDt4cHBwcHBwcHBwcHBwcHBwcHBwc3IAMnNjYWxhLmNvbGxlY3Rpb24uZ2VuZXJpYy5EZWZhdWx0U2VyaWFsaXphdGlvblByb3h5AAAAAAAAAAMDAAFMAAdmYWN0b3J5dAAaTHNjYWxhL2NvbGxlY3Rpb24vRmFjdG9yeTt4cHNyACpzY2FsYS5jb2xsZWN0aW9uLkl0ZXJhYmxlRmFjdG9yeSRUb0ZhY3RvcnkAAAAAAAAAAwIAAUwAB2ZhY3Rvcnl0ACJMc2NhbGEvY29sbGVjdGlvbi9JdGVyYWJsZUZhY3Rvcnk7eHBzcgAfc2NhbGEuY29sbGVjdGlvbi5pbW11dGFibGUuU2V0JAAAAAAAAAADAwABWgArc2NhbGEkY29sbGVjdGlvbiRpbW11dGFibGUkU2V0JCR1c2VCYXNlbGluZXhweHcE/////3NyACZzY2FsYS5jb2xsZWN0aW9uLmdlbmVyaWMuU2VyaWFsaXplRW5kJAAAAAAAAAADAgAAeHB4") - check(g)(new collection.convert.Wrappers.SetWrapper(immutable.Set(1, 2, 3)))("rO0ABXNyACxzY2FsYS5jb2xsZWN0aW9uLmNvbnZlcnQuV3JhcHBlcnMkU2V0V3JhcHBlcgAAAAAAAAADAgACTAAGJG91dGVydAAjTHNjYWxhL2NvbGxlY3Rpb24vY29udmVydC9XcmFwcGVycztMADhzY2FsYSRjb2xsZWN0aW9uJGNvbnZlcnQkV3JhcHBlcnMkU2V0V3JhcHBlciQkdW5kZXJseWluZ3QAFkxzY2FsYS9jb2xsZWN0aW9uL1NldDt4cHNyACJzY2FsYS5jb2xsZWN0aW9uLmNvbnZlcnQuV3JhcHBlcnMkAAAAAAAAAAMCABFMABhEaWN0aW9uYXJ5V3JhcHBlciRtb2R1bGV0ADZMc2NhbGEvY29sbGVjdGlvbi9jb252ZXJ0L1dyYXBwZXJzJERpY3Rpb25hcnlXcmFwcGVyJDtMABZJdGVyYWJsZVdyYXBwZXIkbW9kdWxldAA0THNjYWxhL2NvbGxlY3Rpb24vY29udmVydC9XcmFwcGVycyRJdGVyYWJsZVdyYXBwZXIkO0wAFkl0ZXJhdG9yV3JhcHBlciRtb2R1bGV0ADRMc2NhbGEvY29sbGVjdGlvbi9jb252ZXJ0L1dyYXBwZXJzJEl0ZXJhdG9yV3JhcHBlciQ7TAAZSkNvbGxlY3Rpb25XcmFwcGVyJG1vZHVsZXQAN0xzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkSkNvbGxlY3Rpb25XcmFwcGVyJDtMABxKQ29uY3VycmVudE1hcFdyYXBwZXIkbW9kdWxldAA6THNjYWxhL2NvbGxlY3Rpb24vY29udmVydC9XcmFwcGVycyRKQ29uY3VycmVudE1hcFdyYXBwZXIkO0wAGUpEaWN0aW9uYXJ5V3JhcHBlciRtb2R1bGV0ADdMc2NhbGEvY29sbGVjdGlvbi9jb252ZXJ0L1dyYXBwZXJzJEpEaWN0aW9uYXJ5V3JhcHBlciQ7TAAaSkVudW1lcmF0aW9uV3JhcHBlciRtb2R1bGV0ADhMc2NhbGEvY29sbGVjdGlvbi9jb252ZXJ0L1dyYXBwZXJzJEpFbnVtZXJhdGlvbldyYXBwZXIkO0wAF0pJdGVyYWJsZVdyYXBwZXIkbW9kdWxldAA1THNjYWxhL2NvbGxlY3Rpb24vY29udmVydC9XcmFwcGVycyRKSXRlcmFibGVXcmFwcGVyJDtMABdKSXRlcmF0b3JXcmFwcGVyJG1vZHVsZXQANUxzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkSkl0ZXJhdG9yV3JhcHBlciQ7TAATSkxpc3RXcmFwcGVyJG1vZHVsZXQAMUxzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkSkxpc3RXcmFwcGVyJDtMABlKUHJvcGVydGllc1dyYXBwZXIkbW9kdWxldAA3THNjYWxhL2NvbGxlY3Rpb24vY29udmVydC9XcmFwcGVycyRKUHJvcGVydGllc1dyYXBwZXIkO0wAEkpTZXRXcmFwcGVyJG1vZHVsZXQAMExzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkSlNldFdyYXBwZXIkO0wAG011dGFibGVCdWZmZXJXcmFwcGVyJG1vZHVsZXQAOUxzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkTXV0YWJsZUJ1ZmZlcldyYXBwZXIkO0wAGE11dGFibGVNYXBXcmFwcGVyJG1vZHVsZXQANkxzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkTXV0YWJsZU1hcFdyYXBwZXIkO0wAGE11dGFibGVTZXFXcmFwcGVyJG1vZHVsZXQANkxzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkTXV0YWJsZVNlcVdyYXBwZXIkO0wAGE11dGFibGVTZXRXcmFwcGVyJG1vZHVsZXQANkxzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkTXV0YWJsZVNldFdyYXBwZXIkO0wAEVNlcVdyYXBwZXIkbW9kdWxldAAvTHNjYWxhL2NvbGxlY3Rpb24vY29udmVydC9XcmFwcGVycyRTZXFXcmFwcGVyJDt4cHBwcHBwcHBwcHBwcHBwcHBwc3IAMnNjYWxhLmNvbGxlY3Rpb24uZ2VuZXJpYy5EZWZhdWx0U2VyaWFsaXphdGlvblByb3h5AAAAAAAAAAMDAAFMAAdmYWN0b3J5dAAaTHNjYWxhL2NvbGxlY3Rpb24vRmFjdG9yeTt4cHNyACpzY2FsYS5jb2xsZWN0aW9uLkl0ZXJhYmxlRmFjdG9yeSRUb0ZhY3RvcnkAAAAAAAAAAwIAAUwAB2ZhY3Rvcnl0ACJMc2NhbGEvY29sbGVjdGlvbi9JdGVyYWJsZUZhY3Rvcnk7eHBzcgAfc2NhbGEuY29sbGVjdGlvbi5pbW11dGFibGUuU2V0JAAAAAAAAAADAwABWgArc2NhbGEkY29sbGVjdGlvbiRpbW11dGFibGUkU2V0JCR1c2VCYXNlbGluZXhweHcE/////3NyABFqYXZhLmxhbmcuSW50ZWdlchLioKT3gYc4AgABSQAFdmFsdWV4cgAQamF2YS5sYW5nLk51bWJlcoaslR0LlOCLAgAAeHAAAAABc3EAfgAfAAAAAnNxAH4AHwAAAANzcgAmc2NhbGEuY29sbGVjdGlvbi5nZW5lcmljLlNlcmlhbGl6ZUVuZCQAAAAAAAAAAwIAAHhweA==") + check(g)(new collection.convert.Wrappers.SetWrapper(immutable.Set()))("rO0ABXNyACxzY2FsYS5jb2xsZWN0aW9uLmNvbnZlcnQuV3JhcHBlcnMkU2V0V3JhcHBlcgAAAAAAAAADAgACTAAGJG91dGVydAAjTHNjYWxhL2NvbGxlY3Rpb24vY29udmVydC9XcmFwcGVycztMADhzY2FsYSRjb2xsZWN0aW9uJGNvbnZlcnQkV3JhcHBlcnMkU2V0V3JhcHBlciQkdW5kZXJseWluZ3QAFkxzY2FsYS9jb2xsZWN0aW9uL1NldDt4cHNyACJzY2FsYS5jb2xsZWN0aW9uLmNvbnZlcnQuV3JhcHBlcnMkAAAAAAAAAAMCABFMABhEaWN0aW9uYXJ5V3JhcHBlciRtb2R1bGV0ADZMc2NhbGEvY29sbGVjdGlvbi9jb252ZXJ0L1dyYXBwZXJzJERpY3Rpb25hcnlXcmFwcGVyJDtMABZJdGVyYWJsZVdyYXBwZXIkbW9kdWxldAA0THNjYWxhL2NvbGxlY3Rpb24vY29udmVydC9XcmFwcGVycyRJdGVyYWJsZVdyYXBwZXIkO0wAFkl0ZXJhdG9yV3JhcHBlciRtb2R1bGV0ADRMc2NhbGEvY29sbGVjdGlvbi9jb252ZXJ0L1dyYXBwZXJzJEl0ZXJhdG9yV3JhcHBlciQ7TAAZSkNvbGxlY3Rpb25XcmFwcGVyJG1vZHVsZXQAN0xzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkSkNvbGxlY3Rpb25XcmFwcGVyJDtMABxKQ29uY3VycmVudE1hcFdyYXBwZXIkbW9kdWxldAA6THNjYWxhL2NvbGxlY3Rpb24vY29udmVydC9XcmFwcGVycyRKQ29uY3VycmVudE1hcFdyYXBwZXIkO0wAGUpEaWN0aW9uYXJ5V3JhcHBlciRtb2R1bGV0ADdMc2NhbGEvY29sbGVjdGlvbi9jb252ZXJ0L1dyYXBwZXJzJEpEaWN0aW9uYXJ5V3JhcHBlciQ7TAAaSkVudW1lcmF0aW9uV3JhcHBlciRtb2R1bGV0ADhMc2NhbGEvY29sbGVjdGlvbi9jb252ZXJ0L1dyYXBwZXJzJEpFbnVtZXJhdGlvbldyYXBwZXIkO0wAF0pJdGVyYWJsZVdyYXBwZXIkbW9kdWxldAA1THNjYWxhL2NvbGxlY3Rpb24vY29udmVydC9XcmFwcGVycyRKSXRlcmFibGVXcmFwcGVyJDtMABdKSXRlcmF0b3JXcmFwcGVyJG1vZHVsZXQANUxzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkSkl0ZXJhdG9yV3JhcHBlciQ7TAATSkxpc3RXcmFwcGVyJG1vZHVsZXQAMUxzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkSkxpc3RXcmFwcGVyJDtMABlKUHJvcGVydGllc1dyYXBwZXIkbW9kdWxldAA3THNjYWxhL2NvbGxlY3Rpb24vY29udmVydC9XcmFwcGVycyRKUHJvcGVydGllc1dyYXBwZXIkO0wAEkpTZXRXcmFwcGVyJG1vZHVsZXQAMExzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkSlNldFdyYXBwZXIkO0wAG011dGFibGVCdWZmZXJXcmFwcGVyJG1vZHVsZXQAOUxzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkTXV0YWJsZUJ1ZmZlcldyYXBwZXIkO0wAGE11dGFibGVNYXBXcmFwcGVyJG1vZHVsZXQANkxzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkTXV0YWJsZU1hcFdyYXBwZXIkO0wAGE11dGFibGVTZXFXcmFwcGVyJG1vZHVsZXQANkxzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkTXV0YWJsZVNlcVdyYXBwZXIkO0wAGE11dGFibGVTZXRXcmFwcGVyJG1vZHVsZXQANkxzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkTXV0YWJsZVNldFdyYXBwZXIkO0wAEVNlcVdyYXBwZXIkbW9kdWxldAAvTHNjYWxhL2NvbGxlY3Rpb24vY29udmVydC9XcmFwcGVycyRTZXFXcmFwcGVyJDt4cHBwcHBwcHBwcHBwcHBwcHBwc3IAMnNjYWxhLmNvbGxlY3Rpb24uZ2VuZXJpYy5EZWZhdWx0U2VyaWFsaXphdGlvblByb3h5AAAAAAAAAAMDAAFMAAdmYWN0b3J5dAAaTHNjYWxhL2NvbGxlY3Rpb24vRmFjdG9yeTt4cHNyACpzY2FsYS5jb2xsZWN0aW9uLkl0ZXJhYmxlRmFjdG9yeSRUb0ZhY3RvcnkAAAAAAAAAAwIAAUwAB2ZhY3Rvcnl0ACJMc2NhbGEvY29sbGVjdGlvbi9JdGVyYWJsZUZhY3Rvcnk7eHBzcgAfc2NhbGEuY29sbGVjdGlvbi5pbW11dGFibGUuU2V0JAAAAAAAAAADAwABWgArc2NhbGEkY29sbGVjdGlvbiRpbW11dGFibGUkU2V0JCR1c2VCYXNlbGluZXhweHcEAAAAAHg=") + check(g)(new collection.convert.Wrappers.SetWrapper(immutable.Set(1, 2, 3)))("rO0ABXNyACxzY2FsYS5jb2xsZWN0aW9uLmNvbnZlcnQuV3JhcHBlcnMkU2V0V3JhcHBlcgAAAAAAAAADAgACTAAGJG91dGVydAAjTHNjYWxhL2NvbGxlY3Rpb24vY29udmVydC9XcmFwcGVycztMADhzY2FsYSRjb2xsZWN0aW9uJGNvbnZlcnQkV3JhcHBlcnMkU2V0V3JhcHBlciQkdW5kZXJseWluZ3QAFkxzY2FsYS9jb2xsZWN0aW9uL1NldDt4cHNyACJzY2FsYS5jb2xsZWN0aW9uLmNvbnZlcnQuV3JhcHBlcnMkAAAAAAAAAAMCABFMABhEaWN0aW9uYXJ5V3JhcHBlciRtb2R1bGV0ADZMc2NhbGEvY29sbGVjdGlvbi9jb252ZXJ0L1dyYXBwZXJzJERpY3Rpb25hcnlXcmFwcGVyJDtMABZJdGVyYWJsZVdyYXBwZXIkbW9kdWxldAA0THNjYWxhL2NvbGxlY3Rpb24vY29udmVydC9XcmFwcGVycyRJdGVyYWJsZVdyYXBwZXIkO0wAFkl0ZXJhdG9yV3JhcHBlciRtb2R1bGV0ADRMc2NhbGEvY29sbGVjdGlvbi9jb252ZXJ0L1dyYXBwZXJzJEl0ZXJhdG9yV3JhcHBlciQ7TAAZSkNvbGxlY3Rpb25XcmFwcGVyJG1vZHVsZXQAN0xzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkSkNvbGxlY3Rpb25XcmFwcGVyJDtMABxKQ29uY3VycmVudE1hcFdyYXBwZXIkbW9kdWxldAA6THNjYWxhL2NvbGxlY3Rpb24vY29udmVydC9XcmFwcGVycyRKQ29uY3VycmVudE1hcFdyYXBwZXIkO0wAGUpEaWN0aW9uYXJ5V3JhcHBlciRtb2R1bGV0ADdMc2NhbGEvY29sbGVjdGlvbi9jb252ZXJ0L1dyYXBwZXJzJEpEaWN0aW9uYXJ5V3JhcHBlciQ7TAAaSkVudW1lcmF0aW9uV3JhcHBlciRtb2R1bGV0ADhMc2NhbGEvY29sbGVjdGlvbi9jb252ZXJ0L1dyYXBwZXJzJEpFbnVtZXJhdGlvbldyYXBwZXIkO0wAF0pJdGVyYWJsZVdyYXBwZXIkbW9kdWxldAA1THNjYWxhL2NvbGxlY3Rpb24vY29udmVydC9XcmFwcGVycyRKSXRlcmFibGVXcmFwcGVyJDtMABdKSXRlcmF0b3JXcmFwcGVyJG1vZHVsZXQANUxzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkSkl0ZXJhdG9yV3JhcHBlciQ7TAATSkxpc3RXcmFwcGVyJG1vZHVsZXQAMUxzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkSkxpc3RXcmFwcGVyJDtMABlKUHJvcGVydGllc1dyYXBwZXIkbW9kdWxldAA3THNjYWxhL2NvbGxlY3Rpb24vY29udmVydC9XcmFwcGVycyRKUHJvcGVydGllc1dyYXBwZXIkO0wAEkpTZXRXcmFwcGVyJG1vZHVsZXQAMExzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkSlNldFdyYXBwZXIkO0wAG011dGFibGVCdWZmZXJXcmFwcGVyJG1vZHVsZXQAOUxzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkTXV0YWJsZUJ1ZmZlcldyYXBwZXIkO0wAGE11dGFibGVNYXBXcmFwcGVyJG1vZHVsZXQANkxzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkTXV0YWJsZU1hcFdyYXBwZXIkO0wAGE11dGFibGVTZXFXcmFwcGVyJG1vZHVsZXQANkxzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkTXV0YWJsZVNlcVdyYXBwZXIkO0wAGE11dGFibGVTZXRXcmFwcGVyJG1vZHVsZXQANkxzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkTXV0YWJsZVNldFdyYXBwZXIkO0wAEVNlcVdyYXBwZXIkbW9kdWxldAAvTHNjYWxhL2NvbGxlY3Rpb24vY29udmVydC9XcmFwcGVycyRTZXFXcmFwcGVyJDt4cHBwcHBwcHBwcHBwcHBwcHBwc3IAMnNjYWxhLmNvbGxlY3Rpb24uZ2VuZXJpYy5EZWZhdWx0U2VyaWFsaXphdGlvblByb3h5AAAAAAAAAAMDAAFMAAdmYWN0b3J5dAAaTHNjYWxhL2NvbGxlY3Rpb24vRmFjdG9yeTt4cHNyACpzY2FsYS5jb2xsZWN0aW9uLkl0ZXJhYmxlRmFjdG9yeSRUb0ZhY3RvcnkAAAAAAAAAAwIAAUwAB2ZhY3Rvcnl0ACJMc2NhbGEvY29sbGVjdGlvbi9JdGVyYWJsZUZhY3Rvcnk7eHBzcgAfc2NhbGEuY29sbGVjdGlvbi5pbW11dGFibGUuU2V0JAAAAAAAAAADAwABWgArc2NhbGEkY29sbGVjdGlvbiRpbW11dGFibGUkU2V0JCR1c2VCYXNlbGluZXhweHcEAAAAA3NyABFqYXZhLmxhbmcuSW50ZWdlchLioKT3gYc4AgABSQAFdmFsdWV4cgAQamF2YS5sYW5nLk51bWJlcoaslR0LlOCLAgAAeHAAAAABc3EAfgAfAAAAAnNxAH4AHwAAAAN4") check(g)(new collection.convert.Wrappers.SetWrapper(mutable.Set()))("rO0ABXNyACxzY2FsYS5jb2xsZWN0aW9uLmNvbnZlcnQuV3JhcHBlcnMkU2V0V3JhcHBlcgAAAAAAAAADAgACTAAGJG91dGVydAAjTHNjYWxhL2NvbGxlY3Rpb24vY29udmVydC9XcmFwcGVycztMADhzY2FsYSRjb2xsZWN0aW9uJGNvbnZlcnQkV3JhcHBlcnMkU2V0V3JhcHBlciQkdW5kZXJseWluZ3QAFkxzY2FsYS9jb2xsZWN0aW9uL1NldDt4cHNyACJzY2FsYS5jb2xsZWN0aW9uLmNvbnZlcnQuV3JhcHBlcnMkAAAAAAAAAAMCABFMABhEaWN0aW9uYXJ5V3JhcHBlciRtb2R1bGV0ADZMc2NhbGEvY29sbGVjdGlvbi9jb252ZXJ0L1dyYXBwZXJzJERpY3Rpb25hcnlXcmFwcGVyJDtMABZJdGVyYWJsZVdyYXBwZXIkbW9kdWxldAA0THNjYWxhL2NvbGxlY3Rpb24vY29udmVydC9XcmFwcGVycyRJdGVyYWJsZVdyYXBwZXIkO0wAFkl0ZXJhdG9yV3JhcHBlciRtb2R1bGV0ADRMc2NhbGEvY29sbGVjdGlvbi9jb252ZXJ0L1dyYXBwZXJzJEl0ZXJhdG9yV3JhcHBlciQ7TAAZSkNvbGxlY3Rpb25XcmFwcGVyJG1vZHVsZXQAN0xzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkSkNvbGxlY3Rpb25XcmFwcGVyJDtMABxKQ29uY3VycmVudE1hcFdyYXBwZXIkbW9kdWxldAA6THNjYWxhL2NvbGxlY3Rpb24vY29udmVydC9XcmFwcGVycyRKQ29uY3VycmVudE1hcFdyYXBwZXIkO0wAGUpEaWN0aW9uYXJ5V3JhcHBlciRtb2R1bGV0ADdMc2NhbGEvY29sbGVjdGlvbi9jb252ZXJ0L1dyYXBwZXJzJEpEaWN0aW9uYXJ5V3JhcHBlciQ7TAAaSkVudW1lcmF0aW9uV3JhcHBlciRtb2R1bGV0ADhMc2NhbGEvY29sbGVjdGlvbi9jb252ZXJ0L1dyYXBwZXJzJEpFbnVtZXJhdGlvbldyYXBwZXIkO0wAF0pJdGVyYWJsZVdyYXBwZXIkbW9kdWxldAA1THNjYWxhL2NvbGxlY3Rpb24vY29udmVydC9XcmFwcGVycyRKSXRlcmFibGVXcmFwcGVyJDtMABdKSXRlcmF0b3JXcmFwcGVyJG1vZHVsZXQANUxzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkSkl0ZXJhdG9yV3JhcHBlciQ7TAATSkxpc3RXcmFwcGVyJG1vZHVsZXQAMUxzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkSkxpc3RXcmFwcGVyJDtMABlKUHJvcGVydGllc1dyYXBwZXIkbW9kdWxldAA3THNjYWxhL2NvbGxlY3Rpb24vY29udmVydC9XcmFwcGVycyRKUHJvcGVydGllc1dyYXBwZXIkO0wAEkpTZXRXcmFwcGVyJG1vZHVsZXQAMExzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkSlNldFdyYXBwZXIkO0wAG011dGFibGVCdWZmZXJXcmFwcGVyJG1vZHVsZXQAOUxzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkTXV0YWJsZUJ1ZmZlcldyYXBwZXIkO0wAGE11dGFibGVNYXBXcmFwcGVyJG1vZHVsZXQANkxzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkTXV0YWJsZU1hcFdyYXBwZXIkO0wAGE11dGFibGVTZXFXcmFwcGVyJG1vZHVsZXQANkxzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkTXV0YWJsZVNlcVdyYXBwZXIkO0wAGE11dGFibGVTZXRXcmFwcGVyJG1vZHVsZXQANkxzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkTXV0YWJsZVNldFdyYXBwZXIkO0wAEVNlcVdyYXBwZXIkbW9kdWxldAAvTHNjYWxhL2NvbGxlY3Rpb24vY29udmVydC9XcmFwcGVycyRTZXFXcmFwcGVyJDt4cHBwcHBwcHBwcHBwcHBwcHBwc3IAMnNjYWxhLmNvbGxlY3Rpb24uZ2VuZXJpYy5EZWZhdWx0U2VyaWFsaXphdGlvblByb3h5AAAAAAAAAAMDAAFMAAdmYWN0b3J5dAAaTHNjYWxhL2NvbGxlY3Rpb24vRmFjdG9yeTt4cHNyACpzY2FsYS5jb2xsZWN0aW9uLkl0ZXJhYmxlRmFjdG9yeSRUb0ZhY3RvcnkAAAAAAAAAAwIAAUwAB2ZhY3Rvcnl0ACJMc2NhbGEvY29sbGVjdGlvbi9JdGVyYWJsZUZhY3Rvcnk7eHBzcgAhc2NhbGEuY29sbGVjdGlvbi5tdXRhYmxlLkhhc2hTZXQkAAAAAAAAAAMCAAB4cHcEAAAAAHg=") check(g)(new collection.convert.Wrappers.SetWrapper(mutable.Set(1, 2, 3)))("rO0ABXNyACxzY2FsYS5jb2xsZWN0aW9uLmNvbnZlcnQuV3JhcHBlcnMkU2V0V3JhcHBlcgAAAAAAAAADAgACTAAGJG91dGVydAAjTHNjYWxhL2NvbGxlY3Rpb24vY29udmVydC9XcmFwcGVycztMADhzY2FsYSRjb2xsZWN0aW9uJGNvbnZlcnQkV3JhcHBlcnMkU2V0V3JhcHBlciQkdW5kZXJseWluZ3QAFkxzY2FsYS9jb2xsZWN0aW9uL1NldDt4cHNyACJzY2FsYS5jb2xsZWN0aW9uLmNvbnZlcnQuV3JhcHBlcnMkAAAAAAAAAAMCABFMABhEaWN0aW9uYXJ5V3JhcHBlciRtb2R1bGV0ADZMc2NhbGEvY29sbGVjdGlvbi9jb252ZXJ0L1dyYXBwZXJzJERpY3Rpb25hcnlXcmFwcGVyJDtMABZJdGVyYWJsZVdyYXBwZXIkbW9kdWxldAA0THNjYWxhL2NvbGxlY3Rpb24vY29udmVydC9XcmFwcGVycyRJdGVyYWJsZVdyYXBwZXIkO0wAFkl0ZXJhdG9yV3JhcHBlciRtb2R1bGV0ADRMc2NhbGEvY29sbGVjdGlvbi9jb252ZXJ0L1dyYXBwZXJzJEl0ZXJhdG9yV3JhcHBlciQ7TAAZSkNvbGxlY3Rpb25XcmFwcGVyJG1vZHVsZXQAN0xzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkSkNvbGxlY3Rpb25XcmFwcGVyJDtMABxKQ29uY3VycmVudE1hcFdyYXBwZXIkbW9kdWxldAA6THNjYWxhL2NvbGxlY3Rpb24vY29udmVydC9XcmFwcGVycyRKQ29uY3VycmVudE1hcFdyYXBwZXIkO0wAGUpEaWN0aW9uYXJ5V3JhcHBlciRtb2R1bGV0ADdMc2NhbGEvY29sbGVjdGlvbi9jb252ZXJ0L1dyYXBwZXJzJEpEaWN0aW9uYXJ5V3JhcHBlciQ7TAAaSkVudW1lcmF0aW9uV3JhcHBlciRtb2R1bGV0ADhMc2NhbGEvY29sbGVjdGlvbi9jb252ZXJ0L1dyYXBwZXJzJEpFbnVtZXJhdGlvbldyYXBwZXIkO0wAF0pJdGVyYWJsZVdyYXBwZXIkbW9kdWxldAA1THNjYWxhL2NvbGxlY3Rpb24vY29udmVydC9XcmFwcGVycyRKSXRlcmFibGVXcmFwcGVyJDtMABdKSXRlcmF0b3JXcmFwcGVyJG1vZHVsZXQANUxzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkSkl0ZXJhdG9yV3JhcHBlciQ7TAATSkxpc3RXcmFwcGVyJG1vZHVsZXQAMUxzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkSkxpc3RXcmFwcGVyJDtMABlKUHJvcGVydGllc1dyYXBwZXIkbW9kdWxldAA3THNjYWxhL2NvbGxlY3Rpb24vY29udmVydC9XcmFwcGVycyRKUHJvcGVydGllc1dyYXBwZXIkO0wAEkpTZXRXcmFwcGVyJG1vZHVsZXQAMExzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkSlNldFdyYXBwZXIkO0wAG011dGFibGVCdWZmZXJXcmFwcGVyJG1vZHVsZXQAOUxzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkTXV0YWJsZUJ1ZmZlcldyYXBwZXIkO0wAGE11dGFibGVNYXBXcmFwcGVyJG1vZHVsZXQANkxzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkTXV0YWJsZU1hcFdyYXBwZXIkO0wAGE11dGFibGVTZXFXcmFwcGVyJG1vZHVsZXQANkxzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkTXV0YWJsZVNlcVdyYXBwZXIkO0wAGE11dGFibGVTZXRXcmFwcGVyJG1vZHVsZXQANkxzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkTXV0YWJsZVNldFdyYXBwZXIkO0wAEVNlcVdyYXBwZXIkbW9kdWxldAAvTHNjYWxhL2NvbGxlY3Rpb24vY29udmVydC9XcmFwcGVycyRTZXFXcmFwcGVyJDt4cHBwcHBwcHBwcHBwcHBwcHBwc3IAMnNjYWxhLmNvbGxlY3Rpb24uZ2VuZXJpYy5EZWZhdWx0U2VyaWFsaXphdGlvblByb3h5AAAAAAAAAAMDAAFMAAdmYWN0b3J5dAAaTHNjYWxhL2NvbGxlY3Rpb24vRmFjdG9yeTt4cHNyACpzY2FsYS5jb2xsZWN0aW9uLkl0ZXJhYmxlRmFjdG9yeSRUb0ZhY3RvcnkAAAAAAAAAAwIAAUwAB2ZhY3Rvcnl0ACJMc2NhbGEvY29sbGVjdGlvbi9JdGVyYWJsZUZhY3Rvcnk7eHBzcgAhc2NhbGEuY29sbGVjdGlvbi5tdXRhYmxlLkhhc2hTZXQkAAAAAAAAAAMCAAB4cHcEAAAAA3NyABFqYXZhLmxhbmcuSW50ZWdlchLioKT3gYc4AgABSQAFdmFsdWV4cgAQamF2YS5sYW5nLk51bWJlcoaslR0LlOCLAgAAeHAAAAABc3EAfgAfAAAAAnNxAH4AHwAAAAN4") check(g)(new collection.convert.Wrappers.MutableSetWrapper(mutable.Set()))("rO0ABXNyADNzY2FsYS5jb2xsZWN0aW9uLmNvbnZlcnQuV3JhcHBlcnMkTXV0YWJsZVNldFdyYXBwZXIAAAAAAAAAAwIAAUwACnVuZGVybHlpbmd0AB5Mc2NhbGEvY29sbGVjdGlvbi9tdXRhYmxlL1NldDt4cgAsc2NhbGEuY29sbGVjdGlvbi5jb252ZXJ0LldyYXBwZXJzJFNldFdyYXBwZXIAAAAAAAAAAwIAAkwABiRvdXRlcnQAI0xzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnM7TAA4c2NhbGEkY29sbGVjdGlvbiRjb252ZXJ0JFdyYXBwZXJzJFNldFdyYXBwZXIkJHVuZGVybHlpbmd0ABZMc2NhbGEvY29sbGVjdGlvbi9TZXQ7eHBzcgAic2NhbGEuY29sbGVjdGlvbi5jb252ZXJ0LldyYXBwZXJzJAAAAAAAAAADAgARTAAYRGljdGlvbmFyeVdyYXBwZXIkbW9kdWxldAA2THNjYWxhL2NvbGxlY3Rpb24vY29udmVydC9XcmFwcGVycyREaWN0aW9uYXJ5V3JhcHBlciQ7TAAWSXRlcmFibGVXcmFwcGVyJG1vZHVsZXQANExzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkSXRlcmFibGVXcmFwcGVyJDtMABZJdGVyYXRvcldyYXBwZXIkbW9kdWxldAA0THNjYWxhL2NvbGxlY3Rpb24vY29udmVydC9XcmFwcGVycyRJdGVyYXRvcldyYXBwZXIkO0wAGUpDb2xsZWN0aW9uV3JhcHBlciRtb2R1bGV0ADdMc2NhbGEvY29sbGVjdGlvbi9jb252ZXJ0L1dyYXBwZXJzJEpDb2xsZWN0aW9uV3JhcHBlciQ7TAAcSkNvbmN1cnJlbnRNYXBXcmFwcGVyJG1vZHVsZXQAOkxzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkSkNvbmN1cnJlbnRNYXBXcmFwcGVyJDtMABlKRGljdGlvbmFyeVdyYXBwZXIkbW9kdWxldAA3THNjYWxhL2NvbGxlY3Rpb24vY29udmVydC9XcmFwcGVycyRKRGljdGlvbmFyeVdyYXBwZXIkO0wAGkpFbnVtZXJhdGlvbldyYXBwZXIkbW9kdWxldAA4THNjYWxhL2NvbGxlY3Rpb24vY29udmVydC9XcmFwcGVycyRKRW51bWVyYXRpb25XcmFwcGVyJDtMABdKSXRlcmFibGVXcmFwcGVyJG1vZHVsZXQANUxzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkSkl0ZXJhYmxlV3JhcHBlciQ7TAAXSkl0ZXJhdG9yV3JhcHBlciRtb2R1bGV0ADVMc2NhbGEvY29sbGVjdGlvbi9jb252ZXJ0L1dyYXBwZXJzJEpJdGVyYXRvcldyYXBwZXIkO0wAE0pMaXN0V3JhcHBlciRtb2R1bGV0ADFMc2NhbGEvY29sbGVjdGlvbi9jb252ZXJ0L1dyYXBwZXJzJEpMaXN0V3JhcHBlciQ7TAAZSlByb3BlcnRpZXNXcmFwcGVyJG1vZHVsZXQAN0xzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkSlByb3BlcnRpZXNXcmFwcGVyJDtMABJKU2V0V3JhcHBlciRtb2R1bGV0ADBMc2NhbGEvY29sbGVjdGlvbi9jb252ZXJ0L1dyYXBwZXJzJEpTZXRXcmFwcGVyJDtMABtNdXRhYmxlQnVmZmVyV3JhcHBlciRtb2R1bGV0ADlMc2NhbGEvY29sbGVjdGlvbi9jb252ZXJ0L1dyYXBwZXJzJE11dGFibGVCdWZmZXJXcmFwcGVyJDtMABhNdXRhYmxlTWFwV3JhcHBlciRtb2R1bGV0ADZMc2NhbGEvY29sbGVjdGlvbi9jb252ZXJ0L1dyYXBwZXJzJE11dGFibGVNYXBXcmFwcGVyJDtMABhNdXRhYmxlU2VxV3JhcHBlciRtb2R1bGV0ADZMc2NhbGEvY29sbGVjdGlvbi9jb252ZXJ0L1dyYXBwZXJzJE11dGFibGVTZXFXcmFwcGVyJDtMABhNdXRhYmxlU2V0V3JhcHBlciRtb2R1bGV0ADZMc2NhbGEvY29sbGVjdGlvbi9jb252ZXJ0L1dyYXBwZXJzJE11dGFibGVTZXRXcmFwcGVyJDtMABFTZXFXcmFwcGVyJG1vZHVsZXQAL0xzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkU2VxV3JhcHBlciQ7eHBwcHBwcHBwcHBwcHBwcHBwcHNyADJzY2FsYS5jb2xsZWN0aW9uLmdlbmVyaWMuRGVmYXVsdFNlcmlhbGl6YXRpb25Qcm94eQAAAAAAAAADAwABTAAHZmFjdG9yeXQAGkxzY2FsYS9jb2xsZWN0aW9uL0ZhY3Rvcnk7eHBzcgAqc2NhbGEuY29sbGVjdGlvbi5JdGVyYWJsZUZhY3RvcnkkVG9GYWN0b3J5AAAAAAAAAAMCAAFMAAdmYWN0b3J5dAAiTHNjYWxhL2NvbGxlY3Rpb24vSXRlcmFibGVGYWN0b3J5O3hwc3IAIXNjYWxhLmNvbGxlY3Rpb24ubXV0YWJsZS5IYXNoU2V0JAAAAAAAAAADAgAAeHB3BAAAAAB4cQB+ABs=") @@ -138,20 +138,20 @@ object SerializationStability { check(g)(new collection.convert.Wrappers.MutableMapWrapper(mutable.Map[Int, Int](1 -> 2, 2 -> 3, 3 -> 4)))("rO0ABXNyADNzY2FsYS5jb2xsZWN0aW9uLmNvbnZlcnQuV3JhcHBlcnMkTXV0YWJsZU1hcFdyYXBwZXIAAAAAAAAAAwIAAUwACnVuZGVybHlpbmd0AB5Mc2NhbGEvY29sbGVjdGlvbi9tdXRhYmxlL01hcDt4cgAsc2NhbGEuY29sbGVjdGlvbi5jb252ZXJ0LldyYXBwZXJzJE1hcFdyYXBwZXIAAAAAAAAAAwIAAkwABiRvdXRlcnQAI0xzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnM7TAA4c2NhbGEkY29sbGVjdGlvbiRjb252ZXJ0JFdyYXBwZXJzJE1hcFdyYXBwZXIkJHVuZGVybHlpbmd0ABZMc2NhbGEvY29sbGVjdGlvbi9NYXA7eHBzcgAic2NhbGEuY29sbGVjdGlvbi5jb252ZXJ0LldyYXBwZXJzJAAAAAAAAAADAgARTAAYRGljdGlvbmFyeVdyYXBwZXIkbW9kdWxldAA2THNjYWxhL2NvbGxlY3Rpb24vY29udmVydC9XcmFwcGVycyREaWN0aW9uYXJ5V3JhcHBlciQ7TAAWSXRlcmFibGVXcmFwcGVyJG1vZHVsZXQANExzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkSXRlcmFibGVXcmFwcGVyJDtMABZJdGVyYXRvcldyYXBwZXIkbW9kdWxldAA0THNjYWxhL2NvbGxlY3Rpb24vY29udmVydC9XcmFwcGVycyRJdGVyYXRvcldyYXBwZXIkO0wAGUpDb2xsZWN0aW9uV3JhcHBlciRtb2R1bGV0ADdMc2NhbGEvY29sbGVjdGlvbi9jb252ZXJ0L1dyYXBwZXJzJEpDb2xsZWN0aW9uV3JhcHBlciQ7TAAcSkNvbmN1cnJlbnRNYXBXcmFwcGVyJG1vZHVsZXQAOkxzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkSkNvbmN1cnJlbnRNYXBXcmFwcGVyJDtMABlKRGljdGlvbmFyeVdyYXBwZXIkbW9kdWxldAA3THNjYWxhL2NvbGxlY3Rpb24vY29udmVydC9XcmFwcGVycyRKRGljdGlvbmFyeVdyYXBwZXIkO0wAGkpFbnVtZXJhdGlvbldyYXBwZXIkbW9kdWxldAA4THNjYWxhL2NvbGxlY3Rpb24vY29udmVydC9XcmFwcGVycyRKRW51bWVyYXRpb25XcmFwcGVyJDtMABdKSXRlcmFibGVXcmFwcGVyJG1vZHVsZXQANUxzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkSkl0ZXJhYmxlV3JhcHBlciQ7TAAXSkl0ZXJhdG9yV3JhcHBlciRtb2R1bGV0ADVMc2NhbGEvY29sbGVjdGlvbi9jb252ZXJ0L1dyYXBwZXJzJEpJdGVyYXRvcldyYXBwZXIkO0wAE0pMaXN0V3JhcHBlciRtb2R1bGV0ADFMc2NhbGEvY29sbGVjdGlvbi9jb252ZXJ0L1dyYXBwZXJzJEpMaXN0V3JhcHBlciQ7TAAZSlByb3BlcnRpZXNXcmFwcGVyJG1vZHVsZXQAN0xzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkSlByb3BlcnRpZXNXcmFwcGVyJDtMABJKU2V0V3JhcHBlciRtb2R1bGV0ADBMc2NhbGEvY29sbGVjdGlvbi9jb252ZXJ0L1dyYXBwZXJzJEpTZXRXcmFwcGVyJDtMABtNdXRhYmxlQnVmZmVyV3JhcHBlciRtb2R1bGV0ADlMc2NhbGEvY29sbGVjdGlvbi9jb252ZXJ0L1dyYXBwZXJzJE11dGFibGVCdWZmZXJXcmFwcGVyJDtMABhNdXRhYmxlTWFwV3JhcHBlciRtb2R1bGV0ADZMc2NhbGEvY29sbGVjdGlvbi9jb252ZXJ0L1dyYXBwZXJzJE11dGFibGVNYXBXcmFwcGVyJDtMABhNdXRhYmxlU2VxV3JhcHBlciRtb2R1bGV0ADZMc2NhbGEvY29sbGVjdGlvbi9jb252ZXJ0L1dyYXBwZXJzJE11dGFibGVTZXFXcmFwcGVyJDtMABhNdXRhYmxlU2V0V3JhcHBlciRtb2R1bGV0ADZMc2NhbGEvY29sbGVjdGlvbi9jb252ZXJ0L1dyYXBwZXJzJE11dGFibGVTZXRXcmFwcGVyJDtMABFTZXFXcmFwcGVyJG1vZHVsZXQAL0xzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkU2VxV3JhcHBlciQ7eHBwcHBwcHBwcHBwcHBwcHBwcHNyADJzY2FsYS5jb2xsZWN0aW9uLmdlbmVyaWMuRGVmYXVsdFNlcmlhbGl6YXRpb25Qcm94eQAAAAAAAAADAwABTAAHZmFjdG9yeXQAGkxzY2FsYS9jb2xsZWN0aW9uL0ZhY3Rvcnk7eHBzcgAlc2NhbGEuY29sbGVjdGlvbi5NYXBGYWN0b3J5JFRvRmFjdG9yeQAAAAAAAAADAgABTAAHZmFjdG9yeXQAHUxzY2FsYS9jb2xsZWN0aW9uL01hcEZhY3Rvcnk7eHBzcgAhc2NhbGEuY29sbGVjdGlvbi5tdXRhYmxlLkhhc2hNYXAkAAAAAAAAAAMCAAB4cHcEAAAAA3NyAAxzY2FsYS5UdXBsZTIulGZ9W5L59QIAAkwAAl8xdAASTGphdmEvbGFuZy9PYmplY3Q7TAACXzJxAH4AInhwc3IAEWphdmEubGFuZy5JbnRlZ2VyEuKgpPeBhzgCAAFJAAV2YWx1ZXhyABBqYXZhLmxhbmcuTnVtYmVyhqyVHQuU4IsCAAB4cAAAAAJzcQB+ACQAAAADc3EAfgAhc3EAfgAkAAAAAXEAfgAmc3EAfgAhcQB+ACdzcQB+ACQAAAAEeHEAfgAb") check(g)(immutable.BitSet(1, 2, 3))( "rO0ABXNyADRzY2FsYS5jb2xsZWN0aW9uLmltbXV0YWJsZS5CaXRTZXQkU2VyaWFsaXphdGlvblByb3h5AAAAAAAAAAMCAAB4cgAqc2NhbGEuY29sbGVjdGlvbi5CaXRTZXQkU2VyaWFsaXphdGlvblByb3h5AAAAAAAAAAMDAAB4cHcMAAAAAQAAAAAAAAAOeA==") - check(g)(immutable.HashMap())( "rO0ABXNyADJzY2FsYS5jb2xsZWN0aW9uLmdlbmVyaWMuRGVmYXVsdFNlcmlhbGl6YXRpb25Qcm94eQAAAAAAAAADAwABTAAHZmFjdG9yeXQAGkxzY2FsYS9jb2xsZWN0aW9uL0ZhY3Rvcnk7eHBzcgAlc2NhbGEuY29sbGVjdGlvbi5NYXBGYWN0b3J5JFRvRmFjdG9yeQAAAAAAAAADAgABTAAHZmFjdG9yeXQAHUxzY2FsYS9jb2xsZWN0aW9uL01hcEZhY3Rvcnk7eHBzcgAjc2NhbGEuY29sbGVjdGlvbi5pbW11dGFibGUuSGFzaE1hcCQAAAAAAAAAAwMAAUwADWRlZmF1bHRNZXJnZXJ0ACtMc2NhbGEvY29sbGVjdGlvbi9pbW11dGFibGUvSGFzaE1hcCRNZXJnZXI7eHB4dwT/////c3IAJnNjYWxhLmNvbGxlY3Rpb24uZ2VuZXJpYy5TZXJpYWxpemVFbmQkAAAAAAAAAAMCAAB4cHg=") - check(g)(immutable.HashMap(1 -> 2))( "rO0ABXNyADJzY2FsYS5jb2xsZWN0aW9uLmdlbmVyaWMuRGVmYXVsdFNlcmlhbGl6YXRpb25Qcm94eQAAAAAAAAADAwABTAAHZmFjdG9yeXQAGkxzY2FsYS9jb2xsZWN0aW9uL0ZhY3Rvcnk7eHBzcgAlc2NhbGEuY29sbGVjdGlvbi5NYXBGYWN0b3J5JFRvRmFjdG9yeQAAAAAAAAADAgABTAAHZmFjdG9yeXQAHUxzY2FsYS9jb2xsZWN0aW9uL01hcEZhY3Rvcnk7eHBzcgAjc2NhbGEuY29sbGVjdGlvbi5pbW11dGFibGUuSGFzaE1hcCQAAAAAAAAAAwMAAUwADWRlZmF1bHRNZXJnZXJ0ACtMc2NhbGEvY29sbGVjdGlvbi9pbW11dGFibGUvSGFzaE1hcCRNZXJnZXI7eHB4dwT/////c3IADHNjYWxhLlR1cGxlMi6UZn1bkvn1AgACTAACXzF0ABJMamF2YS9sYW5nL09iamVjdDtMAAJfMnEAfgAKeHBzcgARamF2YS5sYW5nLkludGVnZXIS4qCk94GHOAIAAUkABXZhbHVleHIAEGphdmEubGFuZy5OdW1iZXKGrJUdC5TgiwIAAHhwAAAAAXNxAH4ADAAAAAJzcgAmc2NhbGEuY29sbGVjdGlvbi5nZW5lcmljLlNlcmlhbGl6ZUVuZCQAAAAAAAAAAwIAAHhweA==") - check(g)(immutable.HashMap(1 -> 2, 3 -> 4))( "rO0ABXNyADJzY2FsYS5jb2xsZWN0aW9uLmdlbmVyaWMuRGVmYXVsdFNlcmlhbGl6YXRpb25Qcm94eQAAAAAAAAADAwABTAAHZmFjdG9yeXQAGkxzY2FsYS9jb2xsZWN0aW9uL0ZhY3Rvcnk7eHBzcgAlc2NhbGEuY29sbGVjdGlvbi5NYXBGYWN0b3J5JFRvRmFjdG9yeQAAAAAAAAADAgABTAAHZmFjdG9yeXQAHUxzY2FsYS9jb2xsZWN0aW9uL01hcEZhY3Rvcnk7eHBzcgAjc2NhbGEuY29sbGVjdGlvbi5pbW11dGFibGUuSGFzaE1hcCQAAAAAAAAAAwMAAUwADWRlZmF1bHRNZXJnZXJ0ACtMc2NhbGEvY29sbGVjdGlvbi9pbW11dGFibGUvSGFzaE1hcCRNZXJnZXI7eHB4dwT/////c3IADHNjYWxhLlR1cGxlMi6UZn1bkvn1AgACTAACXzF0ABJMamF2YS9sYW5nL09iamVjdDtMAAJfMnEAfgAKeHBzcgARamF2YS5sYW5nLkludGVnZXIS4qCk94GHOAIAAUkABXZhbHVleHIAEGphdmEubGFuZy5OdW1iZXKGrJUdC5TgiwIAAHhwAAAAAXNxAH4ADAAAAAJzcQB+AAlzcQB+AAwAAAADc3EAfgAMAAAABHNyACZzY2FsYS5jb2xsZWN0aW9uLmdlbmVyaWMuU2VyaWFsaXplRW5kJAAAAAAAAAADAgAAeHB4") + check(g)(immutable.HashMap())( "rO0ABXNyADJzY2FsYS5jb2xsZWN0aW9uLmdlbmVyaWMuRGVmYXVsdFNlcmlhbGl6YXRpb25Qcm94eQAAAAAAAAADAwABTAAHZmFjdG9yeXQAGkxzY2FsYS9jb2xsZWN0aW9uL0ZhY3Rvcnk7eHBzcgAlc2NhbGEuY29sbGVjdGlvbi5NYXBGYWN0b3J5JFRvRmFjdG9yeQAAAAAAAAADAgABTAAHZmFjdG9yeXQAHUxzY2FsYS9jb2xsZWN0aW9uL01hcEZhY3Rvcnk7eHBzcgAjc2NhbGEuY29sbGVjdGlvbi5pbW11dGFibGUuSGFzaE1hcCQAAAAAAAAAAwMAAUwADWRlZmF1bHRNZXJnZXJ0ACtMc2NhbGEvY29sbGVjdGlvbi9pbW11dGFibGUvSGFzaE1hcCRNZXJnZXI7eHB4dwQAAAAAeA==") + check(g)(immutable.HashMap(1 -> 2))( "rO0ABXNyADJzY2FsYS5jb2xsZWN0aW9uLmdlbmVyaWMuRGVmYXVsdFNlcmlhbGl6YXRpb25Qcm94eQAAAAAAAAADAwABTAAHZmFjdG9yeXQAGkxzY2FsYS9jb2xsZWN0aW9uL0ZhY3Rvcnk7eHBzcgAlc2NhbGEuY29sbGVjdGlvbi5NYXBGYWN0b3J5JFRvRmFjdG9yeQAAAAAAAAADAgABTAAHZmFjdG9yeXQAHUxzY2FsYS9jb2xsZWN0aW9uL01hcEZhY3Rvcnk7eHBzcgAjc2NhbGEuY29sbGVjdGlvbi5pbW11dGFibGUuSGFzaE1hcCQAAAAAAAAAAwMAAUwADWRlZmF1bHRNZXJnZXJ0ACtMc2NhbGEvY29sbGVjdGlvbi9pbW11dGFibGUvSGFzaE1hcCRNZXJnZXI7eHB4dwQAAAABc3IADHNjYWxhLlR1cGxlMi6UZn1bkvn1AgACTAACXzF0ABJMamF2YS9sYW5nL09iamVjdDtMAAJfMnEAfgAKeHBzcgARamF2YS5sYW5nLkludGVnZXIS4qCk94GHOAIAAUkABXZhbHVleHIAEGphdmEubGFuZy5OdW1iZXKGrJUdC5TgiwIAAHhwAAAAAXNxAH4ADAAAAAJ4") + check(g)(immutable.HashMap(1 -> 2, 3 -> 4))( "rO0ABXNyADJzY2FsYS5jb2xsZWN0aW9uLmdlbmVyaWMuRGVmYXVsdFNlcmlhbGl6YXRpb25Qcm94eQAAAAAAAAADAwABTAAHZmFjdG9yeXQAGkxzY2FsYS9jb2xsZWN0aW9uL0ZhY3Rvcnk7eHBzcgAlc2NhbGEuY29sbGVjdGlvbi5NYXBGYWN0b3J5JFRvRmFjdG9yeQAAAAAAAAADAgABTAAHZmFjdG9yeXQAHUxzY2FsYS9jb2xsZWN0aW9uL01hcEZhY3Rvcnk7eHBzcgAjc2NhbGEuY29sbGVjdGlvbi5pbW11dGFibGUuSGFzaE1hcCQAAAAAAAAAAwMAAUwADWRlZmF1bHRNZXJnZXJ0ACtMc2NhbGEvY29sbGVjdGlvbi9pbW11dGFibGUvSGFzaE1hcCRNZXJnZXI7eHB4dwQAAAACc3IADHNjYWxhLlR1cGxlMi6UZn1bkvn1AgACTAACXzF0ABJMamF2YS9sYW5nL09iamVjdDtMAAJfMnEAfgAKeHBzcgARamF2YS5sYW5nLkludGVnZXIS4qCk94GHOAIAAUkABXZhbHVleHIAEGphdmEubGFuZy5OdW1iZXKGrJUdC5TgiwIAAHhwAAAAAXNxAH4ADAAAAAJzcQB+AAlzcQB+AAwAAAADc3EAfgAMAAAABHg=") // TODO provoke HashMapCollision1 - check(g)(immutable.HashSet())( "rO0ABXNyADJzY2FsYS5jb2xsZWN0aW9uLmdlbmVyaWMuRGVmYXVsdFNlcmlhbGl6YXRpb25Qcm94eQAAAAAAAAADAwABTAAHZmFjdG9yeXQAGkxzY2FsYS9jb2xsZWN0aW9uL0ZhY3Rvcnk7eHBzcgAqc2NhbGEuY29sbGVjdGlvbi5JdGVyYWJsZUZhY3RvcnkkVG9GYWN0b3J5AAAAAAAAAAMCAAFMAAdmYWN0b3J5dAAiTHNjYWxhL2NvbGxlY3Rpb24vSXRlcmFibGVGYWN0b3J5O3hwc3IAI3NjYWxhLmNvbGxlY3Rpb24uaW1tdXRhYmxlLkhhc2hTZXQkAAAAAAAAAAMDAAB4cHh3BP////9zcgAmc2NhbGEuY29sbGVjdGlvbi5nZW5lcmljLlNlcmlhbGl6ZUVuZCQAAAAAAAAAAwIAAHhweA==") - check(g)(immutable.HashSet(1))( "rO0ABXNyADJzY2FsYS5jb2xsZWN0aW9uLmdlbmVyaWMuRGVmYXVsdFNlcmlhbGl6YXRpb25Qcm94eQAAAAAAAAADAwABTAAHZmFjdG9yeXQAGkxzY2FsYS9jb2xsZWN0aW9uL0ZhY3Rvcnk7eHBzcgAqc2NhbGEuY29sbGVjdGlvbi5JdGVyYWJsZUZhY3RvcnkkVG9GYWN0b3J5AAAAAAAAAAMCAAFMAAdmYWN0b3J5dAAiTHNjYWxhL2NvbGxlY3Rpb24vSXRlcmFibGVGYWN0b3J5O3hwc3IAI3NjYWxhLmNvbGxlY3Rpb24uaW1tdXRhYmxlLkhhc2hTZXQkAAAAAAAAAAMDAAB4cHh3BP////9zcgARamF2YS5sYW5nLkludGVnZXIS4qCk94GHOAIAAUkABXZhbHVleHIAEGphdmEubGFuZy5OdW1iZXKGrJUdC5TgiwIAAHhwAAAAAXNyACZzY2FsYS5jb2xsZWN0aW9uLmdlbmVyaWMuU2VyaWFsaXplRW5kJAAAAAAAAAADAgAAeHB4") - check(g)(immutable.HashSet(1, 2))( "rO0ABXNyADJzY2FsYS5jb2xsZWN0aW9uLmdlbmVyaWMuRGVmYXVsdFNlcmlhbGl6YXRpb25Qcm94eQAAAAAAAAADAwABTAAHZmFjdG9yeXQAGkxzY2FsYS9jb2xsZWN0aW9uL0ZhY3Rvcnk7eHBzcgAqc2NhbGEuY29sbGVjdGlvbi5JdGVyYWJsZUZhY3RvcnkkVG9GYWN0b3J5AAAAAAAAAAMCAAFMAAdmYWN0b3J5dAAiTHNjYWxhL2NvbGxlY3Rpb24vSXRlcmFibGVGYWN0b3J5O3hwc3IAI3NjYWxhLmNvbGxlY3Rpb24uaW1tdXRhYmxlLkhhc2hTZXQkAAAAAAAAAAMDAAB4cHh3BP////9zcgARamF2YS5sYW5nLkludGVnZXIS4qCk94GHOAIAAUkABXZhbHVleHIAEGphdmEubGFuZy5OdW1iZXKGrJUdC5TgiwIAAHhwAAAAAXNxAH4ACAAAAAJzcgAmc2NhbGEuY29sbGVjdGlvbi5nZW5lcmljLlNlcmlhbGl6ZUVuZCQAAAAAAAAAAwIAAHhweA==") - check(g)(immutable.HashSet(1, 2, 3))( "rO0ABXNyADJzY2FsYS5jb2xsZWN0aW9uLmdlbmVyaWMuRGVmYXVsdFNlcmlhbGl6YXRpb25Qcm94eQAAAAAAAAADAwABTAAHZmFjdG9yeXQAGkxzY2FsYS9jb2xsZWN0aW9uL0ZhY3Rvcnk7eHBzcgAqc2NhbGEuY29sbGVjdGlvbi5JdGVyYWJsZUZhY3RvcnkkVG9GYWN0b3J5AAAAAAAAAAMCAAFMAAdmYWN0b3J5dAAiTHNjYWxhL2NvbGxlY3Rpb24vSXRlcmFibGVGYWN0b3J5O3hwc3IAI3NjYWxhLmNvbGxlY3Rpb24uaW1tdXRhYmxlLkhhc2hTZXQkAAAAAAAAAAMDAAB4cHh3BP////9zcgARamF2YS5sYW5nLkludGVnZXIS4qCk94GHOAIAAUkABXZhbHVleHIAEGphdmEubGFuZy5OdW1iZXKGrJUdC5TgiwIAAHhwAAAAAXNxAH4ACAAAAAJzcQB+AAgAAAADc3IAJnNjYWxhLmNvbGxlY3Rpb24uZ2VuZXJpYy5TZXJpYWxpemVFbmQkAAAAAAAAAAMCAAB4cHg=") + check(g)(immutable.HashSet())( "rO0ABXNyADJzY2FsYS5jb2xsZWN0aW9uLmdlbmVyaWMuRGVmYXVsdFNlcmlhbGl6YXRpb25Qcm94eQAAAAAAAAADAwABTAAHZmFjdG9yeXQAGkxzY2FsYS9jb2xsZWN0aW9uL0ZhY3Rvcnk7eHBzcgAqc2NhbGEuY29sbGVjdGlvbi5JdGVyYWJsZUZhY3RvcnkkVG9GYWN0b3J5AAAAAAAAAAMCAAFMAAdmYWN0b3J5dAAiTHNjYWxhL2NvbGxlY3Rpb24vSXRlcmFibGVGYWN0b3J5O3hwc3IAI3NjYWxhLmNvbGxlY3Rpb24uaW1tdXRhYmxlLkhhc2hTZXQkAAAAAAAAAAMDAAB4cHh3BAAAAAB4") + check(g)(immutable.HashSet(1))( "rO0ABXNyADJzY2FsYS5jb2xsZWN0aW9uLmdlbmVyaWMuRGVmYXVsdFNlcmlhbGl6YXRpb25Qcm94eQAAAAAAAAADAwABTAAHZmFjdG9yeXQAGkxzY2FsYS9jb2xsZWN0aW9uL0ZhY3Rvcnk7eHBzcgAqc2NhbGEuY29sbGVjdGlvbi5JdGVyYWJsZUZhY3RvcnkkVG9GYWN0b3J5AAAAAAAAAAMCAAFMAAdmYWN0b3J5dAAiTHNjYWxhL2NvbGxlY3Rpb24vSXRlcmFibGVGYWN0b3J5O3hwc3IAI3NjYWxhLmNvbGxlY3Rpb24uaW1tdXRhYmxlLkhhc2hTZXQkAAAAAAAAAAMDAAB4cHh3BAAAAAFzcgARamF2YS5sYW5nLkludGVnZXIS4qCk94GHOAIAAUkABXZhbHVleHIAEGphdmEubGFuZy5OdW1iZXKGrJUdC5TgiwIAAHhwAAAAAXg=") + check(g)(immutable.HashSet(1, 2))( "rO0ABXNyADJzY2FsYS5jb2xsZWN0aW9uLmdlbmVyaWMuRGVmYXVsdFNlcmlhbGl6YXRpb25Qcm94eQAAAAAAAAADAwABTAAHZmFjdG9yeXQAGkxzY2FsYS9jb2xsZWN0aW9uL0ZhY3Rvcnk7eHBzcgAqc2NhbGEuY29sbGVjdGlvbi5JdGVyYWJsZUZhY3RvcnkkVG9GYWN0b3J5AAAAAAAAAAMCAAFMAAdmYWN0b3J5dAAiTHNjYWxhL2NvbGxlY3Rpb24vSXRlcmFibGVGYWN0b3J5O3hwc3IAI3NjYWxhLmNvbGxlY3Rpb24uaW1tdXRhYmxlLkhhc2hTZXQkAAAAAAAAAAMDAAB4cHh3BAAAAAJzcgARamF2YS5sYW5nLkludGVnZXIS4qCk94GHOAIAAUkABXZhbHVleHIAEGphdmEubGFuZy5OdW1iZXKGrJUdC5TgiwIAAHhwAAAAAXNxAH4ACAAAAAJ4") + check(g)(immutable.HashSet(1, 2, 3))( "rO0ABXNyADJzY2FsYS5jb2xsZWN0aW9uLmdlbmVyaWMuRGVmYXVsdFNlcmlhbGl6YXRpb25Qcm94eQAAAAAAAAADAwABTAAHZmFjdG9yeXQAGkxzY2FsYS9jb2xsZWN0aW9uL0ZhY3Rvcnk7eHBzcgAqc2NhbGEuY29sbGVjdGlvbi5JdGVyYWJsZUZhY3RvcnkkVG9GYWN0b3J5AAAAAAAAAAMCAAFMAAdmYWN0b3J5dAAiTHNjYWxhL2NvbGxlY3Rpb24vSXRlcmFibGVGYWN0b3J5O3hwc3IAI3NjYWxhLmNvbGxlY3Rpb24uaW1tdXRhYmxlLkhhc2hTZXQkAAAAAAAAAAMDAAB4cHh3BAAAAANzcgARamF2YS5sYW5nLkludGVnZXIS4qCk94GHOAIAAUkABXZhbHVleHIAEGphdmEubGFuZy5OdW1iZXKGrJUdC5TgiwIAAHhwAAAAAXNxAH4ACAAAAAJzcQB+AAgAAAADeA==") // TODO provoke HashSetCollision1 - check(g)(immutable.ListSet())( "rO0ABXNyADJzY2FsYS5jb2xsZWN0aW9uLmdlbmVyaWMuRGVmYXVsdFNlcmlhbGl6YXRpb25Qcm94eQAAAAAAAAADAwABTAAHZmFjdG9yeXQAGkxzY2FsYS9jb2xsZWN0aW9uL0ZhY3Rvcnk7eHBzcgAqc2NhbGEuY29sbGVjdGlvbi5JdGVyYWJsZUZhY3RvcnkkVG9GYWN0b3J5AAAAAAAAAAMCAAFMAAdmYWN0b3J5dAAiTHNjYWxhL2NvbGxlY3Rpb24vSXRlcmFibGVGYWN0b3J5O3hwc3IAI3NjYWxhLmNvbGxlY3Rpb24uaW1tdXRhYmxlLkxpc3RTZXQkAAAAAAAAAAMDAAB4cHh3BP////9zcgAmc2NhbGEuY29sbGVjdGlvbi5nZW5lcmljLlNlcmlhbGl6ZUVuZCQAAAAAAAAAAwIAAHhweA==") + check(g)(immutable.ListSet())( "rO0ABXNyADJzY2FsYS5jb2xsZWN0aW9uLmdlbmVyaWMuRGVmYXVsdFNlcmlhbGl6YXRpb25Qcm94eQAAAAAAAAADAwABTAAHZmFjdG9yeXQAGkxzY2FsYS9jb2xsZWN0aW9uL0ZhY3Rvcnk7eHBzcgAqc2NhbGEuY29sbGVjdGlvbi5JdGVyYWJsZUZhY3RvcnkkVG9GYWN0b3J5AAAAAAAAAAMCAAFMAAdmYWN0b3J5dAAiTHNjYWxhL2NvbGxlY3Rpb24vSXRlcmFibGVGYWN0b3J5O3hwc3IAI3NjYWxhLmNvbGxlY3Rpb24uaW1tdXRhYmxlLkxpc3RTZXQkAAAAAAAAAAMDAAB4cHh3BAAAAAB4") check(g)(immutable.ListSet(1))( "rO0ABXNyADJzY2FsYS5jb2xsZWN0aW9uLmdlbmVyaWMuRGVmYXVsdFNlcmlhbGl6YXRpb25Qcm94eQAAAAAAAAADAwABTAAHZmFjdG9yeXQAGkxzY2FsYS9jb2xsZWN0aW9uL0ZhY3Rvcnk7eHBzcgAqc2NhbGEuY29sbGVjdGlvbi5JdGVyYWJsZUZhY3RvcnkkVG9GYWN0b3J5AAAAAAAAAAMCAAFMAAdmYWN0b3J5dAAiTHNjYWxhL2NvbGxlY3Rpb24vSXRlcmFibGVGYWN0b3J5O3hwc3IAI3NjYWxhLmNvbGxlY3Rpb24uaW1tdXRhYmxlLkxpc3RTZXQkAAAAAAAAAAMDAAB4cHh3BP////9zcgARamF2YS5sYW5nLkludGVnZXIS4qCk94GHOAIAAUkABXZhbHVleHIAEGphdmEubGFuZy5OdW1iZXKGrJUdC5TgiwIAAHhwAAAAAXNyACZzY2FsYS5jb2xsZWN0aW9uLmdlbmVyaWMuU2VyaWFsaXplRW5kJAAAAAAAAAADAgAAeHB4") - check(g)(immutable.ListMap())( "rO0ABXNyADJzY2FsYS5jb2xsZWN0aW9uLmdlbmVyaWMuRGVmYXVsdFNlcmlhbGl6YXRpb25Qcm94eQAAAAAAAAADAwABTAAHZmFjdG9yeXQAGkxzY2FsYS9jb2xsZWN0aW9uL0ZhY3Rvcnk7eHBzcgAlc2NhbGEuY29sbGVjdGlvbi5NYXBGYWN0b3J5JFRvRmFjdG9yeQAAAAAAAAADAgABTAAHZmFjdG9yeXQAHUxzY2FsYS9jb2xsZWN0aW9uL01hcEZhY3Rvcnk7eHBzcgAjc2NhbGEuY29sbGVjdGlvbi5pbW11dGFibGUuTGlzdE1hcCQAAAAAAAAAAwMAAHhweHcE/////3NyACZzY2FsYS5jb2xsZWN0aW9uLmdlbmVyaWMuU2VyaWFsaXplRW5kJAAAAAAAAAADAgAAeHB4") + check(g)(immutable.ListMap())( "rO0ABXNyADJzY2FsYS5jb2xsZWN0aW9uLmdlbmVyaWMuRGVmYXVsdFNlcmlhbGl6YXRpb25Qcm94eQAAAAAAAAADAwABTAAHZmFjdG9yeXQAGkxzY2FsYS9jb2xsZWN0aW9uL0ZhY3Rvcnk7eHBzcgAlc2NhbGEuY29sbGVjdGlvbi5NYXBGYWN0b3J5JFRvRmFjdG9yeQAAAAAAAAADAgABTAAHZmFjdG9yeXQAHUxzY2FsYS9jb2xsZWN0aW9uL01hcEZhY3Rvcnk7eHBzcgAjc2NhbGEuY29sbGVjdGlvbi5pbW11dGFibGUuTGlzdE1hcCQAAAAAAAAAAwMAAHhweHcEAAAAAHg=") check(g)(immutable.ListMap(1 -> 2))( "rO0ABXNyADJzY2FsYS5jb2xsZWN0aW9uLmdlbmVyaWMuRGVmYXVsdFNlcmlhbGl6YXRpb25Qcm94eQAAAAAAAAADAwABTAAHZmFjdG9yeXQAGkxzY2FsYS9jb2xsZWN0aW9uL0ZhY3Rvcnk7eHBzcgAlc2NhbGEuY29sbGVjdGlvbi5NYXBGYWN0b3J5JFRvRmFjdG9yeQAAAAAAAAADAgABTAAHZmFjdG9yeXQAHUxzY2FsYS9jb2xsZWN0aW9uL01hcEZhY3Rvcnk7eHBzcgAjc2NhbGEuY29sbGVjdGlvbi5pbW11dGFibGUuTGlzdE1hcCQAAAAAAAAAAwMAAHhweHcE/////3NyAAxzY2FsYS5UdXBsZTIulGZ9W5L59QIAAkwAAl8xdAASTGphdmEvbGFuZy9PYmplY3Q7TAACXzJxAH4ACXhwc3IAEWphdmEubGFuZy5JbnRlZ2VyEuKgpPeBhzgCAAFJAAV2YWx1ZXhyABBqYXZhLmxhbmcuTnVtYmVyhqyVHQuU4IsCAAB4cAAAAAFzcQB+AAsAAAACc3IAJnNjYWxhLmNvbGxlY3Rpb24uZ2VuZXJpYy5TZXJpYWxpemVFbmQkAAAAAAAAAAMCAAB4cHg=") //check(g)(immutable.Queue())( "rO0ABXNyACBzY2FsYS5jb2xsZWN0aW9uLmltbXV0YWJsZS5RdWV1ZZY146W3qSuhAgACTAACaW50ACFMc2NhbGEvY29sbGVjdGlvbi9pbW11dGFibGUvTGlzdDtMAANvdXRxAH4AAXhwc3IAMnNjYWxhLmNvbGxlY3Rpb24uaW1tdXRhYmxlLkxpc3QkU2VyaWFsaXphdGlvblByb3h5AAAAAAAAAAEDAAB4cHNyACxzY2FsYS5jb2xsZWN0aW9uLmltbXV0YWJsZS5MaXN0U2VyaWFsaXplRW5kJIpcY1v3UwttAgAAeHB4cQB+AAQ=") //check(g)(immutable.Queue(1, 2, 3))( "rO0ABXNyACBzY2FsYS5jb2xsZWN0aW9uLmltbXV0YWJsZS5RdWV1ZZY146W3qSuhAgACTAACaW50ACFMc2NhbGEvY29sbGVjdGlvbi9pbW11dGFibGUvTGlzdDtMAANvdXRxAH4AAXhwc3IAMnNjYWxhLmNvbGxlY3Rpb24uaW1tdXRhYmxlLkxpc3QkU2VyaWFsaXphdGlvblByb3h5AAAAAAAAAAEDAAB4cHNyACxzY2FsYS5jb2xsZWN0aW9uLmltbXV0YWJsZS5MaXN0U2VyaWFsaXplRW5kJIpcY1v3UwttAgAAeHB4c3EAfgADc3IAEWphdmEubGFuZy5JbnRlZ2VyEuKgpPeBhzgCAAFJAAV2YWx1ZXhyABBqYXZhLmxhbmcuTnVtYmVyhqyVHQuU4IsCAAB4cAAAAAFzcQB+AAgAAAACc3EAfgAIAAAAA3EAfgAGeA==") @@ -159,11 +159,11 @@ object SerializationStability { // TODO scala/bug#8576 throws scala.UnitializedFieldError under -Xcheckinit // check(g)(new immutable.Range(0, 1, 1))( "rO0ABXNyACBzY2FsYS5jb2xsZWN0aW9uLmltbXV0YWJsZS5SYW5nZWm7o1SrFTINAgAHSQADZW5kWgAHaXNFbXB0eUkAC2xhc3RFbGVtZW50SQAQbnVtUmFuZ2VFbGVtZW50c0kABXN0YXJ0SQAEc3RlcEkAD3Rlcm1pbmFsRWxlbWVudHhwAAAAAQAAAAAAAAAAAQAAAAAAAAABAAAAAQ==") - check(g)(immutable.Set())( "rO0ABXNyADJzY2FsYS5jb2xsZWN0aW9uLmdlbmVyaWMuRGVmYXVsdFNlcmlhbGl6YXRpb25Qcm94eQAAAAAAAAADAwABTAAHZmFjdG9yeXQAGkxzY2FsYS9jb2xsZWN0aW9uL0ZhY3Rvcnk7eHBzcgAqc2NhbGEuY29sbGVjdGlvbi5JdGVyYWJsZUZhY3RvcnkkVG9GYWN0b3J5AAAAAAAAAAMCAAFMAAdmYWN0b3J5dAAiTHNjYWxhL2NvbGxlY3Rpb24vSXRlcmFibGVGYWN0b3J5O3hwc3IAH3NjYWxhLmNvbGxlY3Rpb24uaW1tdXRhYmxlLlNldCQAAAAAAAAAAwMAAVoAK3NjYWxhJGNvbGxlY3Rpb24kaW1tdXRhYmxlJFNldCQkdXNlQmFzZWxpbmV4cHh3BP////9zcgAmc2NhbGEuY29sbGVjdGlvbi5nZW5lcmljLlNlcmlhbGl6ZUVuZCQAAAAAAAAAAwIAAHhweA==") - check(g)(immutable.Set(1))( "rO0ABXNyADJzY2FsYS5jb2xsZWN0aW9uLmdlbmVyaWMuRGVmYXVsdFNlcmlhbGl6YXRpb25Qcm94eQAAAAAAAAADAwABTAAHZmFjdG9yeXQAGkxzY2FsYS9jb2xsZWN0aW9uL0ZhY3Rvcnk7eHBzcgAqc2NhbGEuY29sbGVjdGlvbi5JdGVyYWJsZUZhY3RvcnkkVG9GYWN0b3J5AAAAAAAAAAMCAAFMAAdmYWN0b3J5dAAiTHNjYWxhL2NvbGxlY3Rpb24vSXRlcmFibGVGYWN0b3J5O3hwc3IAH3NjYWxhLmNvbGxlY3Rpb24uaW1tdXRhYmxlLlNldCQAAAAAAAAAAwMAAVoAK3NjYWxhJGNvbGxlY3Rpb24kaW1tdXRhYmxlJFNldCQkdXNlQmFzZWxpbmV4cHh3BP////9zcgARamF2YS5sYW5nLkludGVnZXIS4qCk94GHOAIAAUkABXZhbHVleHIAEGphdmEubGFuZy5OdW1iZXKGrJUdC5TgiwIAAHhwAAAAAXNyACZzY2FsYS5jb2xsZWN0aW9uLmdlbmVyaWMuU2VyaWFsaXplRW5kJAAAAAAAAAADAgAAeHB4") - check(g)(immutable.Set(1, 2))( "rO0ABXNyADJzY2FsYS5jb2xsZWN0aW9uLmdlbmVyaWMuRGVmYXVsdFNlcmlhbGl6YXRpb25Qcm94eQAAAAAAAAADAwABTAAHZmFjdG9yeXQAGkxzY2FsYS9jb2xsZWN0aW9uL0ZhY3Rvcnk7eHBzcgAqc2NhbGEuY29sbGVjdGlvbi5JdGVyYWJsZUZhY3RvcnkkVG9GYWN0b3J5AAAAAAAAAAMCAAFMAAdmYWN0b3J5dAAiTHNjYWxhL2NvbGxlY3Rpb24vSXRlcmFibGVGYWN0b3J5O3hwc3IAH3NjYWxhLmNvbGxlY3Rpb24uaW1tdXRhYmxlLlNldCQAAAAAAAAAAwMAAVoAK3NjYWxhJGNvbGxlY3Rpb24kaW1tdXRhYmxlJFNldCQkdXNlQmFzZWxpbmV4cHh3BP////9zcgARamF2YS5sYW5nLkludGVnZXIS4qCk94GHOAIAAUkABXZhbHVleHIAEGphdmEubGFuZy5OdW1iZXKGrJUdC5TgiwIAAHhwAAAAAXNxAH4ACAAAAAJzcgAmc2NhbGEuY29sbGVjdGlvbi5nZW5lcmljLlNlcmlhbGl6ZUVuZCQAAAAAAAAAAwIAAHhweA==") - check(g)(immutable.Set(1, 2, 3))( "rO0ABXNyADJzY2FsYS5jb2xsZWN0aW9uLmdlbmVyaWMuRGVmYXVsdFNlcmlhbGl6YXRpb25Qcm94eQAAAAAAAAADAwABTAAHZmFjdG9yeXQAGkxzY2FsYS9jb2xsZWN0aW9uL0ZhY3Rvcnk7eHBzcgAqc2NhbGEuY29sbGVjdGlvbi5JdGVyYWJsZUZhY3RvcnkkVG9GYWN0b3J5AAAAAAAAAAMCAAFMAAdmYWN0b3J5dAAiTHNjYWxhL2NvbGxlY3Rpb24vSXRlcmFibGVGYWN0b3J5O3hwc3IAH3NjYWxhLmNvbGxlY3Rpb24uaW1tdXRhYmxlLlNldCQAAAAAAAAAAwMAAVoAK3NjYWxhJGNvbGxlY3Rpb24kaW1tdXRhYmxlJFNldCQkdXNlQmFzZWxpbmV4cHh3BP////9zcgARamF2YS5sYW5nLkludGVnZXIS4qCk94GHOAIAAUkABXZhbHVleHIAEGphdmEubGFuZy5OdW1iZXKGrJUdC5TgiwIAAHhwAAAAAXNxAH4ACAAAAAJzcQB+AAgAAAADc3IAJnNjYWxhLmNvbGxlY3Rpb24uZ2VuZXJpYy5TZXJpYWxpemVFbmQkAAAAAAAAAAMCAAB4cHg=") - check(g)(immutable.Set(1, 2, 3, 4))( "rO0ABXNyADJzY2FsYS5jb2xsZWN0aW9uLmdlbmVyaWMuRGVmYXVsdFNlcmlhbGl6YXRpb25Qcm94eQAAAAAAAAADAwABTAAHZmFjdG9yeXQAGkxzY2FsYS9jb2xsZWN0aW9uL0ZhY3Rvcnk7eHBzcgAqc2NhbGEuY29sbGVjdGlvbi5JdGVyYWJsZUZhY3RvcnkkVG9GYWN0b3J5AAAAAAAAAAMCAAFMAAdmYWN0b3J5dAAiTHNjYWxhL2NvbGxlY3Rpb24vSXRlcmFibGVGYWN0b3J5O3hwc3IAH3NjYWxhLmNvbGxlY3Rpb24uaW1tdXRhYmxlLlNldCQAAAAAAAAAAwMAAVoAK3NjYWxhJGNvbGxlY3Rpb24kaW1tdXRhYmxlJFNldCQkdXNlQmFzZWxpbmV4cHh3BP////9zcgARamF2YS5sYW5nLkludGVnZXIS4qCk94GHOAIAAUkABXZhbHVleHIAEGphdmEubGFuZy5OdW1iZXKGrJUdC5TgiwIAAHhwAAAAAXNxAH4ACAAAAAJzcQB+AAgAAAADc3EAfgAIAAAABHNyACZzY2FsYS5jb2xsZWN0aW9uLmdlbmVyaWMuU2VyaWFsaXplRW5kJAAAAAAAAAADAgAAeHB4") + check(g)(immutable.Set())( "rO0ABXNyADJzY2FsYS5jb2xsZWN0aW9uLmdlbmVyaWMuRGVmYXVsdFNlcmlhbGl6YXRpb25Qcm94eQAAAAAAAAADAwABTAAHZmFjdG9yeXQAGkxzY2FsYS9jb2xsZWN0aW9uL0ZhY3Rvcnk7eHBzcgAqc2NhbGEuY29sbGVjdGlvbi5JdGVyYWJsZUZhY3RvcnkkVG9GYWN0b3J5AAAAAAAAAAMCAAFMAAdmYWN0b3J5dAAiTHNjYWxhL2NvbGxlY3Rpb24vSXRlcmFibGVGYWN0b3J5O3hwc3IAH3NjYWxhLmNvbGxlY3Rpb24uaW1tdXRhYmxlLlNldCQAAAAAAAAAAwMAAVoAK3NjYWxhJGNvbGxlY3Rpb24kaW1tdXRhYmxlJFNldCQkdXNlQmFzZWxpbmV4cHh3BAAAAAB4") + check(g)(immutable.Set(1))( "rO0ABXNyADJzY2FsYS5jb2xsZWN0aW9uLmdlbmVyaWMuRGVmYXVsdFNlcmlhbGl6YXRpb25Qcm94eQAAAAAAAAADAwABTAAHZmFjdG9yeXQAGkxzY2FsYS9jb2xsZWN0aW9uL0ZhY3Rvcnk7eHBzcgAqc2NhbGEuY29sbGVjdGlvbi5JdGVyYWJsZUZhY3RvcnkkVG9GYWN0b3J5AAAAAAAAAAMCAAFMAAdmYWN0b3J5dAAiTHNjYWxhL2NvbGxlY3Rpb24vSXRlcmFibGVGYWN0b3J5O3hwc3IAH3NjYWxhLmNvbGxlY3Rpb24uaW1tdXRhYmxlLlNldCQAAAAAAAAAAwMAAVoAK3NjYWxhJGNvbGxlY3Rpb24kaW1tdXRhYmxlJFNldCQkdXNlQmFzZWxpbmV4cHh3BAAAAAFzcgARamF2YS5sYW5nLkludGVnZXIS4qCk94GHOAIAAUkABXZhbHVleHIAEGphdmEubGFuZy5OdW1iZXKGrJUdC5TgiwIAAHhwAAAAAXg=") + check(g)(immutable.Set(1, 2))( "rO0ABXNyADJzY2FsYS5jb2xsZWN0aW9uLmdlbmVyaWMuRGVmYXVsdFNlcmlhbGl6YXRpb25Qcm94eQAAAAAAAAADAwABTAAHZmFjdG9yeXQAGkxzY2FsYS9jb2xsZWN0aW9uL0ZhY3Rvcnk7eHBzcgAqc2NhbGEuY29sbGVjdGlvbi5JdGVyYWJsZUZhY3RvcnkkVG9GYWN0b3J5AAAAAAAAAAMCAAFMAAdmYWN0b3J5dAAiTHNjYWxhL2NvbGxlY3Rpb24vSXRlcmFibGVGYWN0b3J5O3hwc3IAH3NjYWxhLmNvbGxlY3Rpb24uaW1tdXRhYmxlLlNldCQAAAAAAAAAAwMAAVoAK3NjYWxhJGNvbGxlY3Rpb24kaW1tdXRhYmxlJFNldCQkdXNlQmFzZWxpbmV4cHh3BAAAAAJzcgARamF2YS5sYW5nLkludGVnZXIS4qCk94GHOAIAAUkABXZhbHVleHIAEGphdmEubGFuZy5OdW1iZXKGrJUdC5TgiwIAAHhwAAAAAXNxAH4ACAAAAAJ4") + check(g)(immutable.Set(1, 2, 3))( "rO0ABXNyADJzY2FsYS5jb2xsZWN0aW9uLmdlbmVyaWMuRGVmYXVsdFNlcmlhbGl6YXRpb25Qcm94eQAAAAAAAAADAwABTAAHZmFjdG9yeXQAGkxzY2FsYS9jb2xsZWN0aW9uL0ZhY3Rvcnk7eHBzcgAqc2NhbGEuY29sbGVjdGlvbi5JdGVyYWJsZUZhY3RvcnkkVG9GYWN0b3J5AAAAAAAAAAMCAAFMAAdmYWN0b3J5dAAiTHNjYWxhL2NvbGxlY3Rpb24vSXRlcmFibGVGYWN0b3J5O3hwc3IAH3NjYWxhLmNvbGxlY3Rpb24uaW1tdXRhYmxlLlNldCQAAAAAAAAAAwMAAVoAK3NjYWxhJGNvbGxlY3Rpb24kaW1tdXRhYmxlJFNldCQkdXNlQmFzZWxpbmV4cHh3BAAAAANzcgARamF2YS5sYW5nLkludGVnZXIS4qCk94GHOAIAAUkABXZhbHVleHIAEGphdmEubGFuZy5OdW1iZXKGrJUdC5TgiwIAAHhwAAAAAXNxAH4ACAAAAAJzcQB+AAgAAAADeA==") + check(g)(immutable.Set(1, 2, 3, 4))( "rO0ABXNyADJzY2FsYS5jb2xsZWN0aW9uLmdlbmVyaWMuRGVmYXVsdFNlcmlhbGl6YXRpb25Qcm94eQAAAAAAAAADAwABTAAHZmFjdG9yeXQAGkxzY2FsYS9jb2xsZWN0aW9uL0ZhY3Rvcnk7eHBzcgAqc2NhbGEuY29sbGVjdGlvbi5JdGVyYWJsZUZhY3RvcnkkVG9GYWN0b3J5AAAAAAAAAAMCAAFMAAdmYWN0b3J5dAAiTHNjYWxhL2NvbGxlY3Rpb24vSXRlcmFibGVGYWN0b3J5O3hwc3IAH3NjYWxhLmNvbGxlY3Rpb24uaW1tdXRhYmxlLlNldCQAAAAAAAAAAwMAAVoAK3NjYWxhJGNvbGxlY3Rpb24kaW1tdXRhYmxlJFNldCQkdXNlQmFzZWxpbmV4cHh3BAAAAARzcgARamF2YS5sYW5nLkludGVnZXIS4qCk94GHOAIAAUkABXZhbHVleHIAEGphdmEubGFuZy5OdW1iZXKGrJUdC5TgiwIAAHhwAAAAAXNxAH4ACAAAAAJzcQB+AAgAAAADc3EAfgAIAAAABHg=") check(g)(immutable.Set(1, 2, 3, 4, 5))( "rO0ABXNyADJzY2FsYS5jb2xsZWN0aW9uLmdlbmVyaWMuRGVmYXVsdFNlcmlhbGl6YXRpb25Qcm94eQAAAAAAAAADAwABTAAHZmFjdG9yeXQAGkxzY2FsYS9jb2xsZWN0aW9uL0ZhY3Rvcnk7eHBzcgAqc2NhbGEuY29sbGVjdGlvbi5JdGVyYWJsZUZhY3RvcnkkVG9GYWN0b3J5AAAAAAAAAAMCAAFMAAdmYWN0b3J5dAAiTHNjYWxhL2NvbGxlY3Rpb24vSXRlcmFibGVGYWN0b3J5O3hwc3IAKHNjYWxhLmNvbGxlY3Rpb24uaW1tdXRhYmxlLkNoYW1wSGFzaFNldCQAAAAAAAAAAwMAAUwACEVtcHR5U2V0dAApTHNjYWxhL2NvbGxlY3Rpb24vaW1tdXRhYmxlL0NoYW1wSGFzaFNldDt4cHh3BAAAAAVzcgARamF2YS5sYW5nLkludGVnZXIS4qCk94GHOAIAAUkABXZhbHVleHIAEGphdmEubGFuZy5OdW1iZXKGrJUdC5TgiwIAAHhwAAAABXNxAH4ACQAAAAFzcQB+AAkAAAACc3EAfgAJAAAAA3NxAH4ACQAAAAR4") check(g)(immutable.Map())( "rO0ABXNyADJzY2FsYS5jb2xsZWN0aW9uLmdlbmVyaWMuRGVmYXVsdFNlcmlhbGl6YXRpb25Qcm94eQAAAAAAAAADAwABTAAHZmFjdG9yeXQAGkxzY2FsYS9jb2xsZWN0aW9uL0ZhY3Rvcnk7eHBzcgAlc2NhbGEuY29sbGVjdGlvbi5NYXBGYWN0b3J5JFRvRmFjdG9yeQAAAAAAAAADAgABTAAHZmFjdG9yeXQAHUxzY2FsYS9jb2xsZWN0aW9uL01hcEZhY3Rvcnk7eHBzcgAfc2NhbGEuY29sbGVjdGlvbi5pbW11dGFibGUuTWFwJAAAAAAAAAADAwABWgArc2NhbGEkY29sbGVjdGlvbiRpbW11dGFibGUkTWFwJCR1c2VCYXNlbGluZXhweHcEAAAAAHg=") @@ -187,23 +187,23 @@ object SerializationStability { // check(g)(mutable.ArrayBuffer(1, 2, 3))( "rO0ABXNyACRzY2FsYS5jb2xsZWN0aW9uLm11dGFibGUuQXJyYXlCdWZmZXIVOLBTg4KOcwIAA0kAC2luaXRpYWxTaXplSQAFc2l6ZTBbAAVhcnJheXQAE1tMamF2YS9sYW5nL09iamVjdDt4cAAAABAAAAADdXIAE1tMamF2YS5sYW5nLk9iamVjdDuQzlifEHMpbAIAAHhwAAAAEHNyABFqYXZhLmxhbmcuSW50ZWdlchLioKT3gYc4AgABSQAFdmFsdWV4cgAQamF2YS5sYW5nLk51bWJlcoaslR0LlOCLAgAAeHAAAAABc3EAfgAFAAAAAnNxAH4ABQAAAANwcHBwcHBwcHBwcHBw") // TODO scala/bug#8576 Uninitialized field under -Xcheckinit // check(g)(mutable.ArraySeq(1, 2, 3))( "rO0ABXNyACFzY2FsYS5jb2xsZWN0aW9uLm11dGFibGUuQXJyYXlTZXEVPD3SKEkOcwIAAkkABmxlbmd0aFsABWFycmF5dAATW0xqYXZhL2xhbmcvT2JqZWN0O3hwAAAAA3VyABNbTGphdmEubGFuZy5PYmplY3Q7kM5YnxBzKWwCAAB4cAAAAANzcgARamF2YS5sYW5nLkludGVnZXIS4qCk94GHOAIAAUkABXZhbHVleHIAEGphdmEubGFuZy5OdW1iZXKGrJUdC5TgiwIAAHhwAAAAAXNxAH4ABQAAAAJzcQB+AAUAAAAD") - check(g)(mutable.AnyRefMap("a" -> "A"))( "rO0ABXNyADJzY2FsYS5jb2xsZWN0aW9uLmdlbmVyaWMuRGVmYXVsdFNlcmlhbGl6YXRpb25Qcm94eQAAAAAAAAADAwABTAAHZmFjdG9yeXQAGkxzY2FsYS9jb2xsZWN0aW9uL0ZhY3Rvcnk7eHBzcgAtc2NhbGEuY29sbGVjdGlvbi5tdXRhYmxlLkFueVJlZk1hcCRUb0ZhY3RvcnkkAAAAAAAAAAMCAAB4cHcE/////3NyAAxzY2FsYS5UdXBsZTIulGZ9W5L59QIAAkwAAl8xdAASTGphdmEvbGFuZy9PYmplY3Q7TAACXzJxAH4ABnhwdAABYXQAAUFzcgAmc2NhbGEuY29sbGVjdGlvbi5nZW5lcmljLlNlcmlhbGl6ZUVuZCQAAAAAAAAAAwIAAHhweA==") + check(g)(mutable.AnyRefMap("a" -> "A"))( "rO0ABXNyADJzY2FsYS5jb2xsZWN0aW9uLmdlbmVyaWMuRGVmYXVsdFNlcmlhbGl6YXRpb25Qcm94eQAAAAAAAAADAwABTAAHZmFjdG9yeXQAGkxzY2FsYS9jb2xsZWN0aW9uL0ZhY3Rvcnk7eHBzcgAtc2NhbGEuY29sbGVjdGlvbi5tdXRhYmxlLkFueVJlZk1hcCRUb0ZhY3RvcnkkAAAAAAAAAAMCAAB4cHcEAAAAAXNyAAxzY2FsYS5UdXBsZTIulGZ9W5L59QIAAkwAAl8xdAASTGphdmEvbGFuZy9PYmplY3Q7TAACXzJxAH4ABnhwdAABYXQAAUF4") //check(g)(mutable.ArrayStack(1, 2, 3))( "rO0ABXNyACNzY2FsYS5jb2xsZWN0aW9uLm11dGFibGUuQXJyYXlTdGFja3bdxXbcnLBeAgACSQAqc2NhbGEkY29sbGVjdGlvbiRtdXRhYmxlJEFycmF5U3RhY2skJGluZGV4WwAqc2NhbGEkY29sbGVjdGlvbiRtdXRhYmxlJEFycmF5U3RhY2skJHRhYmxldAATW0xqYXZhL2xhbmcvT2JqZWN0O3hwAAAAA3VyABNbTGphdmEubGFuZy5PYmplY3Q7kM5YnxBzKWwCAAB4cAAAAANzcgARamF2YS5sYW5nLkludGVnZXIS4qCk94GHOAIAAUkABXZhbHVleHIAEGphdmEubGFuZy5OdW1iZXKGrJUdC5TgiwIAAHhwAAAAA3NxAH4ABQAAAAJzcQB+AAUAAAAB") //check(g)(mutable.DoubleLinkedList(1, 2, 3))( "rO0ABXNyAClzY2FsYS5jb2xsZWN0aW9uLm11dGFibGUuRG91YmxlTGlua2VkTGlzdI73LKsKRr1RAgADTAAEZWxlbXQAEkxqYXZhL2xhbmcvT2JqZWN0O0wABG5leHR0ACtMc2NhbGEvY29sbGVjdGlvbi9tdXRhYmxlL0RvdWJsZUxpbmtlZExpc3Q7TAAEcHJldnEAfgACeHBzcgARamF2YS5sYW5nLkludGVnZXIS4qCk94GHOAIAAUkABXZhbHVleHIAEGphdmEubGFuZy5OdW1iZXKGrJUdC5TgiwIAAHhwAAAAAXNxAH4AAHNxAH4ABAAAAAJzcQB+AABzcQB+AAQAAAADc3EAfgAAcHEAfgALcQB+AAlxAH4AB3EAfgADcA==") check(g)(mutable.HashMap())( "rO0ABXNyADJzY2FsYS5jb2xsZWN0aW9uLmdlbmVyaWMuRGVmYXVsdFNlcmlhbGl6YXRpb25Qcm94eQAAAAAAAAADAwABTAAHZmFjdG9yeXQAGkxzY2FsYS9jb2xsZWN0aW9uL0ZhY3Rvcnk7eHBzcgAlc2NhbGEuY29sbGVjdGlvbi5NYXBGYWN0b3J5JFRvRmFjdG9yeQAAAAAAAAADAgABTAAHZmFjdG9yeXQAHUxzY2FsYS9jb2xsZWN0aW9uL01hcEZhY3Rvcnk7eHBzcgAhc2NhbGEuY29sbGVjdGlvbi5tdXRhYmxlLkhhc2hNYXAkAAAAAAAAAAMCAAB4cHcEAAAAAHg=") check(g)(mutable.HashMap(1 -> 1))( "rO0ABXNyADJzY2FsYS5jb2xsZWN0aW9uLmdlbmVyaWMuRGVmYXVsdFNlcmlhbGl6YXRpb25Qcm94eQAAAAAAAAADAwABTAAHZmFjdG9yeXQAGkxzY2FsYS9jb2xsZWN0aW9uL0ZhY3Rvcnk7eHBzcgAlc2NhbGEuY29sbGVjdGlvbi5NYXBGYWN0b3J5JFRvRmFjdG9yeQAAAAAAAAADAgABTAAHZmFjdG9yeXQAHUxzY2FsYS9jb2xsZWN0aW9uL01hcEZhY3Rvcnk7eHBzcgAhc2NhbGEuY29sbGVjdGlvbi5tdXRhYmxlLkhhc2hNYXAkAAAAAAAAAAMCAAB4cHcEAAAAAXNyAAxzY2FsYS5UdXBsZTIulGZ9W5L59QIAAkwAAl8xdAASTGphdmEvbGFuZy9PYmplY3Q7TAACXzJxAH4ACXhwc3IAEWphdmEubGFuZy5JbnRlZ2VyEuKgpPeBhzgCAAFJAAV2YWx1ZXhyABBqYXZhLmxhbmcuTnVtYmVyhqyVHQuU4IsCAAB4cAAAAAFxAH4ADXg=") check(g)(mutable.HashSet(1, 2, 3))( "rO0ABXNyADJzY2FsYS5jb2xsZWN0aW9uLmdlbmVyaWMuRGVmYXVsdFNlcmlhbGl6YXRpb25Qcm94eQAAAAAAAAADAwABTAAHZmFjdG9yeXQAGkxzY2FsYS9jb2xsZWN0aW9uL0ZhY3Rvcnk7eHBzcgAqc2NhbGEuY29sbGVjdGlvbi5JdGVyYWJsZUZhY3RvcnkkVG9GYWN0b3J5AAAAAAAAAAMCAAFMAAdmYWN0b3J5dAAiTHNjYWxhL2NvbGxlY3Rpb24vSXRlcmFibGVGYWN0b3J5O3hwc3IAIXNjYWxhLmNvbGxlY3Rpb24ubXV0YWJsZS5IYXNoU2V0JAAAAAAAAAADAgAAeHB3BAAAAANzcgARamF2YS5sYW5nLkludGVnZXIS4qCk94GHOAIAAUkABXZhbHVleHIAEGphdmEubGFuZy5OdW1iZXKGrJUdC5TgiwIAAHhwAAAAAXNxAH4ACAAAAAJzcQB+AAgAAAADeA==") - check(g)(mutable.TreeMap[Int, Int]())( "rO0ABXNyADJzY2FsYS5jb2xsZWN0aW9uLmdlbmVyaWMuRGVmYXVsdFNlcmlhbGl6YXRpb25Qcm94eQAAAAAAAAADAwABTAAHZmFjdG9yeXQAGkxzY2FsYS9jb2xsZWN0aW9uL0ZhY3Rvcnk7eHBzcgArc2NhbGEuY29sbGVjdGlvbi5Tb3J0ZWRNYXBGYWN0b3J5JFRvRmFjdG9yeQAAAAAAAAADAgACTAALZXZpZGVuY2UkNDB0ABVMc2NhbGEvbWF0aC9PcmRlcmluZztMAAdmYWN0b3J5dAAjTHNjYWxhL2NvbGxlY3Rpb24vU29ydGVkTWFwRmFjdG9yeTt4cHNyABhzY2FsYS5tYXRoLk9yZGVyaW5nJEludCSzOU33V6xBtgIAAHhwc3IAIXNjYWxhLmNvbGxlY3Rpb24ubXV0YWJsZS5UcmVlTWFwJAAAAAAAAAADAgAAeHB3BP////9zcgAmc2NhbGEuY29sbGVjdGlvbi5nZW5lcmljLlNlcmlhbGl6ZUVuZCQAAAAAAAAAAwIAAHhweA==") - check(g)(mutable.TreeMap(1 -> 1, 3 -> 6))( "rO0ABXNyADJzY2FsYS5jb2xsZWN0aW9uLmdlbmVyaWMuRGVmYXVsdFNlcmlhbGl6YXRpb25Qcm94eQAAAAAAAAADAwABTAAHZmFjdG9yeXQAGkxzY2FsYS9jb2xsZWN0aW9uL0ZhY3Rvcnk7eHBzcgArc2NhbGEuY29sbGVjdGlvbi5Tb3J0ZWRNYXBGYWN0b3J5JFRvRmFjdG9yeQAAAAAAAAADAgACTAALZXZpZGVuY2UkNDB0ABVMc2NhbGEvbWF0aC9PcmRlcmluZztMAAdmYWN0b3J5dAAjTHNjYWxhL2NvbGxlY3Rpb24vU29ydGVkTWFwRmFjdG9yeTt4cHNyABhzY2FsYS5tYXRoLk9yZGVyaW5nJEludCSzOU33V6xBtgIAAHhwc3IAIXNjYWxhLmNvbGxlY3Rpb24ubXV0YWJsZS5UcmVlTWFwJAAAAAAAAAADAgAAeHB3BP////9zcgAMc2NhbGEuVHVwbGUyLpRmfVuS+fUCAAJMAAJfMXQAEkxqYXZhL2xhbmcvT2JqZWN0O0wAAl8ycQB+AAx4cHNyABFqYXZhLmxhbmcuSW50ZWdlchLioKT3gYc4AgABSQAFdmFsdWV4cgAQamF2YS5sYW5nLk51bWJlcoaslR0LlOCLAgAAeHAAAAABcQB+ABBzcQB+AAtzcQB+AA4AAAADc3EAfgAOAAAABnNyACZzY2FsYS5jb2xsZWN0aW9uLmdlbmVyaWMuU2VyaWFsaXplRW5kJAAAAAAAAAADAgAAeHB4") + check(g)(mutable.TreeMap[Int, Int]())( "rO0ABXNyADJzY2FsYS5jb2xsZWN0aW9uLmdlbmVyaWMuRGVmYXVsdFNlcmlhbGl6YXRpb25Qcm94eQAAAAAAAAADAwABTAAHZmFjdG9yeXQAGkxzY2FsYS9jb2xsZWN0aW9uL0ZhY3Rvcnk7eHBzcgArc2NhbGEuY29sbGVjdGlvbi5Tb3J0ZWRNYXBGYWN0b3J5JFRvRmFjdG9yeQAAAAAAAAADAgACTAALZXZpZGVuY2UkNDB0ABVMc2NhbGEvbWF0aC9PcmRlcmluZztMAAdmYWN0b3J5dAAjTHNjYWxhL2NvbGxlY3Rpb24vU29ydGVkTWFwRmFjdG9yeTt4cHNyABhzY2FsYS5tYXRoLk9yZGVyaW5nJEludCSzOU33V6xBtgIAAHhwc3IAIXNjYWxhLmNvbGxlY3Rpb24ubXV0YWJsZS5UcmVlTWFwJAAAAAAAAAADAgAAeHB3BAAAAAB4") + check(g)(mutable.TreeMap(1 -> 1, 3 -> 6))( "rO0ABXNyADJzY2FsYS5jb2xsZWN0aW9uLmdlbmVyaWMuRGVmYXVsdFNlcmlhbGl6YXRpb25Qcm94eQAAAAAAAAADAwABTAAHZmFjdG9yeXQAGkxzY2FsYS9jb2xsZWN0aW9uL0ZhY3Rvcnk7eHBzcgArc2NhbGEuY29sbGVjdGlvbi5Tb3J0ZWRNYXBGYWN0b3J5JFRvRmFjdG9yeQAAAAAAAAADAgACTAALZXZpZGVuY2UkNDB0ABVMc2NhbGEvbWF0aC9PcmRlcmluZztMAAdmYWN0b3J5dAAjTHNjYWxhL2NvbGxlY3Rpb24vU29ydGVkTWFwRmFjdG9yeTt4cHNyABhzY2FsYS5tYXRoLk9yZGVyaW5nJEludCSzOU33V6xBtgIAAHhwc3IAIXNjYWxhLmNvbGxlY3Rpb24ubXV0YWJsZS5UcmVlTWFwJAAAAAAAAAADAgAAeHB3BAAAAAJzcgAMc2NhbGEuVHVwbGUyLpRmfVuS+fUCAAJMAAJfMXQAEkxqYXZhL2xhbmcvT2JqZWN0O0wAAl8ycQB+AAx4cHNyABFqYXZhLmxhbmcuSW50ZWdlchLioKT3gYc4AgABSQAFdmFsdWV4cgAQamF2YS5sYW5nLk51bWJlcoaslR0LlOCLAgAAeHAAAAABcQB+ABBzcQB+AAtzcQB+AA4AAAADc3EAfgAOAAAABng=") check(g)(mutable.TreeMap(1 -> 1, 3 -> 6).range(1, 2))( "rO0ABXNyADJzY2FsYS5jb2xsZWN0aW9uLmdlbmVyaWMuRGVmYXVsdFNlcmlhbGl6YXRpb25Qcm94eQAAAAAAAAADAwABTAAHZmFjdG9yeXQAGkxzY2FsYS9jb2xsZWN0aW9uL0ZhY3Rvcnk7eHBzcgArc2NhbGEuY29sbGVjdGlvbi5Tb3J0ZWRNYXBGYWN0b3J5JFRvRmFjdG9yeQAAAAAAAAADAgACTAALZXZpZGVuY2UkNDB0ABVMc2NhbGEvbWF0aC9PcmRlcmluZztMAAdmYWN0b3J5dAAjTHNjYWxhL2NvbGxlY3Rpb24vU29ydGVkTWFwRmFjdG9yeTt4cHNyABhzY2FsYS5tYXRoLk9yZGVyaW5nJEludCSzOU33V6xBtgIAAHhwc3IAIXNjYWxhLmNvbGxlY3Rpb24ubXV0YWJsZS5UcmVlTWFwJAAAAAAAAAADAgAAeHB3BP////9zcgAMc2NhbGEuVHVwbGUyLpRmfVuS+fUCAAJMAAJfMXQAEkxqYXZhL2xhbmcvT2JqZWN0O0wAAl8ycQB+AAx4cHNyABFqYXZhLmxhbmcuSW50ZWdlchLioKT3gYc4AgABSQAFdmFsdWV4cgAQamF2YS5sYW5nLk51bWJlcoaslR0LlOCLAgAAeHAAAAABcQB+ABBzcgAmc2NhbGEuY29sbGVjdGlvbi5nZW5lcmljLlNlcmlhbGl6ZUVuZCQAAAAAAAAAAwIAAHhweA==") - check(g)(mutable.TreeSet[Int]())( "rO0ABXNyADJzY2FsYS5jb2xsZWN0aW9uLmdlbmVyaWMuRGVmYXVsdFNlcmlhbGl6YXRpb25Qcm94eQAAAAAAAAADAwABTAAHZmFjdG9yeXQAGkxzY2FsYS9jb2xsZWN0aW9uL0ZhY3Rvcnk7eHBzcgAyc2NhbGEuY29sbGVjdGlvbi5FdmlkZW5jZUl0ZXJhYmxlRmFjdG9yeSRUb0ZhY3RvcnkAAAAAAAAAAwIAAkwAC2V2aWRlbmNlJDEzdAASTGphdmEvbGFuZy9PYmplY3Q7TAAHZmFjdG9yeXQAKkxzY2FsYS9jb2xsZWN0aW9uL0V2aWRlbmNlSXRlcmFibGVGYWN0b3J5O3hwc3IAGHNjYWxhLm1hdGguT3JkZXJpbmckSW50JLM5TfdXrEG2AgAAeHBzcgAhc2NhbGEuY29sbGVjdGlvbi5tdXRhYmxlLlRyZWVTZXQkAAAAAAAAAAMCAAB4cHcE/////3NyACZzY2FsYS5jb2xsZWN0aW9uLmdlbmVyaWMuU2VyaWFsaXplRW5kJAAAAAAAAAADAgAAeHB4") - check(g)(mutable.TreeSet(1, 3))( "rO0ABXNyADJzY2FsYS5jb2xsZWN0aW9uLmdlbmVyaWMuRGVmYXVsdFNlcmlhbGl6YXRpb25Qcm94eQAAAAAAAAADAwABTAAHZmFjdG9yeXQAGkxzY2FsYS9jb2xsZWN0aW9uL0ZhY3Rvcnk7eHBzcgAyc2NhbGEuY29sbGVjdGlvbi5FdmlkZW5jZUl0ZXJhYmxlRmFjdG9yeSRUb0ZhY3RvcnkAAAAAAAAAAwIAAkwAC2V2aWRlbmNlJDEzdAASTGphdmEvbGFuZy9PYmplY3Q7TAAHZmFjdG9yeXQAKkxzY2FsYS9jb2xsZWN0aW9uL0V2aWRlbmNlSXRlcmFibGVGYWN0b3J5O3hwc3IAGHNjYWxhLm1hdGguT3JkZXJpbmckSW50JLM5TfdXrEG2AgAAeHBzcgAhc2NhbGEuY29sbGVjdGlvbi5tdXRhYmxlLlRyZWVTZXQkAAAAAAAAAAMCAAB4cHcE/////3NyABFqYXZhLmxhbmcuSW50ZWdlchLioKT3gYc4AgABSQAFdmFsdWV4cgAQamF2YS5sYW5nLk51bWJlcoaslR0LlOCLAgAAeHAAAAABc3EAfgALAAAAA3NyACZzY2FsYS5jb2xsZWN0aW9uLmdlbmVyaWMuU2VyaWFsaXplRW5kJAAAAAAAAAADAgAAeHB4") + check(g)(mutable.TreeSet[Int]())( "rO0ABXNyADJzY2FsYS5jb2xsZWN0aW9uLmdlbmVyaWMuRGVmYXVsdFNlcmlhbGl6YXRpb25Qcm94eQAAAAAAAAADAwABTAAHZmFjdG9yeXQAGkxzY2FsYS9jb2xsZWN0aW9uL0ZhY3Rvcnk7eHBzcgAyc2NhbGEuY29sbGVjdGlvbi5FdmlkZW5jZUl0ZXJhYmxlRmFjdG9yeSRUb0ZhY3RvcnkAAAAAAAAAAwIAAkwAC2V2aWRlbmNlJDEzdAASTGphdmEvbGFuZy9PYmplY3Q7TAAHZmFjdG9yeXQAKkxzY2FsYS9jb2xsZWN0aW9uL0V2aWRlbmNlSXRlcmFibGVGYWN0b3J5O3hwc3IAGHNjYWxhLm1hdGguT3JkZXJpbmckSW50JLM5TfdXrEG2AgAAeHBzcgAhc2NhbGEuY29sbGVjdGlvbi5tdXRhYmxlLlRyZWVTZXQkAAAAAAAAAAMCAAB4cHcEAAAAAHg=") + check(g)(mutable.TreeSet(1, 3))( "rO0ABXNyADJzY2FsYS5jb2xsZWN0aW9uLmdlbmVyaWMuRGVmYXVsdFNlcmlhbGl6YXRpb25Qcm94eQAAAAAAAAADAwABTAAHZmFjdG9yeXQAGkxzY2FsYS9jb2xsZWN0aW9uL0ZhY3Rvcnk7eHBzcgAyc2NhbGEuY29sbGVjdGlvbi5FdmlkZW5jZUl0ZXJhYmxlRmFjdG9yeSRUb0ZhY3RvcnkAAAAAAAAAAwIAAkwAC2V2aWRlbmNlJDEzdAASTGphdmEvbGFuZy9PYmplY3Q7TAAHZmFjdG9yeXQAKkxzY2FsYS9jb2xsZWN0aW9uL0V2aWRlbmNlSXRlcmFibGVGYWN0b3J5O3hwc3IAGHNjYWxhLm1hdGguT3JkZXJpbmckSW50JLM5TfdXrEG2AgAAeHBzcgAhc2NhbGEuY29sbGVjdGlvbi5tdXRhYmxlLlRyZWVTZXQkAAAAAAAAAAMCAAB4cHcEAAAAAnNyABFqYXZhLmxhbmcuSW50ZWdlchLioKT3gYc4AgABSQAFdmFsdWV4cgAQamF2YS5sYW5nLk51bWJlcoaslR0LlOCLAgAAeHAAAAABc3EAfgALAAAAA3g=") check(g)(mutable.TreeSet(1, 3).range(1, 2))( "rO0ABXNyADJzY2FsYS5jb2xsZWN0aW9uLmdlbmVyaWMuRGVmYXVsdFNlcmlhbGl6YXRpb25Qcm94eQAAAAAAAAADAwABTAAHZmFjdG9yeXQAGkxzY2FsYS9jb2xsZWN0aW9uL0ZhY3Rvcnk7eHBzcgAyc2NhbGEuY29sbGVjdGlvbi5FdmlkZW5jZUl0ZXJhYmxlRmFjdG9yeSRUb0ZhY3RvcnkAAAAAAAAAAwIAAkwAC2V2aWRlbmNlJDEzdAASTGphdmEvbGFuZy9PYmplY3Q7TAAHZmFjdG9yeXQAKkxzY2FsYS9jb2xsZWN0aW9uL0V2aWRlbmNlSXRlcmFibGVGYWN0b3J5O3hwc3IAGHNjYWxhLm1hdGguT3JkZXJpbmckSW50JLM5TfdXrEG2AgAAeHBzcgAhc2NhbGEuY29sbGVjdGlvbi5tdXRhYmxlLlRyZWVTZXQkAAAAAAAAAAMCAAB4cHcE/////3NyABFqYXZhLmxhbmcuSW50ZWdlchLioKT3gYc4AgABSQAFdmFsdWV4cgAQamF2YS5sYW5nLk51bWJlcoaslR0LlOCLAgAAeHAAAAABc3IAJnNjYWxhLmNvbGxlY3Rpb24uZ2VuZXJpYy5TZXJpYWxpemVFbmQkAAAAAAAAAAMCAAB4cHg=") // TODO scala/bug#8576 Uninitialized field under -Xcheckinit // check(g)(new mutable.History())( "rO0ABXNyACBzY2FsYS5jb2xsZWN0aW9uLm11dGFibGUuSGlzdG9yeUhuXxDIFJrsAgACSQAKbWF4SGlzdG9yeUwAA2xvZ3QAIExzY2FsYS9jb2xsZWN0aW9uL211dGFibGUvUXVldWU7eHAAAAPoc3IAHnNjYWxhLmNvbGxlY3Rpb24ubXV0YWJsZS5RdWV1ZbjMURVfOuHHAgAAeHIAJHNjYWxhLmNvbGxlY3Rpb24ubXV0YWJsZS5NdXRhYmxlTGlzdFJpnjJ+gFbAAgADSQADbGVuTAAGZmlyc3QwdAAlTHNjYWxhL2NvbGxlY3Rpb24vbXV0YWJsZS9MaW5rZWRMaXN0O0wABWxhc3QwcQB+AAV4cAAAAABzcgAjc2NhbGEuY29sbGVjdGlvbi5tdXRhYmxlLkxpbmtlZExpc3Sak+nGCZHaUQIAAkwABGVsZW10ABJMamF2YS9sYW5nL09iamVjdDtMAARuZXh0dAAeTHNjYWxhL2NvbGxlY3Rpb24vbXV0YWJsZS9TZXE7eHBwcQB+AApxAH4ACg==") - check(g)(mutable.LinkedHashMap(1 -> 2))( "rO0ABXNyADJzY2FsYS5jb2xsZWN0aW9uLmdlbmVyaWMuRGVmYXVsdFNlcmlhbGl6YXRpb25Qcm94eQAAAAAAAAADAwABTAAHZmFjdG9yeXQAGkxzY2FsYS9jb2xsZWN0aW9uL0ZhY3Rvcnk7eHBzcgAlc2NhbGEuY29sbGVjdGlvbi5NYXBGYWN0b3J5JFRvRmFjdG9yeQAAAAAAAAADAgABTAAHZmFjdG9yeXQAHUxzY2FsYS9jb2xsZWN0aW9uL01hcEZhY3Rvcnk7eHBzcgAnc2NhbGEuY29sbGVjdGlvbi5tdXRhYmxlLkxpbmtlZEhhc2hNYXAkAAAAAAAAAAMCAAB4cHcE/////3NyAAxzY2FsYS5UdXBsZTIulGZ9W5L59QIAAkwAAl8xdAASTGphdmEvbGFuZy9PYmplY3Q7TAACXzJxAH4ACXhwc3IAEWphdmEubGFuZy5JbnRlZ2VyEuKgpPeBhzgCAAFJAAV2YWx1ZXhyABBqYXZhLmxhbmcuTnVtYmVyhqyVHQuU4IsCAAB4cAAAAAFzcQB+AAsAAAACc3IAJnNjYWxhLmNvbGxlY3Rpb24uZ2VuZXJpYy5TZXJpYWxpemVFbmQkAAAAAAAAAAMCAAB4cHg=") - check(g)(mutable.LinkedHashSet(1, 2, 3))( "rO0ABXNyADJzY2FsYS5jb2xsZWN0aW9uLmdlbmVyaWMuRGVmYXVsdFNlcmlhbGl6YXRpb25Qcm94eQAAAAAAAAADAwABTAAHZmFjdG9yeXQAGkxzY2FsYS9jb2xsZWN0aW9uL0ZhY3Rvcnk7eHBzcgAqc2NhbGEuY29sbGVjdGlvbi5JdGVyYWJsZUZhY3RvcnkkVG9GYWN0b3J5AAAAAAAAAAMCAAFMAAdmYWN0b3J5dAAiTHNjYWxhL2NvbGxlY3Rpb24vSXRlcmFibGVGYWN0b3J5O3hwc3IAJ3NjYWxhLmNvbGxlY3Rpb24ubXV0YWJsZS5MaW5rZWRIYXNoU2V0JAAAAAAAAAADAgAAeHB3BP////9zcgARamF2YS5sYW5nLkludGVnZXIS4qCk94GHOAIAAUkABXZhbHVleHIAEGphdmEubGFuZy5OdW1iZXKGrJUdC5TgiwIAAHhwAAAAAXNxAH4ACAAAAAJzcQB+AAgAAAADc3IAJnNjYWxhLmNvbGxlY3Rpb24uZ2VuZXJpYy5TZXJpYWxpemVFbmQkAAAAAAAAAAMCAAB4cHg=") + check(g)(mutable.LinkedHashMap(1 -> 2))( "rO0ABXNyADJzY2FsYS5jb2xsZWN0aW9uLmdlbmVyaWMuRGVmYXVsdFNlcmlhbGl6YXRpb25Qcm94eQAAAAAAAAADAwABTAAHZmFjdG9yeXQAGkxzY2FsYS9jb2xsZWN0aW9uL0ZhY3Rvcnk7eHBzcgAlc2NhbGEuY29sbGVjdGlvbi5NYXBGYWN0b3J5JFRvRmFjdG9yeQAAAAAAAAADAgABTAAHZmFjdG9yeXQAHUxzY2FsYS9jb2xsZWN0aW9uL01hcEZhY3Rvcnk7eHBzcgAnc2NhbGEuY29sbGVjdGlvbi5tdXRhYmxlLkxpbmtlZEhhc2hNYXAkAAAAAAAAAAMCAAB4cHcEAAAAAXNyAAxzY2FsYS5UdXBsZTIulGZ9W5L59QIAAkwAAl8xdAASTGphdmEvbGFuZy9PYmplY3Q7TAACXzJxAH4ACXhwc3IAEWphdmEubGFuZy5JbnRlZ2VyEuKgpPeBhzgCAAFJAAV2YWx1ZXhyABBqYXZhLmxhbmcuTnVtYmVyhqyVHQuU4IsCAAB4cAAAAAFzcQB+AAsAAAACeA==") + check(g)(mutable.LinkedHashSet(1, 2, 3))( "rO0ABXNyADJzY2FsYS5jb2xsZWN0aW9uLmdlbmVyaWMuRGVmYXVsdFNlcmlhbGl6YXRpb25Qcm94eQAAAAAAAAADAwABTAAHZmFjdG9yeXQAGkxzY2FsYS9jb2xsZWN0aW9uL0ZhY3Rvcnk7eHBzcgAqc2NhbGEuY29sbGVjdGlvbi5JdGVyYWJsZUZhY3RvcnkkVG9GYWN0b3J5AAAAAAAAAAMCAAFMAAdmYWN0b3J5dAAiTHNjYWxhL2NvbGxlY3Rpb24vSXRlcmFibGVGYWN0b3J5O3hwc3IAJ3NjYWxhLmNvbGxlY3Rpb24ubXV0YWJsZS5MaW5rZWRIYXNoU2V0JAAAAAAAAAADAgAAeHB3BAAAAANzcgARamF2YS5sYW5nLkludGVnZXIS4qCk94GHOAIAAUkABXZhbHVleHIAEGphdmEubGFuZy5OdW1iZXKGrJUdC5TgiwIAAHhwAAAAAXNxAH4ACAAAAAJzcQB+AAgAAAADeA==") //check(g)(mutable.LinkedList(1, 2, 3))( "rO0ABXNyACNzY2FsYS5jb2xsZWN0aW9uLm11dGFibGUuTGlua2VkTGlzdJqT6cYJkdpRAgACTAAEZWxlbXQAEkxqYXZhL2xhbmcvT2JqZWN0O0wABG5leHR0ACVMc2NhbGEvY29sbGVjdGlvbi9tdXRhYmxlL0xpbmtlZExpc3Q7eHBzcgARamF2YS5sYW5nLkludGVnZXIS4qCk94GHOAIAAUkABXZhbHVleHIAEGphdmEubGFuZy5OdW1iZXKGrJUdC5TgiwIAAHhwAAAAAXNxAH4AAHNxAH4ABAAAAAJzcQB+AABzcQB+AAQAAAADc3EAfgAAcHEAfgAL") // TODO scala/bug#8576 unstable under -Xcheckinit From 91f835402bb9d739427f9ed68976d82122b1cd8d Mon Sep 17 00:00:00 2001 From: Jason Zaugg Date: Mon, 18 Jun 2018 13:25:07 +1000 Subject: [PATCH 029/143] Reuse empty iterators in LazyList and Stream Empty --- src/library/scala/collection/immutable/LazyList.scala | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/library/scala/collection/immutable/LazyList.scala b/src/library/scala/collection/immutable/LazyList.scala index 84019f873c26..33ed1fb1a74f 100644 --- a/src/library/scala/collection/immutable/LazyList.scala +++ b/src/library/scala/collection/immutable/LazyList.scala @@ -610,6 +610,7 @@ object LazyList extends LazyListFactory[LazyList] { override def tail: LazyList[Nothing] = throw new UnsupportedOperationException("tail of empty lazy list") def force: this.type = this override def knownSize: Int = 0 + override def iterator: Iterator[Nothing] = Iterator.empty protected def tailDefined: Boolean = false protected def headDefined: Boolean = false } @@ -789,6 +790,7 @@ object Stream extends LazyListFactory[Stream] { */ def force: this.type = this override def knownSize: Int = 0 + override def iterator: Iterator[Nothing] = Iterator.empty protected def headDefined: Boolean = false protected def tailDefined: Boolean = false } From 2ad6d7554aec9c88005b99d7197a4f023ae55a54 Mon Sep 17 00:00:00 2001 From: Jason Zaugg Date: Mon, 18 Jun 2018 14:05:36 +1000 Subject: [PATCH 030/143] Reorder fast paths for same- and empty- source collection --- src/library/scala/collection/immutable/ChampHashSet.scala | 2 +- src/library/scala/collection/immutable/LazyList.scala | 2 +- src/library/scala/collection/immutable/List.scala | 2 +- src/library/scala/collection/immutable/ListSet.scala | 2 +- src/library/scala/collection/immutable/Queue.scala | 2 +- src/library/scala/collection/immutable/Set.scala | 8 ++++---- src/library/scala/collection/immutable/Vector.scala | 4 ++-- 7 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/library/scala/collection/immutable/ChampHashSet.scala b/src/library/scala/collection/immutable/ChampHashSet.scala index d35ac301d6eb..f00484812eb7 100644 --- a/src/library/scala/collection/immutable/ChampHashSet.scala +++ b/src/library/scala/collection/immutable/ChampHashSet.scala @@ -590,8 +590,8 @@ object ChampHashSet extends IterableFactory[ChampHashSet] { def from[A](source: collection.IterableOnce[A]): ChampHashSet[A] = source match { - case _ if source.knownSize == 0 => empty[A] case hs: ChampHashSet[A] => hs + case _ if source.knownSize == 0 => empty[A] case _ => (newBuilder[A] ++= source).result() } diff --git a/src/library/scala/collection/immutable/LazyList.scala b/src/library/scala/collection/immutable/LazyList.scala index 33ed1fb1a74f..575df41bc2a0 100644 --- a/src/library/scala/collection/immutable/LazyList.scala +++ b/src/library/scala/collection/immutable/LazyList.scala @@ -684,8 +684,8 @@ object LazyList extends LazyListFactory[LazyList] { } def from[A](coll: collection.IterableOnce[A]): LazyList[A] = coll match { - case _ if coll.knownSize == 0 => empty[A] case coll: LazyList[A] => coll + case _ if coll.knownSize == 0 => empty[A] case _ => fromIterator(coll.iterator) } diff --git a/src/library/scala/collection/immutable/List.scala b/src/library/scala/collection/immutable/List.scala index ad7324d67e33..179604c5c008 100644 --- a/src/library/scala/collection/immutable/List.scala +++ b/src/library/scala/collection/immutable/List.scala @@ -582,8 +582,8 @@ case object Nil extends List[Nothing] { object List extends StrictOptimizedSeqFactory[List] { def from[B](coll: collection.IterableOnce[B]): List[B] = coll match { - case _ if coll.knownSize == 0 => empty[B] case coll: List[B] => coll + case _ if coll.knownSize == 0 => empty[B] case _ => ListBuffer.from(coll).toList } diff --git a/src/library/scala/collection/immutable/ListSet.scala b/src/library/scala/collection/immutable/ListSet.scala index 1bfcb9ec0881..8ce377c6acbf 100644 --- a/src/library/scala/collection/immutable/ListSet.scala +++ b/src/library/scala/collection/immutable/ListSet.scala @@ -111,8 +111,8 @@ object ListSet extends IterableFactory[ListSet] { def from[E](it: scala.collection.IterableOnce[E]): ListSet[E] = it match { - case _ if it.knownSize == 0 => empty[E] case ls: ListSet[E] => ls + case _ if it.knownSize == 0 => empty[E] case _ => (newBuilder[E] ++= it).result() } diff --git a/src/library/scala/collection/immutable/Queue.scala b/src/library/scala/collection/immutable/Queue.scala index 32fd8cf121fd..5f85ee0bd97c 100644 --- a/src/library/scala/collection/immutable/Queue.scala +++ b/src/library/scala/collection/immutable/Queue.scala @@ -177,8 +177,8 @@ object Queue extends StrictOptimizedSeqFactory[Queue] { def newBuilder[A]: Builder[A, Queue[A]] = new ListBuffer[A] mapResult (x => new Queue[A](Nil, x.toList)) def from[A](source: IterableOnce[A]): Queue[A] = source match { - case _ if source.knownSize == 0 => empty[A] case q: Queue[A] => q + case _ if source.knownSize == 0 => empty[A] case _ => new Queue[A](Nil, ListBuffer.from(source).toList) } diff --git a/src/library/scala/collection/immutable/Set.scala b/src/library/scala/collection/immutable/Set.scala index f95468e21c4d..950da3c2fb2f 100644 --- a/src/library/scala/collection/immutable/Set.scala +++ b/src/library/scala/collection/immutable/Set.scala @@ -86,12 +86,12 @@ object Set extends IterableFactory[Set] { def from[E](it: collection.IterableOnce[E]): Set[E] = it match { - case _ if it.knownSize == 0 => empty[E] // We want `SortedSet` (and subclasses, such as `BitSet`) to // rebuild themselves to avoid element type widening issues - case _: SortedSet[E] => (newBuilder[E] ++= it).result() - case s: Set[E] => s - case _ => (newBuilder[E] ++= it).result() + case _: SortedSet[E] => (newBuilder[E] ++= it).result() + case _ if it.knownSize == 0 => empty[E] + case s: Set[E] => s + case _ => (newBuilder[E] ++= it).result() } def newBuilder[A]: Builder[A, Set[A]] = diff --git a/src/library/scala/collection/immutable/Vector.scala b/src/library/scala/collection/immutable/Vector.scala index 6c70a84357cc..d7168119c272 100644 --- a/src/library/scala/collection/immutable/Vector.scala +++ b/src/library/scala/collection/immutable/Vector.scala @@ -20,9 +20,9 @@ object Vector extends StrictOptimizedSeqFactory[Vector] { def from[E](it: collection.IterableOnce[E]): Vector[E] = it match { + case v: Vector[E] => v case _ if it.knownSize == 0 => empty[E] - case v: Vector[E] => v - case _ => (newBuilder ++= it).result() + case _ => (newBuilder ++= it).result() } def newBuilder[A]: Builder[A, Vector[A]] = new VectorBuilder[A] From 1d384eba33cbb3a23691fd086afc97b9be865249 Mon Sep 17 00:00:00 2001 From: Jason Zaugg Date: Tue, 19 Jun 2018 14:21:16 +1000 Subject: [PATCH 031/143] Simplify collection factories to avoid indirection through View.Elems --- src/library/scala/collection/Factory.scala | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/library/scala/collection/Factory.scala b/src/library/scala/collection/Factory.scala index 768956f80b7c..ae6bda602952 100644 --- a/src/library/scala/collection/Factory.scala +++ b/src/library/scala/collection/Factory.scala @@ -90,7 +90,7 @@ trait IterableFactory[+CC[_]] extends Serializable { * @param elems the elements of the created $coll * @return a new $coll with elements `elems` */ - def apply[A](elems: A*): CC[A] = from(new View.Elems(elems: _*)) + def apply[A](elems: A*): CC[A] = from(elems) /** Produces a $coll containing repeated applications of a function to a start value. * @@ -313,7 +313,7 @@ trait StrictOptimizedSeqFactory[+CC[_]] extends SeqFactory[CC] { */ trait SpecificIterableFactory[-A, +C] extends Factory[A, C] { def empty: C - def apply(xs: A*): C = fromSpecific(new View.Elems(xs: _*)) + def apply(xs: A*): C = fromSpecific(xs) def fill(n: Int)(elem: => A): C = fromSpecific(new View.Fill(n)(elem)) def newBuilder: Builder[A, C] @@ -392,7 +392,7 @@ trait EvidenceIterableFactory[+CC[_], Ev[_]] extends Serializable { def empty[A : Ev]: CC[A] - def apply[A : Ev](xs: A*): CC[A] = from(new View.Elems(xs: _*)) + def apply[A : Ev](xs: A*): CC[A] = from(xs) /** Produces a $coll containing the results of some element computation a number of times. * @param n the number of elements contained in the $coll. From 4e425f7ecde83eda0c977356d1090c99f8866318 Mon Sep 17 00:00:00 2001 From: Jason Zaugg Date: Fri, 29 Jun 2018 16:14:22 +1000 Subject: [PATCH 032/143] Add more empty tree fast paths to TreeMap.iterator variants --- .../scala/collection/mutable/LongMap.scala | 2 +- .../scala/collection/mutable/TreeMap.scala | 27 ++++++++++++------- 2 files changed, 19 insertions(+), 10 deletions(-) diff --git a/src/library/scala/collection/mutable/LongMap.scala b/src/library/scala/collection/mutable/LongMap.scala index 66c49af84162..0c418fdcd459 100644 --- a/src/library/scala/collection/mutable/LongMap.scala +++ b/src/library/scala/collection/mutable/LongMap.scala @@ -405,7 +405,7 @@ final class LongMap[V] private[collection] (defaultEntry: Long => V, initialBuff } } - // TODO override these for efficiency. See immutable.LongMap for how to organize the code. + // TODO PERF override these for efficiency. See immutable.LongMap for how to organize the code. override def keysIterator: Iterator[Long] = super.keysIterator override def valuesIterator: Iterator[V] = super.valuesIterator diff --git a/src/library/scala/collection/mutable/TreeMap.scala b/src/library/scala/collection/mutable/TreeMap.scala index bd4ead7b4d9a..3db82c9dfba8 100644 --- a/src/library/scala/collection/mutable/TreeMap.scala +++ b/src/library/scala/collection/mutable/TreeMap.scala @@ -49,11 +49,20 @@ sealed class TreeMap[K, V] private (tree: RB.Tree[K, V])(implicit val ordering: else RB.valuesIterator(tree, None) } - def keysIteratorFrom(start: K): Iterator[K] = RB.keysIterator(tree, Some(start)) + def keysIteratorFrom(start: K): Iterator[K] = { + if (isEmpty) Iterator.empty + else RB.keysIterator(tree, Some(start)) + } - def iteratorFrom(start: K): Iterator[(K, V)] = RB.iterator(tree, Some(start)) + def iteratorFrom(start: K): Iterator[(K, V)] = { + if (isEmpty) Iterator.empty + else RB.iterator(tree, Some(start)) + } - override def valuesIteratorFrom(start: K): Iterator[V] = RB.valuesIterator(tree, Some(start)) + override def valuesIteratorFrom(start: K): Iterator[V] = { + if (isEmpty) Iterator.empty + else RB.valuesIterator(tree, Some(start)) + } def addOne(elem: (K, V)): this.type = { RB.insert(tree, elem._1, elem._2); this } @@ -145,12 +154,12 @@ sealed class TreeMap[K, V] private (tree: RB.Tree[K, V])(implicit val ordering: override def get(key: K) = if (isInsideViewBounds(key)) RB.get(tree, key) else None - override def iterator = RB.iterator(tree, from, until) - override def keysIterator: Iterator[K] = RB.keysIterator(tree, from, until) - override def valuesIterator: Iterator[V] = RB.valuesIterator(tree, from, until) - override def keysIteratorFrom(start: K) = RB.keysIterator(tree, pickLowerBound(Some(start)), until) - override def iteratorFrom(start: K) = RB.iterator(tree, pickLowerBound(Some(start)), until) - override def valuesIteratorFrom(start: K) = RB.valuesIterator(tree, pickLowerBound(Some(start)), until) + override def iterator = if (RB.size(tree) == 0) Iterator.empty else RB.iterator(tree, from, until) + override def keysIterator: Iterator[K] = if (RB.size(tree) == 0) Iterator.empty else RB.keysIterator(tree, from, until) + override def valuesIterator: Iterator[V] = if (RB.size(tree) == 0) Iterator.empty else RB.valuesIterator(tree, from, until) + override def keysIteratorFrom(start: K) = if (RB.size(tree) == 0) Iterator.empty else RB.keysIterator(tree, pickLowerBound(Some(start)), until) + override def iteratorFrom(start: K) = if (RB.size(tree) == 0) Iterator.empty else RB.iterator(tree, pickLowerBound(Some(start)), until) + override def valuesIteratorFrom(start: K) = if (RB.size(tree) == 0) Iterator.empty else RB.valuesIterator(tree, pickLowerBound(Some(start)), until) override def size = if (RB.size(tree) == 0) 0 else iterator.length override def knownSize: Int = if (RB.size(tree) == 0) 0 else -1 override def isEmpty = RB.size(tree) == 0 || !iterator.hasNext From ea9478bd7bc212b8378417ef13f4fe83f94e82b9 Mon Sep 17 00:00:00 2001 From: Jason Zaugg Date: Fri, 29 Jun 2018 16:27:48 +1000 Subject: [PATCH 033/143] Immutable collections: test reusable empty instance / sharing of inputs of from --- .../collection/immutable/HashMapTest.scala | 10 +++++++++- .../collection/immutable/HashSetTest.scala | 18 ++++++++++++++++++ .../scala/collection/immutable/ListTest.scala | 8 ++++++++ .../collection/immutable/TreeMapTest.scala | 6 ++++++ .../collection/immutable/TreeSetTest.scala | 6 ++++++ .../collection/immutable/VectorTest.scala | 9 +++++++++ 6 files changed, 56 insertions(+), 1 deletion(-) create mode 100644 test/junit/scala/collection/immutable/HashSetTest.scala diff --git a/test/junit/scala/collection/immutable/HashMapTest.scala b/test/junit/scala/collection/immutable/HashMapTest.scala index 37140810bbf0..dade5ff6869c 100644 --- a/test/junit/scala/collection/immutable/HashMapTest.scala +++ b/test/junit/scala/collection/immutable/HashMapTest.scala @@ -1,6 +1,6 @@ package scala.collection.immutable -import org.junit.Assert.assertEquals +import org.junit.Assert.{assertEquals, assertSame} import org.junit.Test import org.junit.runner.RunWith import org.junit.runners.JUnit4 @@ -53,4 +53,12 @@ class HashMapTest { assertEquals("a", m2(1)) assertEquals(0, m2(3)) } + + @Test + def factoryReuse(): Unit = { + assertSame(ChampHashMap.empty, ChampHashMap.empty) + assertSame(ChampHashMap.empty, ChampHashMap()) + val m = ChampHashMap("a" -> "a") + assertSame(m, ChampHashMap.from(m)) + } } diff --git a/test/junit/scala/collection/immutable/HashSetTest.scala b/test/junit/scala/collection/immutable/HashSetTest.scala new file mode 100644 index 000000000000..6cb00a836d4e --- /dev/null +++ b/test/junit/scala/collection/immutable/HashSetTest.scala @@ -0,0 +1,18 @@ +package scala.collection.immutable + +import org.junit.Assert.{assertEquals, assertSame} +import org.junit.Test +import org.junit.runner.RunWith +import org.junit.runners.JUnit4 + +@RunWith(classOf[JUnit4]) +class HashSetTest { + + @Test + def factoryReuse(): Unit = { + assertSame(ChampHashSet.empty, ChampHashSet.empty) + assertSame(ChampHashSet.empty, ChampHashSet()) + val m = ChampHashSet("a") + assertSame(m, ChampHashSet.from(m)) + } +} diff --git a/test/junit/scala/collection/immutable/ListTest.scala b/test/junit/scala/collection/immutable/ListTest.scala index d600887f4ebb..19fe45039e78 100644 --- a/test/junit/scala/collection/immutable/ListTest.scala +++ b/test/junit/scala/collection/immutable/ListTest.scala @@ -1,5 +1,6 @@ package scala.collection.immutable +import org.junit.Assert.assertSame import org.junit.{Assert, Test} import org.junit.runner.RunWith import org.junit.runners.JUnit4 @@ -65,4 +66,11 @@ class ListTest { case e: IndexOutOfBoundsException => () } } + + @Test + def factoryReuse(): Unit = { + val ls = List("a") + assertSame(ls, List.apply(ls: _*)) + assertSame(ls, List.from(ls)) + } } diff --git a/test/junit/scala/collection/immutable/TreeMapTest.scala b/test/junit/scala/collection/immutable/TreeMapTest.scala index 33517fccddde..a152945cd5a3 100644 --- a/test/junit/scala/collection/immutable/TreeMapTest.scala +++ b/test/junit/scala/collection/immutable/TreeMapTest.scala @@ -17,4 +17,10 @@ class TreeMapTest { assertEquals(tree, tree drop Int.MinValue) assertEquals(tree, tree dropRight Int.MinValue) } + + @Test + def factoryReuse(): Unit = { + val m = TreeMap("a" -> "a") + assertSame(m, TreeMap.from(m)) + } } diff --git a/test/junit/scala/collection/immutable/TreeSetTest.scala b/test/junit/scala/collection/immutable/TreeSetTest.scala index e711e183aa37..a65a8d401523 100644 --- a/test/junit/scala/collection/immutable/TreeSetTest.scala +++ b/test/junit/scala/collection/immutable/TreeSetTest.scala @@ -17,4 +17,10 @@ class TreeSetTest { assertEquals(set, set drop Int.MinValue) assertEquals(set, set dropRight Int.MinValue) } + + @Test + def factoryReuse(): Unit = { + val m = TreeSet("a") + assertSame(m, TreeSet.from(m)) + } } diff --git a/test/junit/scala/collection/immutable/VectorTest.scala b/test/junit/scala/collection/immutable/VectorTest.scala index 06f123084f14..192c756ef0cc 100644 --- a/test/junit/scala/collection/immutable/VectorTest.scala +++ b/test/junit/scala/collection/immutable/VectorTest.scala @@ -39,4 +39,13 @@ class VectorTest { assertEquals(els, prefix.toList ++: suffix) } } + + @Test + def factoryReuse(): Unit = { + assertSame(Vector.empty, Vector.empty) + assertSame(Vector.empty, Vector()) + val m = Vector("a") + assertSame(m, Vector.from(m)) + assertSame(m, Vector.apply(m: _*)) + } } From c0b038c0c9abeac1d6a03041091fc66c0caef127 Mon Sep 17 00:00:00 2001 From: Jason Zaugg Date: Fri, 29 Jun 2018 16:44:18 +1000 Subject: [PATCH 034/143] Reorder tests in Seq.equals --- src/library/scala/collection/Seq.scala | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/library/scala/collection/Seq.scala b/src/library/scala/collection/Seq.scala index f5f7a79ec190..f0ab600ae758 100644 --- a/src/library/scala/collection/Seq.scala +++ b/src/library/scala/collection/Seq.scala @@ -28,11 +28,12 @@ trait Seq[+A] */ def canEqual(that: Any): Boolean = true - override def equals(o: scala.Any): Boolean = + override def equals(o: scala.Any): Boolean = this.eq(o.asInstanceOf[AnyRef]) || ( o match { - case it: Seq[A] => (this eq it) || (it canEqual this) && sameElements(it) + case it: Seq[A] => (it canEqual this) && sameElements(it) case _ => false } + ) override def hashCode(): Int = MurmurHash3.seqHash(toIterable) From 37d0ca05b9cbe89d9f51071c635fb5f7d0d8a0b2 Mon Sep 17 00:00:00 2001 From: Jason Zaugg Date: Wed, 27 Jun 2018 15:08:20 +1000 Subject: [PATCH 035/143] Unit test for range position validation --- .../reflect/internal/PositionsTest.scala | 57 +++++++++++++++++++ .../symtab/SymbolTableForUnitTesting.scala | 4 +- 2 files changed, 59 insertions(+), 2 deletions(-) create mode 100644 test/junit/scala/reflect/internal/PositionsTest.scala diff --git a/test/junit/scala/reflect/internal/PositionsTest.scala b/test/junit/scala/reflect/internal/PositionsTest.scala new file mode 100644 index 000000000000..348c63fecd2f --- /dev/null +++ b/test/junit/scala/reflect/internal/PositionsTest.scala @@ -0,0 +1,57 @@ +package scala.reflect.internal + +import org.junit.Test + +import scala.reflect.internal.util.NoSourceFile +import scala.tools.nsc.reporters.StoreReporter +import scala.tools.nsc.symtab.SymbolTableForUnitTesting +import scala.tools.testing.AssertUtil + +class PositionsTest { + + private object symbolTable extends SymbolTableForUnitTesting { + override def useOffsetPositions: Boolean = false + override val reporter = new StoreReporter + } + + @Test def positionValidation(): Unit = { + import symbolTable._ + def checkInvalid(tree: Tree): Unit = { + reporter.reset() + AssertUtil.assertThrows[ValidateException](validatePositions(tree)) + } + + def checkValid(tree: Tree): Unit = { + reporter.reset() + validatePositions(tree) + assert(!reporter.hasErrors) + } + def rangePos(start: Int, end: Int): util.Position = util.Position.range(NoSourceFile, start, start, end) + def offsetPos(point: Int): util.Position = util.Position.offset(NoSourceFile, point) + def tree: Tree = Ident(TermName("x")) + def rangePositioned(start: Int, end: Int): Tree = { + Ident(TermName("x")).setPos(rangePos(start, end)) + } + // overlapping ranges + checkInvalid(Block(rangePositioned(0, 2), rangePositioned(1, 2), EmptyTree).setPos(rangePos(0, 2))) + checkInvalid(Block(rangePositioned(1, 2), rangePositioned(0, 2), EmptyTree).setPos(rangePos(0, 2))) + + // transparent position not deemed to overlap itself + checkValid(Block(rangePositioned(0, 2), tree.setPos(rangePos(1, 2).makeTransparent), EmptyTree).setPos(rangePos(0, 2))) + + // children of transparent position overlapping with sibling of transparent position. + checkInvalid(Block(rangePositioned(0, 2), Block(Nil, rangePositioned(1, 2)).setPos(rangePos(1, 2).makeTransparent), EmptyTree).setPos(rangePos(0, 2))) + + // adjacent ranges are allowed to touch + checkValid(Block(rangePositioned(0, 1), rangePositioned(1, 2), EmptyTree).setPos(rangePos(0, 2))) + + // offset position between overlapping ranges + checkInvalid(Block(rangePositioned(0, 2), tree.setPos(offsetPos(0)), rangePositioned(1, 2), EmptyTree).setPos(rangePos(0, 2))) + + // child range position larger than parent + checkInvalid(Block(Nil, rangePositioned(0, 3)).setPos(rangePos(0, 2))) + + // child offset position outside of parent + checkInvalid(Block(Nil, tree.setPos(offsetPos(3)).setPos(rangePos(0, 2)))) + } +} diff --git a/test/junit/scala/tools/nsc/symtab/SymbolTableForUnitTesting.scala b/test/junit/scala/tools/nsc/symtab/SymbolTableForUnitTesting.scala index 7e2028eefb39..cbd5634f292f 100644 --- a/test/junit/scala/tools/nsc/symtab/SymbolTableForUnitTesting.scala +++ b/test/junit/scala/tools/nsc/symtab/SymbolTableForUnitTesting.scala @@ -2,7 +2,7 @@ package scala.tools.nsc package symtab import scala.reflect.ClassTag -import scala.reflect.internal.{NoPhase, Phase, SomePhase} +import scala.reflect.internal.{NoPhase, Phase, Reporter, SomePhase} import scala.reflect.internal.util.Statistics import scala.tools.util.PathResolver import util.ClassPath @@ -81,7 +81,7 @@ class SymbolTableForUnitTesting extends SymbolTable { def erasurePhase: scala.reflect.internal.Phase = SomePhase // Members declared in scala.reflect.internal.Reporting - def reporter = new scala.reflect.internal.ReporterImpl { + def reporter: Reporter = new scala.reflect.internal.ReporterImpl { protected def info0(pos: Position, msg: String, severity: Severity, force: Boolean): Unit = println(msg) } From 49bb79f3f2e03a7ad2abf41378f714ada11cc423 Mon Sep 17 00:00:00 2001 From: Mike Skells Date: Tue, 19 Jun 2018 08:20:18 +0100 Subject: [PATCH 036/143] Optimise rangepos checking use traverser rather than external iteration reuse temporary results where possible --- .../tools/nsc/interactive/ContextTrees.scala | 12 +- .../collection/mutable/ArrayBuilder.scala | 6 +- .../scala/reflect/internal/Positions.scala | 274 ++++++++++-------- .../scala/reflect/internal/Trees.scala | 17 +- .../reflect/runtime/JavaUniverseForce.scala | 1 - 5 files changed, 183 insertions(+), 127 deletions(-) diff --git a/src/interactive/scala/tools/nsc/interactive/ContextTrees.scala b/src/interactive/scala/tools/nsc/interactive/ContextTrees.scala index 975761bb8772..2d513f7e429c 100644 --- a/src/interactive/scala/tools/nsc/interactive/ContextTrees.scala +++ b/src/interactive/scala/tools/nsc/interactive/ContextTrees.scala @@ -108,10 +108,14 @@ trait ContextTrees { self: Global => */ def addContext(contexts: Contexts, context: Context): Unit = { val cpos = context.tree.pos - if (cpos.isTransparent) - for (t <- context.tree.children flatMap solidDescendants) - addContext(contexts, context, t.pos) - else + if (cpos.isTransparent) { + val traverser = new ChildSolidDescendantsCollector() { + override def traverseSolidChild(t: Tree): Unit = { + addContext(contexts, context, t.pos) + } + } + traverser.apply(context.tree) + } else addContext(contexts, context, cpos) } diff --git a/src/library/scala/collection/mutable/ArrayBuilder.scala b/src/library/scala/collection/mutable/ArrayBuilder.scala index d023110c1b42..10c1c94f7054 100644 --- a/src/library/scala/collection/mutable/ArrayBuilder.scala +++ b/src/library/scala/collection/mutable/ArrayBuilder.scala @@ -60,9 +60,9 @@ object ArrayBuilder { private var size: Int = 0 private def mkArray(size: Int): Array[T] = { - val newelems = new Array[T](size) - if (this.size > 0) Array.copy(elems, 0, newelems, 0, this.size) - newelems + if (capacity == size && capacity > 0) elems + else if (elems eq null) new Array[T](size) + else java.util.Arrays.copyOf[T](elems, size) } private def resize(size: Int) { diff --git a/src/reflect/scala/reflect/internal/Positions.scala b/src/reflect/scala/reflect/internal/Positions.scala index b56762c42b37..f7c488c7d365 100644 --- a/src/reflect/scala/reflect/internal/Positions.scala +++ b/src/reflect/scala/reflect/internal/Positions.scala @@ -3,7 +3,6 @@ package reflect package internal import util._ -import scala.collection.mutable.ListBuffer /** Handling range positions * atPos, the main method in this trait, will add positions to a tree, @@ -37,9 +36,22 @@ trait Positions extends api.Positions { self: SymbolTable => def wrappingPos(default: Position, trees: List[Tree]): Position = wrappingPos(default, trees, focus = true) def wrappingPos(default: Position, trees: List[Tree], focus: Boolean): Position = { if (useOffsetPositions) default else { - val ranged = trees filter (_.pos.isRange) - if (ranged.isEmpty) if (focus) default.focus else default - else Position.range(default.source, (ranged map (_.pos.start)).min, default.point, (ranged map (_.pos.end)).max) + var rest = trees + var min = Int.MaxValue + var max = Int.MinValue + while (rest ne Nil) { + val head = rest.head + rest = rest.tail + val pos = head.pos + if (pos.isRange) { + min = Math.min(min, pos.start) + max = Math.max(max, pos.end) + } + } + if (min > max) + //there are no ranges + if (focus) default.focus else default + else Position.range(default.source, min, default.point, max) } } @@ -66,12 +78,13 @@ trait Positions extends api.Positions { self: SymbolTable => def isOverlapping(pos: Position) = pos.isRange && (others exists (pos overlaps _.pos)) - if (isOverlapping(tree.pos)) { + val treePos = tree.pos + if (isOverlapping(treePos)) { val children = tree.children children foreach (ensureNonOverlapping(_, others, focus)) - if (tree.pos.isOpaqueRange) { - val wpos = wrappingPos(tree.pos, children, focus) - tree setPos (if (isOverlapping(wpos)) tree.pos.makeTransparent else wpos) + if (treePos.isOpaqueRange) { + val wpos = wrappingPos(treePos, children, focus) + tree setPos (if (isOverlapping(wpos)) treePos.makeTransparent else wpos) } } } @@ -80,124 +93,163 @@ trait Positions extends api.Positions { self: SymbolTable => if (useOffsetPositions) Position.offset(source, point) else Position.range(source, start, point, end) - def validatePositions(tree: Tree) { - if (useOffsetPositions) return - - def reportTree(prefix : String, tree : Tree) { - val source = if (tree.pos.isDefined) tree.pos.source else "" - inform("== "+prefix+" tree ["+tree.id+"] of type "+tree.productPrefix+" at "+tree.pos.show+source) - inform("") - inform(treeStatus(tree)) - inform("") - } - def positionError(msg: String)(body : => Unit) { - inform("======= Position error\n" + msg) - body - inform("\nWhile validating #" + tree.id) - inform(treeStatus(tree)) - inform("\nChildren:") - tree.children foreach (t => inform(" " + treeStatus(t, tree))) - inform("=======") - throw new ValidateException(msg) - } + abstract class ChildSolidDescendantsCollector extends Traverser { + // don't traverse annotations + override def traverseModifiers(mods: Modifiers): Unit = () - def validate(tree: Tree, encltree: Tree): Unit = { + override def traverse(tree: Tree): Unit = + if (tree ne EmptyTree) { + if (tree.pos.isTransparent) super.traverse(tree) + else { + traverseSolidChild(tree) + } + } + def traverseSolidChild(t: Tree): Unit + def apply(t: Tree): Unit = super.traverse(t) + } - if (!tree.isEmpty && tree.canHaveAttrs) { - if (settings.Yposdebug && settings.verbose) - inform("[%10s] %s".format("validate", treeStatus(tree, encltree))) + private[this] def reportTree(prefix: String, tree: Tree) { + val source = if (tree.pos.isDefined) tree.pos.source else "" + inform("== " + prefix + " tree [" + tree.id + "] of type " + tree.productPrefix + " at " + tree.pos.show + source) + inform("") + inform(treeStatus(tree)) + inform("") + } - if (!tree.pos.isDefined) - positionError("Unpositioned tree #"+tree.id) { - inform("%15s %s".format("unpositioned", treeStatus(tree, encltree))) - inform("%15s %s".format("enclosing", treeStatus(encltree))) - encltree.children foreach (t => inform("%15s %s".format("sibling", treeStatus(t, encltree)))) - } - if (tree.pos.isRange) { - if (!encltree.pos.isRange) - positionError("Synthetic tree ["+encltree.id+"] contains nonsynthetic tree ["+tree.id+"]") { - reportTree("Enclosing", encltree) - reportTree("Enclosed", tree) - } - if (!(encltree.pos includes tree.pos)) - positionError("Enclosing tree ["+encltree.id+"] does not include tree ["+tree.id+"]") { - reportTree("Enclosing", encltree) - reportTree("Enclosed", tree) - } + private[this] def positionError(topTree: Tree, msg: String)(body: => Unit) { + inform("======= Position error\n" + msg) + body + inform("\nWhile validating #" + topTree.id) + inform(treeStatus(topTree)) + inform("\nChildren:") + topTree.children foreach (t => inform(" " + treeStatus(t, topTree))) + inform("=======") + throw new ValidateException(msg) + } - findOverlapping(tree.children flatMap solidDescendants) match { - case List() => ; - case xs => { - positionError("Overlapping trees "+xs.map { case (x, y) => (x.id, y.id) }.mkString("", ", ", "")) { - reportTree("Ancestor", tree) - for((x, y) <- xs) { - reportTree("First overlapping", x) - reportTree("Second overlapping", y) - } - } - } - } - } - for (ct <- tree.children flatMap solidDescendants) validate(ct, tree) + private val posStartOrdering: Ordering[Tree] = new Ordering[Tree] { + override def compare(x: Tree, y: Tree): Int = { + @inline def posOf(t: Tree): Int = { + val pos = t.pos + if (pos eq NoPosition) Int.MinValue else pos.start } + Integer.compare(posOf(x), posOf(y)) } - - validate(tree, tree) } + def validatePositions(tree: Tree): Unit = if (!useOffsetPositions) { + object worker { + val trace = settings.Yposdebug && settings.verbose + val topTree = tree + + object solidChildrenCollector extends ChildSolidDescendantsCollector { + private[this] var size = 0 + private[this] var childSolidDescendants = new Array[Tree](32) + private[this] val spares = new java.util.ArrayList[Array[Tree]] + + def borrowArray: Array[Tree] = { + val borrowed = childSolidDescendants + childSolidDescendants = if (spares.isEmpty) new Array[Tree](32) else spares.remove(spares.size - 1) + clear() + borrowed + } + def spareArray(array: Array[Tree]): Unit = { + spares.add(array) + } - def solidDescendants(tree: Tree): List[Tree] = - if (tree.pos.isTransparent) tree.children flatMap solidDescendants - else List(tree) + def child(i:Int) = childSolidDescendants(i) + def collectedSize = size + def sortedArray: Array[Tree] = { + if (size > 1) + java.util.Arrays.sort(childSolidDescendants, 0, size, posStartOrdering) + childSolidDescendants + } - /** A free range from `lo` to `hi` */ - private def free(lo: Int, hi: Int): Range = - Range(Position.range(null, lo, lo, hi), EmptyTree) + //we dont care about zeroing the array + def clear() {size = 0} - /** The maximal free range */ - private lazy val maxFree: Range = free(0, Int.MaxValue) + def traverseSolidChild(t: Tree): Unit = { + if (size == childSolidDescendants.length) { + spareArray(childSolidDescendants) + childSolidDescendants = java.util.Arrays.copyOf(childSolidDescendants, size << 1) + } + childSolidDescendants(size) = t + size += 1 + } + } - /** A singleton list of a non-empty range from `lo` to `hi`, or else the empty List */ - private def maybeFree(lo: Int, hi: Int) = - if (lo < hi) List(free(lo, hi)) - else List() + def loop(tree: Tree, encltree: Tree) { + if (!tree.isEmpty && tree.canHaveAttrs) { + val treePos = tree.pos + if (trace) + inform("[%10s] %s".format("validate", treeStatus(tree, encltree))) + + if (!treePos.isDefined) + positionError(topTree, "Unpositioned tree #" + tree.id) { + inform("%15s %s".format("unpositioned", treeStatus(tree, encltree))) + inform("%15s %s".format("enclosing", treeStatus(encltree))) + encltree.children foreach (t => inform("%15s %s".format("sibling", treeStatus(t, encltree)))) + } - /** Insert `pos` into ranges `rs` if possible; - * otherwise add conflicting trees to `conflicting`. - */ - private def insert(rs: List[Range], t: Tree, conflicting: ListBuffer[Tree]): List[Range] = rs match { - case List() => - assert(conflicting.nonEmpty) - rs - case r :: rs1 => - assert(!t.pos.isTransparent) - if (r.isFree && (r.pos includes t.pos)) { -// inform("subdividing "+r+"/"+t.pos) - maybeFree(t.pos.end, r.pos.end) ::: List(Range(t.pos, t)) ::: maybeFree(r.pos.start, t.pos.start) ::: rs1 - } else { - if (!r.isFree && (r.pos overlaps t.pos)) conflicting += r.tree - r :: insert(rs1, t, conflicting) - } - } + solidChildrenCollector(tree) + val numChildren = solidChildrenCollector.collectedSize - /** Replace elem `t` of `ts` by `replacement` list. */ - private def replace(ts: List[Tree], t: Tree, replacement: List[Tree]): List[Tree] = - if (ts.head == t) replacement ::: ts.tail - else ts.head :: replace(ts.tail, t, replacement) + if (treePos.isRange) { + val enclPos = encltree.pos + if (!enclPos.isRange) + positionError(topTree, "Synthetic tree [" + encltree.id + "] contains nonsynthetic tree [" + tree.id + "]") { + reportTree("Enclosing", encltree) + reportTree("Enclosed", tree) + } + if (!(enclPos includes treePos)) + positionError(topTree, "Enclosing tree [" + encltree.id + "] does not include tree [" + tree.id + "]") { + reportTree("Enclosing", encltree) + reportTree("Enclosed", tree) + } - /** Does given list of trees have mutually non-overlapping positions? - * pre: None of the trees is transparent - */ - def findOverlapping(cts: List[Tree]): List[(Tree, Tree)] = { - var ranges = List(maxFree) - for (ct <- cts) { - if (ct.pos.isOpaqueRange) { - val conflicting = new ListBuffer[Tree] - ranges = insert(ranges, ct, conflicting) - if (conflicting.nonEmpty) return conflicting.toList map (t => (t, ct)) + if (numChildren > 1) { + val childSolidDescendants = solidChildrenCollector.sortedArray + var t1 = childSolidDescendants(0) + var t1Pos = t1.pos + var i = 1 + while (i < numChildren) { + val t2 = childSolidDescendants(i) + val t2Pos = t2.pos + if (t1Pos.overlaps(t2Pos)) { + positionError(topTree, "Overlapping trees") { + reportTree("Ancestor", tree) + reportTree("First overlapping", t1) + reportTree("Second overlapping", t2) + } + } + //why only for range + if (t2Pos.isRange) { + t1 = t2 + t1Pos = t2Pos + } + i += 1 + } + } + } + if (numChildren > 0) { + if (numChildren == 1) { + val first = solidChildrenCollector.child(0) + solidChildrenCollector.clear() + loop(first, tree) + } else { + val snap = solidChildrenCollector.borrowArray + var i = 0 + while (i < numChildren) { + loop(snap(i), tree) + i += 1 + } + solidChildrenCollector.spareArray(snap) + } + } + } } } - List() + worker.loop(tree, tree) } /** Set position of all children of a node @@ -265,10 +317,6 @@ trait Positions extends api.Positions { self: SymbolTable => } } - case class Range(pos: Position, tree: Tree) { - def isFree = tree == EmptyTree - } - class TypedLocator(pos: Position) extends Locator(pos) { override protected def isEligible(t: Tree) = super.isEligible(t) && t.tpe != null } diff --git a/src/reflect/scala/reflect/internal/Trees.scala b/src/reflect/scala/reflect/internal/Trees.scala index 7b78fca09b58..f94e16a0afb7 100644 --- a/src/reflect/scala/reflect/internal/Trees.scala +++ b/src/reflect/scala/reflect/internal/Trees.scala @@ -9,6 +9,7 @@ package internal import Flags._ import scala.collection.mutable +import scala.collection.mutable.ListBuffer import scala.reflect.macros.Attachments import util.{Statistics, StatisticsStatics} @@ -150,13 +151,17 @@ trait Trees extends api.Trees { }) override def children: List[Tree] = { - def subtrees(x: Any): List[Tree] = x match { - case EmptyTree => Nil - case t: Tree => List(t) - case xs: List[_] => xs flatMap subtrees - case _ => Nil + var builder: ListBuffer[Tree] = null + def subtrees(x: Any): Unit = x match { + case EmptyTree => + case t: Tree => + if (builder eq null) builder = new ListBuffer[Tree] + builder += t + case xs: List[_] => xs foreach subtrees + case _ => } - productIterator.toList flatMap subtrees + productIterator foreach subtrees + if (builder eq null) Nil else builder.result() } def freeTerms: List[FreeTermSymbol] = freeSyms[FreeTermSymbol](_.isFreeTerm, _.termSymbol) diff --git a/src/reflect/scala/reflect/runtime/JavaUniverseForce.scala b/src/reflect/scala/reflect/runtime/JavaUniverseForce.scala index 0d72cbd6f607..c2751fea80ab 100644 --- a/src/reflect/scala/reflect/runtime/JavaUniverseForce.scala +++ b/src/reflect/scala/reflect/runtime/JavaUniverseForce.scala @@ -53,7 +53,6 @@ trait JavaUniverseForce { self: runtime.JavaUniverse => this.KnownDirectSubclassesCalled this.noPrint this.typeDebug - this.Range // inaccessible: this.posAssigner this.ConsoleWriter this.RefTree From 64ef8585bb54ec3e6b3713aec8895dc54fa86b9a Mon Sep 17 00:00:00 2001 From: Jason Zaugg Date: Mon, 2 Jul 2018 17:09:07 +1000 Subject: [PATCH 037/143] Avoid ScalaRuntime for generic arrays that are refined to concrete arrays The value bound by a type pattern takes on an intersection type of the scrutinee type and the pattern type. In the enclosed test, this leads to a type like `Array[T] with Array[AnyRef]`. This is erased to `Array[Object]`, thanks to use of `intersectionDominator` in `ErasureMap`. However, some related code in the erasure tree transform was unable to see through this refinment type and emitted the slower code for array access using runtime type checks in ScalaRuntime. --- .../reflect/internal/transform/Erasure.scala | 4 +- .../tools/nsc/transform/ErasureTest.scala | 41 +++++++++++++++++++ 2 files changed, 43 insertions(+), 2 deletions(-) create mode 100644 test/junit/scala/tools/nsc/transform/ErasureTest.scala diff --git a/src/reflect/scala/reflect/internal/transform/Erasure.scala b/src/reflect/scala/reflect/internal/transform/Erasure.scala index f60adfe530a3..64caafa978f6 100644 --- a/src/reflect/scala/reflect/internal/transform/Erasure.scala +++ b/src/reflect/scala/reflect/internal/transform/Erasure.scala @@ -56,9 +56,9 @@ trait Erasure { /** Arrays despite their finality may turn up as refined type parents, * e.g. with "tagged types" like Array[Int] with T. */ - protected def unboundedGenericArrayLevel(tp: Type): Int = tp match { + def unboundedGenericArrayLevel(tp: Type): Int = tp match { case GenericArray(level, core) if !(core <:< AnyRefTpe) => level - case RefinedType(ps, _) if ps.nonEmpty => logResult(s"Unbounded generic level for $tp is")((ps map unboundedGenericArrayLevel).max) + case RefinedType(ps, _) if ps.nonEmpty => logResult(s"Unbounded generic level for $tp is")(unboundedGenericArrayLevel(intersectionDominator(ps))) case _ => 0 } diff --git a/test/junit/scala/tools/nsc/transform/ErasureTest.scala b/test/junit/scala/tools/nsc/transform/ErasureTest.scala new file mode 100644 index 000000000000..ba1e80fb291f --- /dev/null +++ b/test/junit/scala/tools/nsc/transform/ErasureTest.scala @@ -0,0 +1,41 @@ +package scala.tools.nsc.transform + +import org.junit.Assert.assertEquals +import org.junit.Test + +import scala.tools.nsc.symtab.SymbolTableForUnitTesting +import scala.tools.testing.BytecodeTesting +import scala.tools.testing.BytecodeTesting.{assertNoInvoke, getMethod} + +class ErasureTest extends BytecodeTesting { + object symbolTable extends SymbolTableForUnitTesting + + @Test def testGenericArray(): Unit = { + import symbolTable._ + import definitions._ + val T = NoSymbol.newTypeParameter(TypeName("T")).setInfo(TypeBounds.empty) + val U = NoSymbol.newTypeParameter(TypeName("U")).setInfo(TypeBounds.empty) + val arrayTWithArrayString: Type = refinedType(appliedType(ArrayClass, T.tpeHK) :: appliedType(ArrayClass, StringTpe) :: Nil, NoSymbol) + val arrayTWithArrayU: Type = refinedType(appliedType(ArrayClass, T.tpeHK) :: appliedType(ArrayClass, U.tpeHK) :: Nil, NoSymbol) + + assertEquals(1, erasure.unboundedGenericArrayLevel(appliedType(ArrayClass, T.tpeHK))) + assertEquals(0, erasure.unboundedGenericArrayLevel(arrayTWithArrayString)) + assertEquals(1, erasure.unboundedGenericArrayLevel(arrayTWithArrayU)) + } + + import compiler._ + + @Test + def noScalaRuntimeForRefinedTypeWithGenericAndConcreteArray(): Unit = { + val code = + """class C { + | def t[T](xs: Array[T]): Unit = xs match { + | case x: Array[AnyRef] => x(0) + | case _ => + | } + |} + """.stripMargin + val c = compileClass(code) + assertNoInvoke(getMethod(c, "t")) + } +} From 31e8c5da69574b3e635dc9d1933bc3fe3109bba7 Mon Sep 17 00:00:00 2001 From: Jason Zaugg Date: Mon, 28 May 2018 14:51:06 +1000 Subject: [PATCH 038/143] Adds benchmarks for findMember. - Adds the new benchmarks subproject to the IntelliJ config - Add a benchmark for findMember --- .../internal/FindMemberBenchmark.scala | 53 +++++++++++++++++++ 1 file changed, 53 insertions(+) create mode 100644 test/benchmarks/src/main/scala/scala/reflect/internal/FindMemberBenchmark.scala diff --git a/test/benchmarks/src/main/scala/scala/reflect/internal/FindMemberBenchmark.scala b/test/benchmarks/src/main/scala/scala/reflect/internal/FindMemberBenchmark.scala new file mode 100644 index 000000000000..d8212b555af2 --- /dev/null +++ b/test/benchmarks/src/main/scala/scala/reflect/internal/FindMemberBenchmark.scala @@ -0,0 +1,53 @@ +package scala.reflect.internal + +import java.util.concurrent.TimeUnit + +import org.openjdk.jmh.annotations._ +import org.openjdk.jmh.infra.Blackhole + +import scala.tools.nsc.{Global, Settings} + +@BenchmarkMode(Array(org.openjdk.jmh.annotations.Mode.Throughput)) +@Fork(2) +@Threads(1) +@Warmup(iterations = 10) +@Measurement(iterations = 10) +@OutputTimeUnit(TimeUnit.SECONDS) +@State(Scope.Benchmark) +class FindMemberBenchmark { + type G <: Global with Singleton + var Type_List: G#Type = _ + var Type_ListRefined: G#Type = _ + var Name_Blerg: G#TermName = _ + var Name_toString: G#TermName = _ + var Name_isEmpty: G#TermName = _ + + @Setup(Level.Trial) def setup(): Unit = { + val settings = new Settings() + settings.usejavacp.value = true + settings.stopAfter.value = List("typer") + val global = new Global(settings).asInstanceOf[G] + import global._ + new Run() + Type_List = typeOf[List[_]] + Type_ListRefined = typeOf[List[_] with String { def foo: Int }] // this sort of type turns up in LUBs (search "val lubRefined = ") + Name_Blerg = TermName("Blerg") + Name_toString = TermName("toString") + Name_isEmpty = TermName("isEmpty") + + } + + @Benchmark + def findMember(bh: Blackhole): Unit = { + bh.consume(Type_List.member(Name_Blerg)) + bh.consume(Type_List.member(Name_isEmpty)) + bh.consume(Type_List.member(Name_toString)) + } + + @Benchmark + def findMemberRefined(bh: Blackhole): Unit = { + bh.consume(Type_ListRefined.member(Name_Blerg)) + bh.consume(Type_ListRefined.member(Name_isEmpty)) + bh.consume(Type_ListRefined.member(Name_toString)) + } +} From 0db7dd4e251ec7be75f6f8178977faae9c8274e9 Mon Sep 17 00:00:00 2001 From: "Diego E. Alonso Blas" Date: Fri, 1 Jun 2018 00:00:00 +0100 Subject: [PATCH 039/143] Fixes Issue 493, to avoid unnecessary allocation. This commit avoids unnecessary memory use noticed in Issue 493 of https://github.com/scala/scala-dev. The line: `refinementParents :::= currentBaseClass.parentSymbols` in each iteration pre-prends `currentBaseClass.parentSymbols` to the previous `refinementParens`. Thus, at the end of the loop, the length of `refinementParens` is the sum of the `parentSymbols` lists obtained from each symbol in `initBaseClasses` which is a refinement classes. That creates as many cons (`::`) objects. Moreover, since `parentSymbols` is not a `val` but a `def`, it creates a list of length `m`, copies it (to prepend it) and the throws it away. To prevent these allocations, we replace the flattened `refinedParents` list by a `refinedClasses` list, which stores the classes whose parents we have not yet looked into. We just use the `exists` methods of the List class to look for a refinedClass with at least one parent is the currentBaseClass. --- .../reflect/internal/tpe/FindMembers.scala | 27 +++++++++---------- 1 file changed, 13 insertions(+), 14 deletions(-) diff --git a/src/reflect/scala/reflect/internal/tpe/FindMembers.scala b/src/reflect/scala/reflect/internal/tpe/FindMembers.scala index aa56a9a6e323..b831cace621d 100644 --- a/src/reflect/scala/reflect/internal/tpe/FindMembers.scala +++ b/src/reflect/scala/reflect/internal/tpe/FindMembers.scala @@ -14,7 +14,7 @@ trait FindMembers { /** Implementation of `Type#{findMember, findMembers}` */ private[internal] abstract class FindMemberBase[T](tpe: Type, name: Name, excludedFlags: Long, requiredFlags: Long) { - protected val initBaseClasses: List[Symbol] = tpe.baseClasses + protected[this] final val initBaseClasses: List[Symbol] = tpe.baseClasses // The first base class, or the symbol of the ThisType // e.g in: @@ -73,9 +73,9 @@ trait FindMembers { // Have we seen a candidate deferred member? var deferredSeen = false - // All direct parents of refinement classes in the base class sequence + // All refinement classes in the base class sequence // from the current `walkBaseClasses` - var refinementParents: List[Symbol] = Nil + var refinementClasses: List[Symbol] = Nil // Has the current `walkBaseClasses` encountered a non-refinement class? var seenFirstNonRefinementClass = false @@ -93,7 +93,7 @@ trait FindMembers { if (meetsRequirements) { val excl: Long = flags & excluded val isExcluded: Boolean = excl != 0L - if (!isExcluded && isPotentialMember(sym, flags, currentBaseClass, seenFirstNonRefinementClass, refinementParents)) { + if (!isExcluded && isPotentialMember(sym, flags, currentBaseClass, seenFirstNonRefinementClass, refinementClasses)) { if (shortCircuit(sym)) return false else addMemberIfNew(sym) } else if (excl == DEFERRED) { @@ -110,7 +110,7 @@ trait FindMembers { // the component types T1, ..., Tn and the refinement {R } // // => private members should be included from T1, ... Tn. (scala/bug#7475) - refinementParents :::= currentBaseClass.parentSymbols + refinementClasses ::= currentBaseClass else if (currentBaseClass.isClass) seenFirstNonRefinementClass = true // only inherit privates of refinement parents after this point @@ -130,23 +130,22 @@ trait FindMembers { // Q. When does a potential member fail to be an actual member? // A. if it is subsumed by an member in a subclass. private def isPotentialMember(sym: Symbol, flags: Long, owner: Symbol, - seenFirstNonRefinementClass: Boolean, refinementParents: List[Symbol]): Boolean = { + seenFirstNonRefinementClass: Boolean, refinementClasses: List[Symbol]): Boolean = { // conservatively (performance wise) doing this with flags masks rather than `sym.isPrivate` // to avoid multiple calls to `Symbol#flags`. val isPrivate = (flags & PRIVATE) == PRIVATE val isPrivateLocal = (flags & PrivateLocal) == PrivateLocal // TODO Is the special handling of `private[this]` vs `private` backed up by the spec? - def admitPrivate(sym: Symbol): Boolean = - (selectorClass == owner) || ( - !isPrivateLocal // private[this] only a member from within the selector class. (Optimization only? Does the spec back this up?) - && ( - !seenFirstNonRefinementClass - || refinementParents.contains(owner) - ) + def admitPrivate: Boolean = + // private[this] only a member from within the selector class. + // (Optimization only? Does the spec back this up?) + !isPrivateLocal && ( !seenFirstNonRefinementClass || + refinementClasses.exists(_.info.parents.exists(_.typeSymbol == owner)) ) - (!isPrivate || admitPrivate(sym)) && (sym.name != nme.CONSTRUCTOR || owner == initBaseClasses.head) + (sym.name != nme.CONSTRUCTOR || owner == initBaseClasses.head) && + (!isPrivate || owner == selectorClass || admitPrivate) } // True unless the already-found member of type `memberType` matches the candidate symbol `other`. From 7c9e3724ee6553599a1ce008abfaf49e5a31476d Mon Sep 17 00:00:00 2001 From: Harrison Houghton Date: Thu, 28 Jun 2018 20:59:49 -0400 Subject: [PATCH 040/143] Java annotations are not classes. Previously, `JavaParsers` and `ClassfileParser` would "fix-up" Java annotations to be non-abstract classes with `Annotation` and `StaticAnnotation` as parents. This caused all manner of strangeness and invalid classfiles (see linked tickets) and was surprising, to say the least. Now, the only special dispensation given to Java annotations is that they get a public, no-args class constructor, because that's what it takes to get `typedAnnotation` to be able to look up the type. This means that `new Foo`, where `Foo` is a Java annotation, still compiles (as it does right now, actually). Part of the reason for this commit is to provoke a discussion about how to fix that. Fixes scala/bug#8778. Fixes scala/bug#9400. Fixes scala/bug#9644. --- spec/11-annotations.md | 42 +++++++++--------- .../nsc/backend/jvm/BTypesFromSymbols.scala | 13 ++---- .../scala/tools/nsc/javac/JavaParsers.scala | 11 +++-- .../symtab/classfile/ClassfileParser.scala | 8 ++-- .../tools/nsc/typechecker/Contexts.scala | 10 ++++- .../scala/tools/nsc/typechecker/Namers.scala | 1 + .../scala/tools/nsc/typechecker/Typers.scala | 5 ++- .../reflect/internal/AnnotationInfos.scala | 2 +- .../reflect/internal/ClassfileConstants.scala | 4 +- .../scala/reflect/internal/Symbols.scala | 2 + .../scala/reflect/runtime/JavaMirrors.scala | 4 +- test/files/neg/java-annotation-bad.check | 43 +++++++++++++++++++ test/files/neg/java-annotation-bad/Ann_0.java | 7 +++ test/files/neg/java-annotation-bad/Ann_1.java | 7 +++ .../neg/java-annotation-bad/Test_1.scala | 30 +++++++++++++ test/files/neg/nested-annotation.scala | 2 +- test/files/run/t5699.check | 2 +- test/files/run/t9400.scala | 24 +++++++++++ test/files/run/t9644.scala | 25 +++++++++++ 19 files changed, 190 insertions(+), 52 deletions(-) create mode 100644 test/files/neg/java-annotation-bad.check create mode 100644 test/files/neg/java-annotation-bad/Ann_0.java create mode 100644 test/files/neg/java-annotation-bad/Ann_1.java create mode 100644 test/files/neg/java-annotation-bad/Test_1.scala create mode 100644 test/files/run/t9400.scala create mode 100644 test/files/run/t9644.scala diff --git a/spec/11-annotations.md b/spec/11-annotations.md index 68faee53e657..a26f584ff556 100644 --- a/spec/11-annotations.md +++ b/spec/11-annotations.md @@ -149,26 +149,28 @@ Java platform, the following annotations have a standard meaning. Whenever the static type of an expression matches a specialized variant of a definition, the compiler will instead use the specialized version. See the [specialization sid](http://docs.scala-lang.org/sips/completed/scala-specialization.html) for more details of the implementation. + ## User-defined Annotations -Other annotations may be interpreted by platform- or -application-dependent tools. Class `scala.Annotation` has two -sub-traits which are used to indicate how these annotations are -retained. Instances of an annotation class inheriting from trait -`scala.ClassfileAnnotation` will be stored in the generated class -files. Instances of an annotation class inheriting from trait -`scala.StaticAnnotation` will be visible to the Scala type-checker -in every compilation unit where the annotated symbol is accessed. An -annotation class can inherit from both `scala.ClassfileAnnotation` -and `scala.StaticAnnotation`. If an annotation class inherits from -neither `scala.ClassfileAnnotation` nor -`scala.StaticAnnotation`, its instances are visible only locally -during the compilation run that analyzes them. - -Classes inheriting from `scala.ClassfileAnnotation` may be -subject to further restrictions in order to assure that they can be -mapped to the host environment. In particular, on both the Java and -the .NET platforms, such classes must be toplevel; i.e. they may not -be contained in another class or object. Additionally, on both -Java and .NET, all constructor arguments must be constant expressions. +Other annotations may be interpreted by platform- or application-dependent +tools. The class `scala.annotation.Annotation` is the base class for +user-defined annotations. It has two sub-traits: +- `scala.annotation.StaticAnnotation`: Instances of a subclass of this trait + will be stored in the generated class files, and therefore accessible to + runtime reflection and later compilation runs. +- `scala.annotation.ConstantAnnotation`: Instances of a subclass of this trait + may only have arguments which are + [constant expressions](06-expressions.html#constant-expressions), and are + also stored in the generated class files. +- If an annotation class inherits from neither `scala.ConstantAnnotation` nor + `scala.StaticAnnotation`, its instances are visible only locally during the + compilation run that analyzes them. + +## Host-platform Annotations + +The host platform may define its own annotation format. These annotations do not +extend any of the classes in the `scala.annotation` package, but can generally +be used in the same way as Scala annotations. The host platform may impose +additional restrictions on the expressions which are valid as annotation +arguments. diff --git a/src/compiler/scala/tools/nsc/backend/jvm/BTypesFromSymbols.scala b/src/compiler/scala/tools/nsc/backend/jvm/BTypesFromSymbols.scala index 076bdd6a7dc2..73fdd35bc4f9 100644 --- a/src/compiler/scala/tools/nsc/backend/jvm/BTypesFromSymbols.scala +++ b/src/compiler/scala/tools/nsc/backend/jvm/BTypesFromSymbols.scala @@ -207,16 +207,9 @@ abstract class BTypesFromSymbols[G <: Global](val global: G) extends BTypes { def implementedInterfaces(classSym: Symbol): List[Symbol] = { - // scala/bug#9393: java annotations are interfaces, but the classfile / java source parsers make them look like classes. - def isInterfaceOrTrait(sym: Symbol) = sym.isInterface || sym.isTrait || sym.hasJavaAnnotationFlag - - val classParents = { - val parents = classSym.info.parents - // scala/bug#9393: the classfile / java source parsers add Annotation and StaticAnnotation to the - // parents of a java annotations. undo this for the backend (where we need classfile-level information). - if (classSym.hasJavaAnnotationFlag) parents.filterNot(c => c.typeSymbol == StaticAnnotationClass || c.typeSymbol == AnnotationClass) - else parents - } + def isInterfaceOrTrait(sym: Symbol) = sym.isInterface || sym.isTrait + + val classParents = classSym.info.parents val minimizedParents = if (classSym.isJavaDefined) classParents else erasure.minimizeParents(classSym, classParents) // We keep the superClass when computing minimizeParents to eliminate more interfaces. diff --git a/src/compiler/scala/tools/nsc/javac/JavaParsers.scala b/src/compiler/scala/tools/nsc/javac/JavaParsers.scala index 9bedfa6d5ec7..64c026347880 100644 --- a/src/compiler/scala/tools/nsc/javac/JavaParsers.scala +++ b/src/compiler/scala/tools/nsc/javac/JavaParsers.scala @@ -770,11 +770,7 @@ trait JavaParsers extends ast.parser.ParsersCommon with JavaScanners { val idefs = members.toList ::: (sdefs flatMap forwarders) (sdefs, idefs) } - def annotationParents = List( - gen.scalaAnnotationDot(tpnme.Annotation), - Select(javaLangDot(nme.annotation), tpnme.Annotation), - gen.scalaAnnotationDot(tpnme.StaticAnnotation) - ) + def annotationParents = Select(javaLangDot(nme.annotation), tpnme.Annotation) :: Nil def annotationDecl(mods: Modifiers): List[Tree] = { accept(AT) accept(INTERFACE) @@ -783,7 +779,10 @@ trait JavaParsers extends ast.parser.ParsersCommon with JavaScanners { val (statics, body) = typeBody(AT, name) val templ = makeTemplate(annotationParents, body) addCompanionObject(statics, atPos(pos) { - ClassDef(mods | Flags.JAVA_ANNOTATION, name, List(), templ) + import Flags._ + ClassDef( + mods | JAVA_ANNOTATION | TRAIT | INTERFACE | ABSTRACT, + name, List(), templ) }) } diff --git a/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala b/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala index 574c2b3d98ed..2a0b07beaab3 100644 --- a/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala +++ b/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala @@ -476,11 +476,9 @@ abstract class ClassfileParser { val sflags = jflags.toScalaFlags // includes JAVA def parseParents(): List[Type] = raiseLoaderLevel { - val superType = if (jflags.isAnnotation) { u2; AnnotationClass.tpe } - else pool.getSuperClass(u2).tpe_* + val superType = pool.getSuperClass(u2).tpe_* val ifaceCount = u2 - var ifaces = for (i <- List.range(0, ifaceCount)) yield pool.getSuperClass(u2).tpe_* - if (jflags.isAnnotation) ifaces ::= StaticAnnotationClass.tpe + val ifaces = for (i <- List.range(0, ifaceCount)) yield pool.getSuperClass(u2).tpe_* superType :: ifaces } @@ -518,7 +516,7 @@ abstract class ClassfileParser { val needsConstructor = ( !sawPrivateConstructor && !(instanceScope containsName nme.CONSTRUCTOR) - && (sflags & INTERFACE) == 0 + && ((sflags & INTERFACE) == 0 || (sflags | JAVA_ANNOTATION) != 0) ) if (needsConstructor) instanceScope enter clazz.newClassConstructor(NoPosition) diff --git a/src/compiler/scala/tools/nsc/typechecker/Contexts.scala b/src/compiler/scala/tools/nsc/typechecker/Contexts.scala index a8067a7888ee..dad951cf2c88 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Contexts.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Contexts.scala @@ -270,6 +270,7 @@ trait Contexts { self: Analyzer => def inSecondTry_=(value: Boolean) = this(SecondTry) = value def inReturnExpr = this(ReturnExpr) def inTypeConstructorAllowed = this(TypeConstructorAllowed) + def inAnnotation = this(TypingAnnotation) def defaultModeForTyped: Mode = if (inTypeConstructorAllowed) Mode.NOmode else Mode.EXPRmode @@ -403,6 +404,7 @@ trait Contexts { self: Analyzer => @inline final def withinSuperInit[T](op: => T): T = withMode(enabled = SuperInit)(op) @inline final def withinSecondTry[T](op: => T): T = withMode(enabled = SecondTry)(op) @inline final def withinPatAlternative[T](op: => T): T = withMode(enabled = PatternAlternative)(op) + @inline final def withinAnnotation[T](op: => T): T = withMode(enabled = TypingAnnotation)(op) @inline final def withSuppressDeadArgWarning[T](suppress: Boolean)(op: => T): T = if (suppress) withMode(enabled = SuppressDeadArgWarning)(op) else withMode(disabled = SuppressDeadArgWarning)(op) @@ -1647,6 +1649,11 @@ object ContextMode { /** Were default arguments used? */ final val DiagUsedDefaults: ContextMode = 1 << 18 + /** Are we currently typing the core or args of an annotation? + * When set, Java annotations may be instantiated directly. + */ + final val TypingAnnotation: ContextMode = 1 << 19 + /** TODO: The "sticky modes" are EXPRmode, PATTERNmode, TYPEmode. * To mimic the sticky mode behavior, when captain stickyfingers * comes around we need to propagate those modes but forget the other @@ -1672,7 +1679,8 @@ object ContextMode { SecondTry -> "SecondTry", TypeConstructorAllowed -> "TypeConstructorAllowed", DiagUsedDefaults -> "DiagUsedDefaults", - SuppressDeadArgWarning -> "SuppressDeadArgWarning" + SuppressDeadArgWarning -> "SuppressDeadArgWarning", + TypingAnnotation -> "TypingAnnotation", ) } diff --git a/src/compiler/scala/tools/nsc/typechecker/Namers.scala b/src/compiler/scala/tools/nsc/typechecker/Namers.scala index 0064647a3f9a..2e43ca1374ea 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Namers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Namers.scala @@ -1202,6 +1202,7 @@ trait Namers extends MethodSynthesis { } cda.companionModuleClassNamer = templateNamer } + val classTp = ClassInfoType(parents, decls, clazz) templateNamer.expandMacroAnnotations(templ.body) pluginsTypeSig(classTp, templateNamer.typer, templ, WildcardType) diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala index f8f8d4334b84..cdbe00c25c8f 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala @@ -3740,7 +3740,7 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper /** * Convert an annotation constructor call into an AnnotationInfo. */ - def typedAnnotation(ann: Tree, mode: Mode = EXPRmode): AnnotationInfo = { + def typedAnnotation(ann: Tree, mode: Mode = EXPRmode): AnnotationInfo = context.withinAnnotation { var hasError: Boolean = false val pending = ListBuffer[AbsTypeError]() def ErroneousAnnotation = new ErroneousAnnotation().setOriginal(ann) @@ -4601,7 +4601,8 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper val tp = tpt1.tpe val sym = tp.typeSymbol.initialize - if (sym.isAbstractType || sym.hasAbstractFlag) + if ((sym.isAbstractType || sym.hasAbstractFlag) + && !(sym.isJavaAnnotation && context.inAnnotation)) IsAbstractError(tree, sym) else if (isPrimitiveValueClass(sym)) { NotAMemberError(tpt, TypeTree(tp), nme.CONSTRUCTOR) diff --git a/src/reflect/scala/reflect/internal/AnnotationInfos.scala b/src/reflect/scala/reflect/internal/AnnotationInfos.scala index 9e3d4a935c30..d41903176e8f 100644 --- a/src/reflect/scala/reflect/internal/AnnotationInfos.scala +++ b/src/reflect/scala/reflect/internal/AnnotationInfos.scala @@ -269,7 +269,7 @@ trait AnnotationInfos extends api.Annotations { self: SymbolTable => /** Check whether the type or any of the arguments are erroneous */ def isErroneous = atp.isErroneous || args.exists(_.isErroneous) - def isStatic = symbol isNonBottomSubClass StaticAnnotationClass + final def isStatic = symbol.isStaticAnnotation /** Check whether any of the arguments mention a symbol */ def refsSymbol(sym: Symbol) = hasArgWhich(_.symbol == sym) diff --git a/src/reflect/scala/reflect/internal/ClassfileConstants.scala b/src/reflect/scala/reflect/internal/ClassfileConstants.scala index a4223c1cb500..0f06566bf438 100644 --- a/src/reflect/scala/reflect/internal/ClassfileConstants.scala +++ b/src/reflect/scala/reflect/internal/ClassfileConstants.scala @@ -342,8 +342,8 @@ object ClassfileConstants { case JAVA_ACC_FINAL => FINAL case JAVA_ACC_SYNTHETIC => SYNTHETIC | ARTIFACT // maybe should be just artifact? case JAVA_ACC_STATIC => STATIC - case JAVA_ACC_ABSTRACT => if (isAnnotation) 0L else if (isClass) ABSTRACT else DEFERRED - case JAVA_ACC_INTERFACE => if (isAnnotation) 0L else TRAIT | INTERFACE | ABSTRACT + case JAVA_ACC_ABSTRACT => if (isClass) ABSTRACT else DEFERRED + case JAVA_ACC_INTERFACE => TRAIT | INTERFACE | ABSTRACT case JAVA_ACC_ENUM => JAVA_ENUM case JAVA_ACC_ANNOTATION => JAVA_ANNOTATION case _ => 0L diff --git a/src/reflect/scala/reflect/internal/Symbols.scala b/src/reflect/scala/reflect/internal/Symbols.scala index 834828cc2dd1..e5d2e407cd9c 100644 --- a/src/reflect/scala/reflect/internal/Symbols.scala +++ b/src/reflect/scala/reflect/internal/Symbols.scala @@ -118,6 +118,8 @@ trait Symbols extends api.Symbols { self: SymbolTable => def isJavaEnum: Boolean = hasJavaEnumFlag def isJavaAnnotation: Boolean = hasJavaAnnotationFlag + def isStaticAnnotation: Boolean = + hasJavaAnnotationFlag || isNonBottomSubClass(StaticAnnotationClass) def newNestedSymbol(name: Name, pos: Position, newFlags: Long, isClass: Boolean): Symbol = name match { case n: TermName => newTermSymbol(n, pos, newFlags) diff --git a/src/reflect/scala/reflect/runtime/JavaMirrors.scala b/src/reflect/scala/reflect/runtime/JavaMirrors.scala index 40d959bef599..6f738fa9df97 100644 --- a/src/reflect/scala/reflect/runtime/JavaMirrors.scala +++ b/src/reflect/scala/reflect/runtime/JavaMirrors.scala @@ -760,9 +760,7 @@ private[scala] trait JavaMirrors extends internal.SymbolTable with api.JavaUnive parentsLevel += 1 val jsuperclazz = jclazz.getGenericSuperclass val ifaces = jclazz.getGenericInterfaces.toList map typeToScala - val isAnnotation = JavaAccFlags(jclazz).isAnnotation - if (isAnnotation) AnnotationClass.tpe :: StaticAnnotationClass.tpe :: ifaces - else if (jclazz.isInterface) ObjectTpe :: ifaces // interfaces have Object as superclass in the classfile (see jvm spec), but getGenericSuperclass seems to return null + if (jclazz.isInterface) ObjectTpe :: ifaces // interfaces have Object as superclass in the classfile (see jvm spec), but getGenericSuperclass seems to return null else (if (jsuperclazz == null) AnyTpe else typeToScala(jsuperclazz)) :: ifaces } finally { parentsLevel -= 1 diff --git a/test/files/neg/java-annotation-bad.check b/test/files/neg/java-annotation-bad.check new file mode 100644 index 000000000000..953da743b37f --- /dev/null +++ b/test/files/neg/java-annotation-bad.check @@ -0,0 +1,43 @@ +Test_1.scala:12: error: Java annotation Ann_0 is abstract; cannot be instantiated + val a: Ann_0 = new Ann_0 // nok + ^ +Test_1.scala:13: error: Java annotation Ann_0 is abstract; cannot be instantiated + val b: Ann_0 = new Ann_0(Array()) // nok + ^ +Test_1.scala:14: error: Java annotation Ann_1 is abstract; cannot be instantiated + val c: Ann_1 = new Ann_1 // nok + ^ +Test_1.scala:15: error: Java annotation Ann_1 is abstract; cannot be instantiated + val d: Ann_1 = new Ann_1(Array()) // nok + ^ +Test_1.scala:18: error: type mismatch; + found : ann.Ann_0 + required: scala.annotation.Annotation + val e: Annotation = a // nok + ^ +Test_1.scala:19: error: type mismatch; + found : ann.Ann_1 + required: scala.annotation.Annotation + val f: Annotation = c // nok + ^ +Test_1.scala:20: error: type mismatch; + found : ann.Ann_0 + required: scala.annotation.StaticAnnotation + val g: StaticAnnotation = a // nok + ^ +Test_1.scala:21: error: type mismatch; + found : ann.Ann_1 + required: scala.annotation.StaticAnnotation + val h: StaticAnnotation = c // nok + ^ +Test_1.scala:22: error: type mismatch; + found : ann.Ann_0 + required: scala.annotation.ConstantAnnotation + val i: ConstantAnnotation = a // nok + ^ +Test_1.scala:23: error: type mismatch; + found : ann.Ann_1 + required: scala.annotation.ConstantAnnotation + val j: ConstantAnnotation = c // nok + ^ +10 errors found diff --git a/test/files/neg/java-annotation-bad/Ann_0.java b/test/files/neg/java-annotation-bad/Ann_0.java new file mode 100644 index 000000000000..3e8033edb768 --- /dev/null +++ b/test/files/neg/java-annotation-bad/Ann_0.java @@ -0,0 +1,7 @@ +package ann; + +public @interface Ann_0 { + N[] value(); + + public @interface N {} +} \ No newline at end of file diff --git a/test/files/neg/java-annotation-bad/Ann_1.java b/test/files/neg/java-annotation-bad/Ann_1.java new file mode 100644 index 000000000000..37b87c79deea --- /dev/null +++ b/test/files/neg/java-annotation-bad/Ann_1.java @@ -0,0 +1,7 @@ +package ann; + +public @interface Ann_1 { + N[] value(); + + public @interface N {} +} \ No newline at end of file diff --git a/test/files/neg/java-annotation-bad/Test_1.scala b/test/files/neg/java-annotation-bad/Test_1.scala new file mode 100644 index 000000000000..950c8b6c7b59 --- /dev/null +++ b/test/files/neg/java-annotation-bad/Test_1.scala @@ -0,0 +1,30 @@ +object Test { + import ann._ + + // ok + @Ann_0(Array(new Ann_0.N, new Ann_0.N)) + class A + + // ok + @Ann_1(Array(new Ann_1.N, new Ann_1.N)) + class B + + val a: Ann_0 = new Ann_0 // nok + val b: Ann_0 = new Ann_0(Array()) // nok + val c: Ann_1 = new Ann_1 // nok + val d: Ann_1 = new Ann_1(Array()) // nok + + import scala.annotation._, java.lang.{annotation => jla} + val e: Annotation = a // nok + val f: Annotation = c // nok + val g: StaticAnnotation = a // nok + val h: StaticAnnotation = c // nok + val i: ConstantAnnotation = a // nok + val j: ConstantAnnotation = c // nok + val k: jla.Annotation = a // ok + val l: jla.Annotation = c // ok + + val m = new Ann_0 { val annotationType = classOf[Ann_0] } // ok + val n = new Ann_1 { val annotationType = classOf[Ann_1] } // ok + +} \ No newline at end of file diff --git a/test/files/neg/nested-annotation.scala b/test/files/neg/nested-annotation.scala index 89115344b03e..71bcb7cb064f 100644 --- a/test/files/neg/nested-annotation.scala +++ b/test/files/neg/nested-annotation.scala @@ -1,6 +1,6 @@ import annotation._ -class ComplexAnnotation(val value: Annotation) extends ConstantAnnotation +class ComplexAnnotation(val value: Any) extends ConstantAnnotation class A { // It's hard to induce this error because @ComplexAnnotation(@inline) is a parse diff --git a/test/files/run/t5699.check b/test/files/run/t5699.check index f1a1f6ae97ec..47bcd7767899 100644 --- a/test/files/run/t5699.check +++ b/test/files/run/t5699.check @@ -3,7 +3,7 @@ package { object MyAnnotation extends { def () }; - class MyAnnotation extends scala.annotation.Annotation with _root_.java.lang.annotation.Annotation with scala.annotation.StaticAnnotation { + abstract trait MyAnnotation extends _root_.java.lang.annotation.Annotation { def (); def value(): String } diff --git a/test/files/run/t9400.scala b/test/files/run/t9400.scala new file mode 100644 index 000000000000..8555374d3da1 --- /dev/null +++ b/test/files/run/t9400.scala @@ -0,0 +1,24 @@ + +class Deprecation extends Deprecated { + final val annotationType = classOf[Deprecated] +} + +class Suppression extends SuppressWarnings { + final val annotationType = classOf[SuppressWarnings] + + def value = Array("unchecked") +} + +class Retention(runtime: Boolean) extends java.lang.annotation.Retention { + final val annotationType = classOf[Retention] + + def value = + if (runtime) java.lang.annotation.RetentionPolicy.RUNTIME + else java.lang.annotation.RetentionPolicy.SOURCE +} + +object Test extends App { + new Deprecation + new Suppression + new Retention(true) +} diff --git a/test/files/run/t9644.scala b/test/files/run/t9644.scala new file mode 100644 index 000000000000..822b148f0c13 --- /dev/null +++ b/test/files/run/t9644.scala @@ -0,0 +1,25 @@ +import java.lang.annotation._ + +@Deprecated @Retention(RetentionPolicy.RUNTIME) class Foo + +object Test extends App { + classOf[Foo].getAnnotation(classOf[Deprecated]) + + assert(classOf[Foo].getAnnotation(classOf[Retention]).value() == RetentionPolicy.RUNTIME) + + import reflect.runtime.universe._ + + val List(d, r) = symbolOf[Foo].annotations + + d.tree match { + case Apply(Select(New(tpt), _), Nil) => + assert (tpt.tpe.typeSymbol == symbolOf[Deprecated], tpt.tpe.typeSymbol) + } + + val RetentionPolicy_RUNTIME = symbolOf[RetentionPolicy].companion.info.decl(TermName("RUNTIME")) + r.tree match { + case Apply(Select(New(tpt), _), List(NamedArg(Ident(TermName("value")), Literal(Constant(RetentionPolicy_RUNTIME))))) => + assert (tpt.tpe.typeSymbol == symbolOf[Retention], tpt.tpe.typeSymbol) + } + +} \ No newline at end of file From d9cedb599c42877ef8c39bd3f0a1cf7633218559 Mon Sep 17 00:00:00 2001 From: Som Snytt Date: Tue, 3 Jul 2018 06:16:10 -0700 Subject: [PATCH 041/143] [nomerge] Backport test --- test/files/run/t10956.check | 39 +++++++++++++++++++++++++++++++++++++ test/files/run/t10956.scala | 17 ++++++++++++++++ 2 files changed, 56 insertions(+) create mode 100644 test/files/run/t10956.check create mode 100644 test/files/run/t10956.scala diff --git a/test/files/run/t10956.check b/test/files/run/t10956.check new file mode 100644 index 000000000000..e52daede735f --- /dev/null +++ b/test/files/run/t10956.check @@ -0,0 +1,39 @@ + +scala> :paste < EOF +// Entering paste mode (EOF to finish) + +import java.awt.AWTError,java.awt.Dialog,java.awt.KeyEventDispatcher,java.awt.Robot,java.awt.AWTEvent,java.awt.Dimension,java.awt.KeyEventPostProcessor,java.awt.ScrollPane,java.awt.AWTEventMulticaster,java.awt.DisplayMode,java.awt.KeyboardFocusManager,java.awt.ScrollPaneAdjustable,java.awt.AWTException,java.awt.Event,java.awt.Label,java.awt.Scrollbar,java.awt.AWTKeyStroke,java.awt.EventQueue,java.awt.LayoutManager,java.awt.SecondaryLoop,java.awt.AWTPermission,java.awt.FileDialog,java.awt.LayoutManager2,java.awt.Shape,java.awt.ActiveEvent,java.awt.FlowLayout,java.awt.LinearGradientPaint,java.awt.SplashScreen,java.awt.Adjustable,java.awt.FocusTraversalPolicy,java.awt.List,java.awt.Stroke,java.awt.AlphaComposite,java.awt.Font,java.awt.MediaTracker,java.awt.SystemColor,java.awt.BasicStroke,java.awt.FontFormatException,java.awt.Menu,java.awt.SystemTray,java.awt.BorderLayout,java.awt.FontMetrics,java.awt.MenuBar,java.awt.TextArea,java.awt.BufferCapabilities,java.awt.Frame,java.awt.MenuComponent,java.awt.TextComponent,java.awt.Button,java.awt.GradientPaint,java.awt.MenuContainer,java.awt.TextField,java.awt.Canvas,java.awt.Graphics,java.awt.MenuItem,java.awt.TexturePaint,java.awt.CardLayout,java.awt.Graphics2D,java.awt.MenuShortcut,java.awt.Toolkit,java.awt.Checkbox,java.awt.GraphicsConfigTemplate,java.awt.MouseInfo,java.awt.Transparency,java.awt.CheckboxGroup,java.awt.GraphicsConfiguration,java.awt.MultipleGradientPaint,java.awt.TrayIcon,java.awt.CheckboxMenuItem,java.awt.GraphicsDevice,java.awt.PageAttributes,java.awt.Window,java.awt.Choice,java.awt.GraphicsEnvironment,java.awt.Paint,java.awt.color,java.awt.Color,java.awt.GridBagConstraints,java.awt.PaintContext,java.awt.datatransfer,java.awt.Component,java.awt.GridBagLayout,java.awt.Panel,java.awt.dnd,java.awt.ComponentOrientation,java.awt.GridBagLayoutInfo,java.awt.Point,java.awt.event,java.awt.Composite,java.awt.GridLayout,java.awt.PointerInfo,java.awt.font,java.awt.CompositeContext,java.awt.HeadlessException,java.awt.Polygon,java.awt.geom,java.awt.Container,java.awt.IllegalComponentStateException,java.awt.PopupMenu,java.awt.im,java.awt.ContainerOrderFocusTraversalPolicy,java.awt.Image,java.awt.PrintGraphics,java.awt.image,java.awt.Cursor,java.awt.ImageCapabilities,java.awt.PrintJob,java.awt.peer,java.awt.DefaultFocusTraversalPolicy,java.awt.Insets,java.awt.RadialGradientPaint,java.awt.print,java.awt.DefaultKeyboardFocusManager,java.awt.ItemSelectable,java.awt.Rectangle,java.awt.Desktop,java.awt.JobAttributes,java.awt.RenderingHints +EOF + +// Exiting paste mode, now interpreting. + +import java.awt.AWTError +import java.awt.Dialog +import java.awt.KeyEventDispatcher +import java.awt.Robot +import java.awt.AWTEvent +import java.awt.Dimension +import java.awt.KeyEventPostProcessor +import java.awt.ScrollPane +import java.awt.AWTEventMulticaster +import java.awt.DisplayMode +import java.awt.KeyboardFocusManager +import java.awt.ScrollPaneAdjustable +import java.awt.AWTException +import java.awt.Event +import java.awt.Label +import java.awt.Scrollbar +import java.awt.AWTKeyStroke +import java.awt.EventQueue +import java.awt.LayoutManager +import java.awt.SecondaryLoop +import java.awt.AWTPermission +import java.awt.FileDialog +import java.awt.LayoutManager2 +import java.awt.Shape +import java.awt.ActiveEvent +import java.awt.FlowLayout +import java.awt.LinearGradientPaint +import java.awt.Splash... + +scala> :quit diff --git a/test/files/run/t10956.scala b/test/files/run/t10956.scala new file mode 100644 index 000000000000..88377dde4ee6 --- /dev/null +++ b/test/files/run/t10956.scala @@ -0,0 +1,17 @@ + +import scala.tools.partest.ReplTest +import scala.tools.nsc.Settings + + +/* + * Huge import clause resulted in long "result string" construction. + * That would blow the stack on typecheck or refchecks. + */ +object Test extends ReplTest { + def code = + """ +:paste < EOF +import java.awt.AWTError,java.awt.Dialog,java.awt.KeyEventDispatcher,java.awt.Robot,java.awt.AWTEvent,java.awt.Dimension,java.awt.KeyEventPostProcessor,java.awt.ScrollPane,java.awt.AWTEventMulticaster,java.awt.DisplayMode,java.awt.KeyboardFocusManager,java.awt.ScrollPaneAdjustable,java.awt.AWTException,java.awt.Event,java.awt.Label,java.awt.Scrollbar,java.awt.AWTKeyStroke,java.awt.EventQueue,java.awt.LayoutManager,java.awt.SecondaryLoop,java.awt.AWTPermission,java.awt.FileDialog,java.awt.LayoutManager2,java.awt.Shape,java.awt.ActiveEvent,java.awt.FlowLayout,java.awt.LinearGradientPaint,java.awt.SplashScreen,java.awt.Adjustable,java.awt.FocusTraversalPolicy,java.awt.List,java.awt.Stroke,java.awt.AlphaComposite,java.awt.Font,java.awt.MediaTracker,java.awt.SystemColor,java.awt.BasicStroke,java.awt.FontFormatException,java.awt.Menu,java.awt.SystemTray,java.awt.BorderLayout,java.awt.FontMetrics,java.awt.MenuBar,java.awt.TextArea,java.awt.BufferCapabilities,java.awt.Frame,java.awt.MenuComponent,java.awt.TextComponent,java.awt.Button,java.awt.GradientPaint,java.awt.MenuContainer,java.awt.TextField,java.awt.Canvas,java.awt.Graphics,java.awt.MenuItem,java.awt.TexturePaint,java.awt.CardLayout,java.awt.Graphics2D,java.awt.MenuShortcut,java.awt.Toolkit,java.awt.Checkbox,java.awt.GraphicsConfigTemplate,java.awt.MouseInfo,java.awt.Transparency,java.awt.CheckboxGroup,java.awt.GraphicsConfiguration,java.awt.MultipleGradientPaint,java.awt.TrayIcon,java.awt.CheckboxMenuItem,java.awt.GraphicsDevice,java.awt.PageAttributes,java.awt.Window,java.awt.Choice,java.awt.GraphicsEnvironment,java.awt.Paint,java.awt.color,java.awt.Color,java.awt.GridBagConstraints,java.awt.PaintContext,java.awt.datatransfer,java.awt.Component,java.awt.GridBagLayout,java.awt.Panel,java.awt.dnd,java.awt.ComponentOrientation,java.awt.GridBagLayoutInfo,java.awt.Point,java.awt.event,java.awt.Composite,java.awt.GridLayout,java.awt.PointerInfo,java.awt.font,java.awt.CompositeContext,java.awt.HeadlessException,java.awt.Polygon,java.awt.geom,java.awt.Container,java.awt.IllegalComponentStateException,java.awt.PopupMenu,java.awt.im,java.awt.ContainerOrderFocusTraversalPolicy,java.awt.Image,java.awt.PrintGraphics,java.awt.image,java.awt.Cursor,java.awt.ImageCapabilities,java.awt.PrintJob,java.awt.peer,java.awt.DefaultFocusTraversalPolicy,java.awt.Insets,java.awt.RadialGradientPaint,java.awt.print,java.awt.DefaultKeyboardFocusManager,java.awt.ItemSelectable,java.awt.Rectangle,java.awt.Desktop,java.awt.JobAttributes,java.awt.RenderingHints +EOF + """ +} From 393a2661d6648f62711b0ffa883f7c0c214f3bc6 Mon Sep 17 00:00:00 2001 From: naldo Date: Tue, 3 Jul 2018 17:17:54 +0200 Subject: [PATCH 042/143] Fix error in HashMap.HashMapCollision1.merge0 --- src/library/scala/collection/immutable/HashMap.scala | 2 +- .../scala/collection/immutable/HashMapTest.scala | 12 +++++++++++- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/src/library/scala/collection/immutable/HashMap.scala b/src/library/scala/collection/immutable/HashMap.scala index c3217385d067..79c4ac2d14b8 100644 --- a/src/library/scala/collection/immutable/HashMap.scala +++ b/src/library/scala/collection/immutable/HashMap.scala @@ -297,7 +297,7 @@ object HashMap extends ImmutableMapFactory[HashMap] with BitOperations.Int { protected override def merge0[B1 >: B](that: HashMap[A, B1], level: Int, merger: Merger[A, B1]): HashMap[A, B1] = { // this can be made more efficient by passing the entire ListMap at once var m = that - for (p <- kvs) m = m.updated0(p._1, this.hash, level, p._2, p, merger) + for (p <- kvs) m = m.updated0(p._1, this.hash, level, p._2, p, merger.invert) m } } diff --git a/test/junit/scala/collection/immutable/HashMapTest.scala b/test/junit/scala/collection/immutable/HashMapTest.scala index a970786455e4..8b036f26ac4c 100644 --- a/test/junit/scala/collection/immutable/HashMapTest.scala +++ b/test/junit/scala/collection/immutable/HashMapTest.scala @@ -45,4 +45,14 @@ class HashMapTest { } assertEquals(expected, mergedWithMergeFunction) } -} \ No newline at end of file + + @Test + def canMergeHashMapCollision1WithCorrectMerege() { + case class A(k: Int) { override def hashCode = 0 } + val m1 = HashMap(A(0) -> 2, A(1) -> 2) + val m2 = HashMap(A(0) -> 1, A(1) -> 1) + val merged = m1.merged(m2) { case ((k, l), (_, r)) => k -> (l - r) } + val expected = HashMap(A(0) -> 1, A(1) -> 1) + assertEquals(merged, expected) + } +} From 07b73588a6b8e1283818f4e662e59b3fc290c357 Mon Sep 17 00:00:00 2001 From: Matthew de Detrich Date: Wed, 4 Jul 2018 00:10:24 +0200 Subject: [PATCH 043/143] Rename LinkedMap to SeqMap --- .../scala/collection/immutable/ListMap.scala | 2 +- .../{LinkedMap.scala => SeqMap.scala} | 96 +++++++++---------- .../collection/immutable/VectorMap.scala | 2 +- ...pBenchmark.scala => SeqMapBenchmark.scala} | 6 +- .../{LinkedMap.scala => SeqMap.scala} | 12 +-- 5 files changed, 59 insertions(+), 59 deletions(-) rename src/library/scala/collection/immutable/{LinkedMap.scala => SeqMap.scala} (62%) rename test/benchmarks/src/main/scala/scala/collection/immutable/{LinkedMapBenchmark.scala => SeqMapBenchmark.scala} (82%) rename test/scalacheck/{LinkedMap.scala => SeqMap.scala} (67%) diff --git a/src/library/scala/collection/immutable/ListMap.scala b/src/library/scala/collection/immutable/ListMap.scala index 3d11a58f604a..e58f547b7dd3 100644 --- a/src/library/scala/collection/immutable/ListMap.scala +++ b/src/library/scala/collection/immutable/ListMap.scala @@ -43,7 +43,7 @@ import scala.collection.mutable.{Builder, ImmutableBuilder} */ sealed class ListMap[K, +V] extends AbstractMap[K, V] - with LinkedMap[K, V] + with SeqMap[K, V] with MapOps[K, V, ListMap, ListMap[K, V]] with StrictOptimizedIterableOps[(K, V), Iterable, ListMap[K, V]] { diff --git a/src/library/scala/collection/immutable/LinkedMap.scala b/src/library/scala/collection/immutable/SeqMap.scala similarity index 62% rename from src/library/scala/collection/immutable/LinkedMap.scala rename to src/library/scala/collection/immutable/SeqMap.scala index ccd82bca04fb..259f8e58988d 100644 --- a/src/library/scala/collection/immutable/LinkedMap.scala +++ b/src/library/scala/collection/immutable/SeqMap.scala @@ -8,9 +8,9 @@ import scala.collection.mutable.{Builder, ImmutableBuilder} /** * A generic trait for ordered immutable maps. Concrete classes have to provide - * functionality for the abstract methods in `LinkedMap`. + * functionality for the abstract methods in `SeqMap`. * - * Note that when checking for equality [[LinkedMap]] does not take into account + * Note that when checking for equality [[SeqMap]] does not take into account * ordering. * * @tparam K the type of the keys contained in this linked map. @@ -20,26 +20,26 @@ import scala.collection.mutable.{Builder, ImmutableBuilder} * @version 2.13 * @since 2.13 * @define coll immutable linked map - * @define Coll `immutable.LinkedMap` + * @define Coll `immutable.SeqMap` */ -trait LinkedMap[K, +V] +trait SeqMap[K, +V] extends AbstractMap[K, V] - with MapOps[K, V, LinkedMap, LinkedMap[K, V]] + with MapOps[K, V, SeqMap, SeqMap[K, V]] -object LinkedMap extends MapFactory[LinkedMap] { - def empty[K, V]: LinkedMap[K, V] = EmptyLinkedMap.asInstanceOf[LinkedMap[K, V]] +object SeqMap extends MapFactory[SeqMap] { + def empty[K, V]: SeqMap[K, V] = EmptyLinkedMap.asInstanceOf[SeqMap[K, V]] - def from[K, V](it: collection.IterableOnce[(K, V)]): LinkedMap[K, V] = + def from[K, V](it: collection.IterableOnce[(K, V)]): SeqMap[K, V] = it match { - case vm: LinkedMap[K, V] => vm + case sm: SeqMap[K, V] => sm case _ => (newBuilder[K, V] ++= it).result() } - def newBuilder[K, V]: Builder[(K, V), LinkedMap[K, V]] = VectorMap.newBuilder + def newBuilder[K, V]: Builder[(K, V), SeqMap[K, V]] = VectorMap.newBuilder @SerialVersionUID(3L) - private object EmptyLinkedMap extends LinkedMap[Any, Nothing] { + private object EmptyLinkedMap extends SeqMap[Any, Nothing] { override def size: Int = 0 override def knownSize: Int = 0 override def apply(key: Any) = throw new NoSuchElementException("key not found: " + key) @@ -47,12 +47,12 @@ object LinkedMap extends MapFactory[LinkedMap] { def get(key: Any): Option[Nothing] = None override def getOrElse [V1](key: Any, default: => V1): V1 = default def iterator: Iterator[(Any, Nothing)] = Iterator.empty - def updated [V1] (key: Any, value: V1): LinkedMap[Any, V1] = new LinkedMap1(key, value) - def remove(key: Any): LinkedMap[Any, Nothing] = this + def updated [V1] (key: Any, value: V1): SeqMap[Any, V1] = new SeqMap1(key, value) + def remove(key: Any): SeqMap[Any, Nothing] = this } @SerialVersionUID(3L) - final class LinkedMap1[K, +V](key1: K, value1: V) extends LinkedMap[K,V] with Serializable { + final class SeqMap1[K, +V](key1: K, value1: V) extends SeqMap[K,V] with Serializable { override def size: Int = 1 override def knownSize: Int = 1 override def apply(key: K) = if (key == key1) value1 else throw new NoSuchElementException("key not found: " + key) @@ -62,18 +62,18 @@ object LinkedMap extends MapFactory[LinkedMap] { override def getOrElse [V1 >: V](key: K, default: => V1): V1 = if (key == key1) value1 else default def iterator = Iterator.single((key1, value1)) - def updated[V1 >: V](key: K, value: V1): LinkedMap[K, V1] = - if (key == key1) new LinkedMap1(key1, value) - else new LinkedMap2(key1, value1, key, value) - def remove(key: K): LinkedMap[K, V] = - if (key == key1) LinkedMap.empty else this + def updated[V1 >: V](key: K, value: V1): SeqMap[K, V1] = + if (key == key1) new SeqMap1(key1, value) + else new SeqMap2(key1, value1, key, value) + def remove(key: K): SeqMap[K, V] = + if (key == key1) SeqMap.empty else this override def foreach[U](f: ((K, V)) => U): Unit = { f((key1, value1)) } } @SerialVersionUID(3L) - final class LinkedMap2[K, +V](key1: K, value1: V, key2: K, value2: V) extends LinkedMap[K,V] with Serializable { + final class SeqMap2[K, +V](key1: K, value1: V, key2: K, value2: V) extends SeqMap[K,V] with Serializable { override def size: Int = 2 override def knownSize: Int = 2 override def apply(key: K) = @@ -90,13 +90,13 @@ object LinkedMap extends MapFactory[LinkedMap] { else if (key == key2) value2 else default def iterator = ((key1, value1) :: (key2, value2) :: Nil).iterator - def updated[V1 >: V](key: K, value: V1): LinkedMap[K, V1] = - if (key == key1) new LinkedMap2(key1, value, key2, value2) - else if (key == key2) new LinkedMap2(key1, value1, key2, value) - else new LinkedMap3(key1, value1, key2, value2, key, value) - def remove(key: K): LinkedMap[K, V] = - if (key == key1) new LinkedMap1(key2, value2) - else if (key == key2) new LinkedMap1(key1, value1) + def updated[V1 >: V](key: K, value: V1): SeqMap[K, V1] = + if (key == key1) new SeqMap2(key1, value, key2, value2) + else if (key == key2) new SeqMap2(key1, value1, key2, value) + else new SeqMap3(key1, value1, key2, value2, key, value) + def remove(key: K): SeqMap[K, V] = + if (key == key1) new SeqMap1(key2, value2) + else if (key == key2) new SeqMap1(key1, value1) else this override def foreach[U](f: ((K, V)) => U): Unit = { f((key1, value1)); f((key2, value2)) @@ -104,7 +104,7 @@ object LinkedMap extends MapFactory[LinkedMap] { } @SerialVersionUID(3L) - class LinkedMap3[K, +V](key1: K, value1: V, key2: K, value2: V, key3: K, value3: V) extends LinkedMap[K,V] with Serializable { + class SeqMap3[K, +V](key1: K, value1: V, key2: K, value2: V, key3: K, value3: V) extends SeqMap[K,V] with Serializable { override def size: Int = 3 override def knownSize: Int = 3 override def apply(key: K) = @@ -124,15 +124,15 @@ object LinkedMap extends MapFactory[LinkedMap] { else if (key == key3) value3 else default def iterator = ((key1, value1) :: (key2, value2) :: (key3, value3) :: Nil).iterator - def updated[V1 >: V](key: K, value: V1): LinkedMap[K, V1] = - if (key == key1) new LinkedMap3(key1, value, key2, value2, key3, value3) - else if (key == key2) new LinkedMap3(key1, value1, key2, value, key3, value3) - else if (key == key3) new LinkedMap3(key1, value1, key2, value2, key3, value) - else new LinkedMap4(key1, value1, key2, value2, key3, value3, key, value) - def remove(key: K): LinkedMap[K, V] = - if (key == key1) new LinkedMap2(key2, value2, key3, value3) - else if (key == key2) new LinkedMap2(key1, value1, key3, value3) - else if (key == key3) new LinkedMap2(key1, value1, key2, value2) + def updated[V1 >: V](key: K, value: V1): SeqMap[K, V1] = + if (key == key1) new SeqMap3(key1, value, key2, value2, key3, value3) + else if (key == key2) new SeqMap3(key1, value1, key2, value, key3, value3) + else if (key == key3) new SeqMap3(key1, value1, key2, value2, key3, value) + else new SeqMap4(key1, value1, key2, value2, key3, value3, key, value) + def remove(key: K): SeqMap[K, V] = + if (key == key1) new SeqMap2(key2, value2, key3, value3) + else if (key == key2) new SeqMap2(key1, value1, key3, value3) + else if (key == key3) new SeqMap2(key1, value1, key2, value2) else this override def foreach[U](f: ((K, V)) => U): Unit = { f((key1, value1)); f((key2, value2)); f((key3, value3)) @@ -140,7 +140,7 @@ object LinkedMap extends MapFactory[LinkedMap] { } @SerialVersionUID(3L) - final class LinkedMap4[K, +V](key1: K, value1: V, key2: K, value2: V, key3: K, value3: V, key4: K, value4: V) extends LinkedMap[K,V] with Serializable { + final class SeqMap4[K, +V](key1: K, value1: V, key2: K, value2: V, key3: K, value3: V, key4: K, value4: V) extends SeqMap[K,V] with Serializable { override def size: Int = 4 override def knownSize: Int = 4 override def apply(key: K) = @@ -163,11 +163,11 @@ object LinkedMap extends MapFactory[LinkedMap] { else if (key == key4) value4 else default def iterator = ((key1, value1) :: (key2, value2) :: (key3, value3) :: (key4, value4) :: Nil).iterator - def updated[V1 >: V](key: K, value: V1): LinkedMap[K, V1] = - if (key == key1) new LinkedMap4(key1, value, key2, value2, key3, value3, key4, value4) - else if (key == key2) new LinkedMap4(key1, value1, key2, value, key3, value3, key4, value4) - else if (key == key3) new LinkedMap4(key1, value1, key2, value2, key3, value, key4, value4) - else if (key == key4) new LinkedMap4(key1, value1, key2, value2, key3, value3, key4, value) + def updated[V1 >: V](key: K, value: V1): SeqMap[K, V1] = + if (key == key1) new SeqMap4(key1, value, key2, value2, key3, value3, key4, value4) + else if (key == key2) new SeqMap4(key1, value1, key2, value, key3, value3, key4, value4) + else if (key == key3) new SeqMap4(key1, value1, key2, value2, key3, value, key4, value4) + else if (key == key4) new SeqMap4(key1, value1, key2, value2, key3, value3, key4, value) else { // Directly create the elements for performance reasons val fields = Vector(key1, key2, key3, key4, key) @@ -189,11 +189,11 @@ object LinkedMap extends MapFactory[LinkedMap] { ) new VectorMap(fields, underlying) } - def remove(key: K): LinkedMap[K, V] = - if (key == key1) new LinkedMap3(key2, value2, key3, value3, key4, value4) - else if (key == key2) new LinkedMap3(key1, value1, key3, value3, key4, value4) - else if (key == key3) new LinkedMap3(key1, value1, key2, value2, key4, value4) - else if (key == key4) new LinkedMap3(key1, value1, key2, value2, key3, value3) + def remove(key: K): SeqMap[K, V] = + if (key == key1) new SeqMap3(key2, value2, key3, value3, key4, value4) + else if (key == key2) new SeqMap3(key1, value1, key3, value3, key4, value4) + else if (key == key3) new SeqMap3(key1, value1, key2, value2, key4, value4) + else if (key == key4) new SeqMap3(key1, value1, key2, value2, key3, value3) else this override def foreach[U](f: ((K, V)) => U): Unit = { f((key1, value1)); f((key2, value2)); f((key3, value3)); f((key4, value4)) diff --git a/src/library/scala/collection/immutable/VectorMap.scala b/src/library/scala/collection/immutable/VectorMap.scala index c3993e1446c7..9075621a75a8 100644 --- a/src/library/scala/collection/immutable/VectorMap.scala +++ b/src/library/scala/collection/immutable/VectorMap.scala @@ -26,7 +26,7 @@ final class VectorMap[K, +V] private[immutable] ( private val fields: Vector[K], private val underlying: Map[K, (Int, V)]) extends AbstractMap[K, V] - with LinkedMap[K, V] + with SeqMap[K, V] with MapOps[K, V, VectorMap, VectorMap[K, V]] with StrictOptimizedIterableOps[(K, V), Iterable, VectorMap[K, V]] { diff --git a/test/benchmarks/src/main/scala/scala/collection/immutable/LinkedMapBenchmark.scala b/test/benchmarks/src/main/scala/scala/collection/immutable/SeqMapBenchmark.scala similarity index 82% rename from test/benchmarks/src/main/scala/scala/collection/immutable/LinkedMapBenchmark.scala rename to test/benchmarks/src/main/scala/scala/collection/immutable/SeqMapBenchmark.scala index 4c7f495c4e1c..58e724e848c0 100644 --- a/test/benchmarks/src/main/scala/scala/collection/immutable/LinkedMapBenchmark.scala +++ b/test/benchmarks/src/main/scala/scala/collection/immutable/SeqMapBenchmark.scala @@ -12,13 +12,13 @@ import org.openjdk.jmh.infra._ @Measurement(iterations = 10) @OutputTimeUnit(TimeUnit.NANOSECONDS) @State(Scope.Benchmark) -class LinkedMapBenchmark { +class SeqMapBenchmark { - var base: LinkedMap[String,String] = _ + var base: SeqMap[String,String] = _ @Setup(Level.Trial) def initKeys(): Unit = { - base = LinkedMap("a" -> "a", "b" -> "b", "c" -> "c", "d" -> "d") + base = SeqMap("a" -> "a", "b" -> "b", "c" -> "c", "d" -> "d") } // immutable map is implemented as EmptyMap -> Map1 -> Map2 -> Map3 -> Map4 -> Hashmap diff --git a/test/scalacheck/LinkedMap.scala b/test/scalacheck/SeqMap.scala similarity index 67% rename from test/scalacheck/LinkedMap.scala rename to test/scalacheck/SeqMap.scala index 55283bb8e1bd..08cab9f690c3 100644 --- a/test/scalacheck/LinkedMap.scala +++ b/test/scalacheck/SeqMap.scala @@ -1,4 +1,4 @@ -import scala.collection.immutable.LinkedMap +import scala.collection.immutable.SeqMap import org.scalacheck._ import Arbitrary.arbitrary @@ -7,12 +7,12 @@ import Gen._ import scala.collection.mutable.ListBuffer -object LinkedMapTest extends Properties("LinkedMap") { +object SeqMapTest extends Properties("LinkedMap") { property("ordering") = forAll { (m: Map[Int, Int]) => val list = m.toList - val lm = LinkedMap.from(list) - val iter = lm.iterator + val sm = SeqMap.from(list) + val iter = sm.iterator iter.toList == list } @@ -21,7 +21,7 @@ object LinkedMapTest extends Properties("LinkedMap") { val (m1, m2) = m.splitAt(m.size / 2) val first = m1.toList val second = m2.toList - (LinkedMap.from(first) ++ second).iterator.toList == first ++ second + (SeqMap.from(first) ++ second).iterator.toList == first ++ second } property("ordering on withDefault") = forAll(arbitrary[Map[Int,Int]] suchThat (_.size > 1)) @@ -29,6 +29,6 @@ object LinkedMapTest extends Properties("LinkedMap") { val (m1, m2) = m.splitAt(m.size / 2) val first = m1.toList val second = m2.toList - (LinkedMap.from(first).withDefaultValue(1) ++ second).iterator.toList == first ++ second + (SeqMap.from(first).withDefaultValue(1) ++ second).iterator.toList == first ++ second } } From debe9bb5a1a3966f02681a3d1c202e735d6dbb71 Mon Sep 17 00:00:00 2001 From: Matthew de Detrich Date: Thu, 5 Jul 2018 19:45:52 +0200 Subject: [PATCH 044/143] Add mutable.SeqMap plus make LinkedHashMap extend it --- .../scala/collection/immutable/SeqMap.scala | 2 +- .../collection/mutable/LinkedHashMap.scala | 1 + .../scala/collection/mutable/SeqMap.scala | 27 +++++++++++++++++++ 3 files changed, 29 insertions(+), 1 deletion(-) create mode 100644 src/library/scala/collection/mutable/SeqMap.scala diff --git a/src/library/scala/collection/immutable/SeqMap.scala b/src/library/scala/collection/immutable/SeqMap.scala index 259f8e58988d..b0432baa7ca1 100644 --- a/src/library/scala/collection/immutable/SeqMap.scala +++ b/src/library/scala/collection/immutable/SeqMap.scala @@ -19,7 +19,7 @@ import scala.collection.mutable.{Builder, ImmutableBuilder} * @author Matthew de Detrich * @version 2.13 * @since 2.13 - * @define coll immutable linked map + * @define coll immutable seq map * @define Coll `immutable.SeqMap` */ diff --git a/src/library/scala/collection/mutable/LinkedHashMap.scala b/src/library/scala/collection/mutable/LinkedHashMap.scala index d19acc86d083..2337d553e2fa 100644 --- a/src/library/scala/collection/mutable/LinkedHashMap.scala +++ b/src/library/scala/collection/mutable/LinkedHashMap.scala @@ -46,6 +46,7 @@ object LinkedHashMap extends MapFactory[LinkedHashMap] { */ class LinkedHashMap[K, V] extends AbstractMap[K, V] + with SeqMap[K, V] with MapOps[K, V, LinkedHashMap, LinkedHashMap[K, V]] with StrictOptimizedIterableOps[(K, V), Iterable, LinkedHashMap[K, V]] { diff --git a/src/library/scala/collection/mutable/SeqMap.scala b/src/library/scala/collection/mutable/SeqMap.scala new file mode 100644 index 000000000000..60db95e07907 --- /dev/null +++ b/src/library/scala/collection/mutable/SeqMap.scala @@ -0,0 +1,27 @@ +package scala +package collection +package mutable + +import java.io.{ObjectInputStream, ObjectOutputStream} + +import scala.collection.mutable.{Builder, ImmutableBuilder} + +/** + * A generic trait for ordered mutable maps. Concrete classes have to provide + * functionality for the abstract methods in `SeqMap`. + * + * Note that when checking for equality [[SeqMap]] does not take into account + * ordering. + * + * @tparam K the type of the keys contained in this linked map. + * @tparam V the type of the values associated with the keys in this linked map. + * + * @author Matthew de Detrich + * @version 2.13 + * @since 2.13 + * @define coll mutable Seq map + * @define Coll `mutable.SeqMap` + */ + +trait SeqMap[K, V] extends AbstractMap[K, V] + with MapOps[K, V, SeqMap, SeqMap[K, V]] From b1f8f7c567c4d696a5c294f42c6d46762a8b8a0a Mon Sep 17 00:00:00 2001 From: Matthew de Detrich Date: Fri, 6 Jul 2018 20:44:33 +0200 Subject: [PATCH 045/143] Add delegate for mutable.SeqMap to LinkedHashMap --- src/library/scala/collection/mutable/SeqMap.scala | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/library/scala/collection/mutable/SeqMap.scala b/src/library/scala/collection/mutable/SeqMap.scala index 60db95e07907..c6b95da45b9b 100644 --- a/src/library/scala/collection/mutable/SeqMap.scala +++ b/src/library/scala/collection/mutable/SeqMap.scala @@ -2,10 +2,6 @@ package scala package collection package mutable -import java.io.{ObjectInputStream, ObjectOutputStream} - -import scala.collection.mutable.{Builder, ImmutableBuilder} - /** * A generic trait for ordered mutable maps. Concrete classes have to provide * functionality for the abstract methods in `SeqMap`. @@ -25,3 +21,5 @@ import scala.collection.mutable.{Builder, ImmutableBuilder} trait SeqMap[K, V] extends AbstractMap[K, V] with MapOps[K, V, SeqMap, SeqMap[K, V]] + +object SeqMap extends MapFactory.Delegate[SeqMap](LinkedHashMap) From 9870b4e7032b6bedce213a1a16ba45c140334abc Mon Sep 17 00:00:00 2001 From: Jason Zaugg Date: Mon, 9 Jul 2018 11:10:58 +1000 Subject: [PATCH 046/143] Restrict List.corresponds override to LinearSeq arguments --- .../scala/collection/immutable/List.scala | 23 +++++++++++-------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/src/library/scala/collection/immutable/List.scala b/src/library/scala/collection/immutable/List.scala index 179604c5c008..e75a2dac6f15 100644 --- a/src/library/scala/collection/immutable/List.scala +++ b/src/library/scala/collection/immutable/List.scala @@ -381,16 +381,19 @@ sealed abstract class List[+A] None } - override def corresponds[B](that: collection.Seq[B])(p: (A, B) => Boolean): Boolean = { - var i = this - var j = that - while (!(i.isEmpty || j.isEmpty)) { - if (!p(i.head, j.head)) - return false - i = i.tail - j = j.tail - } - i.isEmpty && j.isEmpty + override def corresponds[B](that: collection.Seq[B])(p: (A, B) => Boolean): Boolean = that match { + case that: LinearSeq[B] => + var i = this + var j = that + while (!(i.isEmpty || j.isEmpty)) { + if (!p(i.head, j.head)) + return false + i = i.tail + j = j.tail + } + i.isEmpty && j.isEmpty + case _ => + super.corresponds(that)(p) } override protected[this] def className = "List" From e6eafcd3b6d0f15983a2661919c83abc620c197a Mon Sep 17 00:00:00 2001 From: Jason Zaugg Date: Mon, 9 Jul 2018 11:15:30 +1000 Subject: [PATCH 047/143] Fix Patched.knownSize, and exploit it in Patched.isEmpty --- src/library/scala/collection/View.scala | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/library/scala/collection/View.scala b/src/library/scala/collection/View.scala index 5f15b15948e7..c3ce9a59964d 100644 --- a/src/library/scala/collection/View.scala +++ b/src/library/scala/collection/View.scala @@ -309,8 +309,8 @@ object View extends IterableFactory[View] { @SerialVersionUID(3L) private[collection] class Patched[A](underlying: SomeIterableOps[A], from: Int, other: IterableOnce[A], replaced: Int) extends AbstractView[A] { def iterator: Iterator[A] = underlying.iterator.patch(from, other.iterator, replaced) - override def knownSize: Int = if (underlying.knownSize == 0) 0 else super.knownSize - override def isEmpty: Boolean = iterator.isEmpty + override def knownSize: Int = if (underlying.knownSize == 0 && other.knownSize == 0) 0 else super.knownSize + override def isEmpty: Boolean = if (knownSize == 0) true else iterator.isEmpty } @SerialVersionUID(3L) From f1f8caeff48881c6d0ca5c9d4d5837c00f10a465 Mon Sep 17 00:00:00 2001 From: Jason Zaugg Date: Mon, 9 Jul 2018 11:34:53 +1000 Subject: [PATCH 048/143] Revert overides of knownSize and isEmpty in fromIteratorProvider --- src/library/scala/collection/View.scala | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/library/scala/collection/View.scala b/src/library/scala/collection/View.scala index c3ce9a59964d..c9f9d29c07fa 100644 --- a/src/library/scala/collection/View.scala +++ b/src/library/scala/collection/View.scala @@ -46,8 +46,6 @@ object View extends IterableFactory[View] { */ def fromIteratorProvider[A](it: () => Iterator[A]): View[A] = new AbstractView[A] { def iterator = it() - override def knownSize: Int = iterator.knownSize - override def isEmpty: Boolean = iterator.isEmpty } /** From 426445dc2bdf165d8d653c631e0088670ae1ffaa Mon Sep 17 00:00:00 2001 From: Jason Zaugg Date: Wed, 20 Jun 2018 19:12:04 +1000 Subject: [PATCH 049/143] Deal with special case for Array[Unit] in Array.{copyOf,copyAs} --- src/library/scala/Array.scala | 40 +++++++++++++++++++------------- test/junit/scala/ArrayTest.scala | 16 +++++++++++++ 2 files changed, 40 insertions(+), 16 deletions(-) create mode 100644 test/junit/scala/ArrayTest.scala diff --git a/src/library/scala/Array.scala b/src/library/scala/Array.scala index e3adc129f5ce..f4cfaaa960b8 100644 --- a/src/library/scala/Array.scala +++ b/src/library/scala/Array.scala @@ -14,7 +14,7 @@ import mutable.ArrayBuilder import immutable.ArraySeq import scala.language.implicitConversions import scala.reflect.ClassTag -import scala.runtime.ScalaRunTime +import scala.runtime.{BoxedUnit, ScalaRunTime} import scala.runtime.ScalaRunTime.{array_apply, array_update} /** Utility methods for operating on arrays. @@ -122,7 +122,9 @@ object Array { * @see `java.util.Arrays#copyOf` */ def copyOf[A](original: Array[A], newLength: Int): Array[A] = (original match { - case x: Array[AnyRef] => java.util.Arrays.copyOf(x, newLength) + case x: Array[AnyRef] => + if (x.getClass.getComponentType == classOf[BoxedUnit]) newUnitArray(newLength).asInstanceOf[Array[A]] + else java.util.Arrays.copyOf(x, newLength) case x: Array[Int] => java.util.Arrays.copyOf(x, newLength) case x: Array[Double] => java.util.Arrays.copyOf(x, newLength) case x: Array[Long] => java.util.Arrays.copyOf(x, newLength) @@ -131,10 +133,6 @@ object Array { case x: Array[Byte] => java.util.Arrays.copyOf(x, newLength) case x: Array[Short] => java.util.Arrays.copyOf(x, newLength) case x: Array[Boolean] => java.util.Arrays.copyOf(x, newLength) - case x: Array[Unit] => - val dest = new Array[Unit](newLength) - Array.copy(original, 0, dest, 0, original.length) - dest }).asInstanceOf[Array[A]] /** Copy one array to another, truncating or padding with default values (if @@ -151,20 +149,30 @@ object Array { * @see `java.util.Arrays#copyOf` */ def copyAs[A](original: Array[_], newLength: Int)(implicit ct: ClassTag[A]): Array[A] = { - val destClass = ct.runtimeClass.asInstanceOf[Class[A]] - if (destClass.isAssignableFrom(original.getClass.getComponentType)) { - if(destClass.isPrimitive) copyOf[A](original.asInstanceOf[Array[A]], newLength) - else { - val destArrayClass = java.lang.reflect.Array.newInstance(destClass, 0).getClass.asInstanceOf[Class[Array[AnyRef]]] - java.util.Arrays.copyOf(original.asInstanceOf[Array[AnyRef]], newLength, destArrayClass).asInstanceOf[Array[A]] + val runtimeClass = ct.runtimeClass + if (runtimeClass == Void.TYPE) newUnitArray(newLength).asInstanceOf[Array[A]] + else { + val destClass = runtimeClass.asInstanceOf[Class[A]] + if (destClass.isAssignableFrom(original.getClass.getComponentType)) { + if (destClass.isPrimitive) copyOf[A](original.asInstanceOf[Array[A]], newLength) + else { + val destArrayClass = java.lang.reflect.Array.newInstance(destClass, 0).getClass.asInstanceOf[Class[Array[AnyRef]]] + java.util.Arrays.copyOf(original.asInstanceOf[Array[AnyRef]], newLength, destArrayClass).asInstanceOf[Array[A]] + } + } else { + val dest = new Array[A](newLength) + Array.copy(original, 0, dest, 0, original.length) + dest } - } else { - val dest = new Array[A](newLength) - Array.copy(original, 0, dest, 0, original.length) - dest } } + private def newUnitArray(len: Int): Array[Unit] = { + val result = new Array[Unit](len) + java.util.Arrays.fill(result.asInstanceOf[Array[AnyRef]], ()) + result + } + /** Returns an array of length 0 */ def empty[T: ClassTag]: Array[T] = new Array[T](0) diff --git a/test/junit/scala/ArrayTest.scala b/test/junit/scala/ArrayTest.scala new file mode 100644 index 000000000000..753c485a69f5 --- /dev/null +++ b/test/junit/scala/ArrayTest.scala @@ -0,0 +1,16 @@ +package scala + +import org.junit.Assert.assertArrayEquals +import org.junit.Test + +import scala.runtime.BoxedUnit + +class ArrayTest { + @Test + def testArrayCopyOfUnit(): Unit = { + val expected = new Array[BoxedUnit](32).asInstanceOf[Array[AnyRef]]; java.util.Arrays.fill(expected, ().asInstanceOf[AnyRef]) + assertArrayEquals(expected, Array.copyOf(Array[Unit](), 32).asInstanceOf[Array[AnyRef]]) + assertArrayEquals(expected, Array.copyAs[Unit](Array[Nothing](), 32).asInstanceOf[Array[AnyRef]]) + assertArrayEquals(expected, Array.copyAs[Unit](Array[Unit](), 32).asInstanceOf[Array[AnyRef]]) + } +} From 7fca0f3b7cfb26b716287c01ed2dc77d46001dd1 Mon Sep 17 00:00:00 2001 From: Jason Zaugg Date: Tue, 10 Jul 2018 11:39:15 +1000 Subject: [PATCH 050/143] Use ordered pattern match to distinguish Array[BoxedUnit] --- src/library/scala/Array.scala | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/library/scala/Array.scala b/src/library/scala/Array.scala index f4cfaaa960b8..1ef6679501d1 100644 --- a/src/library/scala/Array.scala +++ b/src/library/scala/Array.scala @@ -122,9 +122,8 @@ object Array { * @see `java.util.Arrays#copyOf` */ def copyOf[A](original: Array[A], newLength: Int): Array[A] = (original match { - case x: Array[AnyRef] => - if (x.getClass.getComponentType == classOf[BoxedUnit]) newUnitArray(newLength).asInstanceOf[Array[A]] - else java.util.Arrays.copyOf(x, newLength) + case x: Array[BoxedUnit] => newUnitArray(newLength).asInstanceOf[Array[A]] + case x: Array[AnyRef] => java.util.Arrays.copyOf(x, newLength) case x: Array[Int] => java.util.Arrays.copyOf(x, newLength) case x: Array[Double] => java.util.Arrays.copyOf(x, newLength) case x: Array[Long] => java.util.Arrays.copyOf(x, newLength) From f3cad7e7211ee425d5be4e14b6465219d6318ff7 Mon Sep 17 00:00:00 2001 From: Jason Zaugg Date: Mon, 9 Jul 2018 19:54:27 +1000 Subject: [PATCH 051/143] Fix regression with curried implicit defs conforming to function types Fixes scala/bug#10858 --- src/compiler/scala/tools/nsc/typechecker/Implicits.scala | 7 +++++-- test/files/pos/t10858.scala | 6 ++++++ 2 files changed, 11 insertions(+), 2 deletions(-) create mode 100644 test/files/pos/t10858.scala diff --git a/src/compiler/scala/tools/nsc/typechecker/Implicits.scala b/src/compiler/scala/tools/nsc/typechecker/Implicits.scala index 4db10827f248..4c66b77a54dd 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Implicits.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Implicits.scala @@ -386,10 +386,12 @@ trait Implicits { /** The type parameters to instantiate */ val undetParams = if (isView) Nil else context.outer.undetparams val wildPt = approximate(pt) - private val ptFunctionArity: Int = { - val dealiased = pt.dealiasWiden + private[this] def functionArityOf(tp: Type): Int = { + val dealiased = tp.dealiasWiden if (isFunctionTypeDirect(dealiased)) dealiased.typeArgs.length - 1 else -1 } + private val cachedPtFunctionArity: Int = functionArityOf(pt) + final def functionArity(tp: Type): Int = if (tp eq pt) cachedPtFunctionArity else functionArityOf(tp) private val stableRunDefsForImport = currentRun.runDefinitions import stableRunDefsForImport._ @@ -579,6 +581,7 @@ trait Implicits { if (sym.isAliasType) loop(tp, pt.dealias) else if (sym.isAbstractType) loop(tp, pt.bounds.lo) else { + val ptFunctionArity = functionArity(pt) ptFunctionArity > 0 && hasLength(params, ptFunctionArity) && { var ps = params var as = args diff --git a/test/files/pos/t10858.scala b/test/files/pos/t10858.scala new file mode 100644 index 000000000000..8d439f0d0c98 --- /dev/null +++ b/test/files/pos/t10858.scala @@ -0,0 +1,6 @@ +import language.implicitConversions + +object Test { + implicit def foo(a: Int)(b: Int, c: Int): String = "" + a + b; + implicitly[Int => (Int, Int) => String].apply(1).apply(2, 3) +} From cd3b0e8afe761ec09e8cd604470319982a582692 Mon Sep 17 00:00:00 2001 From: Julien Richard-Foy Date: Wed, 11 Jul 2018 09:20:55 +0200 Subject: [PATCH 052/143] Undeprecate IterableOnceOps#toBuffer --- src/library/scala/collection/IterableOnce.scala | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/library/scala/collection/IterableOnce.scala b/src/library/scala/collection/IterableOnce.scala index 1a880be15f2d..193a1c0d8751 100644 --- a/src/library/scala/collection/IterableOnce.scala +++ b/src/library/scala/collection/IterableOnce.scala @@ -1193,8 +1193,7 @@ trait IterableOnceOps[+A, +CC[_], +C] extends Any { this: IterableOnce[A] => @deprecated("Use .to(Stream) instead of .toStream", "2.13.0") @`inline` final def toStream: immutable.Stream[A] = to(immutable.Stream) - @deprecated("Use .to(Buffer) instead of .toBuffer", "2.13.0") - @`inline` final def toBuffer[B >: A]: mutable.Buffer[B] = to(mutable.Buffer) + @`inline` final def toBuffer[B >: A]: mutable.Buffer[B] = mutable.Buffer.from(this) /** Convert collection to array. */ def toArray[B >: A: ClassTag]: Array[B] = From c9d1972425a45d21aae35406a08c00d177536a40 Mon Sep 17 00:00:00 2001 From: Julien Richard-Foy Date: Mon, 16 Jul 2018 09:36:07 +0200 Subject: [PATCH 053/143] Move mapInPlace from mutable.SeqOps to mutable.IndexedSeqOps Fixes scala/bug#10947 --- .../scala/collection/mutable/IndexedSeq.scala | 7 +++++++ .../scala/collection/mutable/Seq.scala | 19 +++++++------------ 2 files changed, 14 insertions(+), 12 deletions(-) diff --git a/src/library/scala/collection/mutable/IndexedSeq.scala b/src/library/scala/collection/mutable/IndexedSeq.scala index cdc4fb5b7dfc..bf0c39bb49e5 100644 --- a/src/library/scala/collection/mutable/IndexedSeq.scala +++ b/src/library/scala/collection/mutable/IndexedSeq.scala @@ -17,6 +17,13 @@ trait IndexedSeqOps[A, +CC[_], +C <: AnyRef] extends scala.collection.IndexedSeqOps[A, CC, C] with SeqOps[A, CC, C] { + /** Modifies this $coll by applying a function to all elements of this $coll. + * + * @param f the function to apply to each element. + * @return this $coll modified by replacing all elements with the + * result of applying the given function `f` to each element + * of this $coll. + */ def mapInPlace(f: A => A): this.type = { var i = 0 val siz = size diff --git a/src/library/scala/collection/mutable/Seq.scala b/src/library/scala/collection/mutable/Seq.scala index ea74a2385af1..5a5304802ac6 100644 --- a/src/library/scala/collection/mutable/Seq.scala +++ b/src/library/scala/collection/mutable/Seq.scala @@ -42,18 +42,13 @@ trait SeqOps[A, +CC[_], +C <: AnyRef] @throws[IndexOutOfBoundsException] def update(idx: Int, elem: A): Unit - - /** Modifies this $coll by applying a function to all elements of this $coll. - * - * @param f the function to apply to each element. - * @return this $coll modified by replacing all elements with the - * result of applying the given function `f` to each element - * of this $coll. - */ - def mapInPlace(f: A => A): this.type - - @deprecated("Use `mapInPlace` instead", "2.13.0") - @`inline`final def transform(f: A => A): this.type = mapInPlace(f) + @deprecated("Use `mapInPlace` on an `IndexedSeq` instead", "2.13.0") + @`inline`final def transform(f: A => A): this.type = { + var i = 0 + val siz = size + while (i < siz) { this(i) = f(this(i)); i += 1 } + this + } } /** Explicit instantiation of the `Seq` trait to reduce class file size in subclasses. */ From 1fd64fa0a40093f28a798a202c0e62bb4927637b Mon Sep 17 00:00:00 2001 From: Adriaan Moors Date: Fri, 13 Jul 2018 14:42:35 +0200 Subject: [PATCH 054/143] Respect BaseTypeSeq invar (3) symbols are distinct In a BTS, a singleton type is redundant with its underlying type. In other words, what could we learn about the superclasses of a singleton type that is not captured entirely by its super type? This duplicate type symbol leads to confusion during asSeenFrom when looking up the base class that defines the T type param (Since `typeOf[this.type].typeSymbol == typeOf[Poly[_]].typeSymbol`, we return `this.type` for the base type at Poly, which does not have the expected type params.) The interesting part is that you have to embed the singleton in a compound type to trigger the bug because SubType (a supertype of SingletonType) delegates `baseType` to its underlying (super) type! TODO: a similar deviation still exists in AbstractTypeRef. I hesitate to bring that one in line with the spec, because I could imagine it actually being used. --- .../scala/reflect/internal/Types.scala | 38 +++++++------------ test/files/pos/t11020.scala | 7 ++++ 2 files changed, 21 insertions(+), 24 deletions(-) create mode 100644 test/files/pos/t11020.scala diff --git a/src/reflect/scala/reflect/internal/Types.scala b/src/reflect/scala/reflect/internal/Types.scala index 4c99c52fbd72..701ae8ac0868 100644 --- a/src/reflect/scala/reflect/internal/Types.scala +++ b/src/reflect/scala/reflect/internal/Types.scala @@ -881,24 +881,15 @@ trait Types /** Same as matches, except that non-method types are always assumed to match. */ def looselyMatches(that: Type): Boolean = matchesType(this, that, alwaysMatchSimple = true) - /** The shortest sorted upwards closed array of types that contains - * this type as first element. - * - * A list or array of types ts is upwards closed if - * - * for all t in ts: - * for all typerefs p.s[args] such that t <: p.s[args] - * there exists a typeref p'.s[args'] in ts such that - * t <: p'.s['args] <: p.s[args], - * - * and - * - * for all singleton types p.s such that t <: p.s - * there exists a singleton type p'.s in ts such that - * t <: p'.s <: p.s - * - * Sorting is with respect to Symbol.isLess() on type symbols. - */ + /** The base type sequence of T is the smallest set of (potentially existentially quantified) + * class types Ti, so that for each supertype T' (T <:< T'), + * there is a Ti so that T <:< Ti <:< T'. + * + * This is also known as the upward closed set of the partially ordered set of + * class types under Symbol#isLess (a refinement of Symbol#isSubclass). + * + * See "Base Types and Member Definitions" in spec/03-types.md. + */ def baseTypeSeq: BaseTypeSeq = baseTypeSingletonSeq(this) /** The maximum depth (@see typeDepth) @@ -1090,7 +1081,8 @@ trait Types override def baseTypeSeq: BaseTypeSeq = supertype.baseTypeSeq override def baseTypeSeqDepth: Depth = supertype.baseTypeSeqDepth override def baseClasses: List[Symbol] = supertype.baseClasses - override def boundSyms: Set[Symbol] = emptySymbolSet} + override def boundSyms: Set[Symbol] = emptySymbolSet + } /** A base class for types that represent a single value * (single-types and this-types). @@ -1098,11 +1090,8 @@ trait Types abstract class SingletonType extends SubType with SimpleTypeProxy with SingletonTypeApi { def supertype = underlying override def isTrivial = false - override def widen: Type = underlying.widen - override def baseTypeSeq: BaseTypeSeq = { - if (StatisticsStatics.areSomeColdStatsEnabled) statistics.incCounter(singletonBaseTypeSeqCount) - underlying.baseTypeSeq prepend this - } +// Spec: "The base types of a singleton type `$p$.type` are the base types of the type of $p$." +// override def baseTypeSeq: BaseTypeSeq = underlying.baseTypeSeq override def isHigherKinded = false // singleton type classifies objects, thus must be kind * override def safeToString: String = { // Avoiding printing Predef.type and scala.package.type as "type", @@ -2091,6 +2080,7 @@ trait Types override def decls = relativeInfo.decls override def bounds = relativeInfo.bounds + // TODO: this deviates from the spec "The base types of an abstract type are the base types of its upper bound." override protected[Types] def baseTypeSeqImpl: BaseTypeSeq = bounds.hi.baseTypeSeq prepend this override protected[Types] def parentsImpl: List[Type] = relativeInfo.parents diff --git a/test/files/pos/t11020.scala b/test/files/pos/t11020.scala new file mode 100644 index 000000000000..bb04cce3b496 --- /dev/null +++ b/test/files/pos/t11020.scala @@ -0,0 +1,7 @@ +// asSeenFrom crash related to BaseTypeSeq bug for singleton types +trait Poly[T] { type TT = T + def foo: (this.type with Any)#TT +} + +// equivalent: +// class C { def meh[T](x: Poly[T]): (x.type with Any)#TT = ??? } From 3c0a4676dea00cb279f31d3399545395e0696457 Mon Sep 17 00:00:00 2001 From: Som Snytt Date: Mon, 16 Jul 2018 11:15:44 -0700 Subject: [PATCH 055/143] Pos test S1 progresses in 2.13 It appears the failing behavior wasn't tested, or maybe was purged during the phase of "pending tests do nothing". --- test/files/pos/S1.scala | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/test/files/pos/S1.scala b/test/files/pos/S1.scala index 68706e3dd3b0..14269ad5ff27 100644 --- a/test/files/pos/S1.scala +++ b/test/files/pos/S1.scala @@ -8,6 +8,24 @@ ** ^ */ class S1() { - def foo[T <: this.type](x: T) = x; - foo[this.type](this); + def foo[T <: this.type](x: T) = x + def f = foo[this.type](this) } + +class S2() { + def foo[T <: this.type](x: T) = x + def f = foo(this) +} +/* + * +$ scalac -d /tmp test/files/pos/S1.scala +test/files/pos/S1.scala:17: error: inferred type arguments [S2] do not conform to method foo's type parameter bounds [T <: S2.this.type] + def f = foo(this) + ^ +test/files/pos/S1.scala:17: error: type mismatch; + found : S2 + required: T + def f = foo(this) + ^ +two errors found + */ From e37f3f3afb675c74a4705130e09095c0fdcdc6bc Mon Sep 17 00:00:00 2001 From: Som Snytt Date: Tue, 17 Jul 2018 14:19:32 -0700 Subject: [PATCH 056/143] Avoid truncation of REPL output Line endings on windows changes the output length. --- test/files/run/t10956.check | 95 ++++++++++++++++++++++++++++++++++++- test/files/run/t10956.scala | 1 + 2 files changed, 95 insertions(+), 1 deletion(-) diff --git a/test/files/run/t10956.check b/test/files/run/t10956.check index e52daede735f..1bec9ae8f2ae 100644 --- a/test/files/run/t10956.check +++ b/test/files/run/t10956.check @@ -1,4 +1,7 @@ +scala> $intp.isettings.maxPrintString = 0 +$intp.isettings.maxPrintString: Int = 0 + scala> :paste < EOF // Entering paste mode (EOF to finish) @@ -34,6 +37,96 @@ import java.awt.Shape import java.awt.ActiveEvent import java.awt.FlowLayout import java.awt.LinearGradientPaint -import java.awt.Splash... +import java.awt.SplashScreen +import java.awt.Adjustable +import java.awt.FocusTraversalPolicy +import java.awt.List +import java.awt.Stroke +import java.awt.AlphaComposite +import java.awt.Font +import java.awt.MediaTracker +import java.awt.SystemColor +import java.awt.BasicStroke +import java.awt.FontFormatException +import java.awt.Menu +import java.awt.SystemTray +import java.awt.BorderLayout +import java.awt.FontMetrics +import java.awt.MenuBar +import java.awt.TextArea +import java.awt.BufferCapabilities +import java.awt.Frame +import java.awt.MenuComponent +import java.awt.TextComponent +import java.awt.Button +import java.awt.GradientPaint +import java.awt.MenuContainer +import java.awt.TextField +import java.awt.Canvas +import java.awt.Graphics +import java.awt.MenuItem +import java.awt.TexturePaint +import java.awt.CardLayout +import java.awt.Graphics2D +import java.awt.MenuShortcut +import java.awt.Toolkit +import java.awt.Checkbox +import java.awt.GraphicsConfigTemplate +import java.awt.MouseInfo +import java.awt.Transparency +import java.awt.CheckboxGroup +import java.awt.GraphicsConfiguration +import java.awt.MultipleGradientPaint +import java.awt.TrayIcon +import java.awt.CheckboxMenuItem +import java.awt.GraphicsDevice +import java.awt.PageAttributes +import java.awt.Window +import java.awt.Choice +import java.awt.GraphicsEnvironment +import java.awt.Paint +import java.awt.color +import java.awt.Color +import java.awt.GridBagConstraints +import java.awt.PaintContext +import java.awt.datatransfer +import java.awt.Component +import java.awt.GridBagLayout +import java.awt.Panel +import java.awt.dnd +import java.awt.ComponentOrientation +import java.awt.GridBagLayoutInfo +import java.awt.Point +import java.awt.event +import java.awt.Composite +import java.awt.GridLayout +import java.awt.PointerInfo +import java.awt.font +import java.awt.CompositeContext +import java.awt.HeadlessException +import java.awt.Polygon +import java.awt.geom +import java.awt.Container +import java.awt.IllegalComponentStateException +import java.awt.PopupMenu +import java.awt.im +import java.awt.ContainerOrderFocusTraversalPolicy +import java.awt.Image +import java.awt.PrintGraphics +import java.awt.image +import java.awt.Cursor +import java.awt.ImageCapabilities +import java.awt.PrintJob +import java.awt.peer +import java.awt.DefaultFocusTraversalPolicy +import java.awt.Insets +import java.awt.RadialGradientPaint +import java.awt.print +import java.awt.DefaultKeyboardFocusManager +import java.awt.ItemSelectable +import java.awt.Rectangle +import java.awt.Desktop +import java.awt.JobAttributes +import java.awt.RenderingHints scala> :quit diff --git a/test/files/run/t10956.scala b/test/files/run/t10956.scala index 88377dde4ee6..94d95de6546c 100644 --- a/test/files/run/t10956.scala +++ b/test/files/run/t10956.scala @@ -10,6 +10,7 @@ import scala.tools.nsc.Settings object Test extends ReplTest { def code = """ +$intp.isettings.maxPrintString = 0 :paste < EOF import java.awt.AWTError,java.awt.Dialog,java.awt.KeyEventDispatcher,java.awt.Robot,java.awt.AWTEvent,java.awt.Dimension,java.awt.KeyEventPostProcessor,java.awt.ScrollPane,java.awt.AWTEventMulticaster,java.awt.DisplayMode,java.awt.KeyboardFocusManager,java.awt.ScrollPaneAdjustable,java.awt.AWTException,java.awt.Event,java.awt.Label,java.awt.Scrollbar,java.awt.AWTKeyStroke,java.awt.EventQueue,java.awt.LayoutManager,java.awt.SecondaryLoop,java.awt.AWTPermission,java.awt.FileDialog,java.awt.LayoutManager2,java.awt.Shape,java.awt.ActiveEvent,java.awt.FlowLayout,java.awt.LinearGradientPaint,java.awt.SplashScreen,java.awt.Adjustable,java.awt.FocusTraversalPolicy,java.awt.List,java.awt.Stroke,java.awt.AlphaComposite,java.awt.Font,java.awt.MediaTracker,java.awt.SystemColor,java.awt.BasicStroke,java.awt.FontFormatException,java.awt.Menu,java.awt.SystemTray,java.awt.BorderLayout,java.awt.FontMetrics,java.awt.MenuBar,java.awt.TextArea,java.awt.BufferCapabilities,java.awt.Frame,java.awt.MenuComponent,java.awt.TextComponent,java.awt.Button,java.awt.GradientPaint,java.awt.MenuContainer,java.awt.TextField,java.awt.Canvas,java.awt.Graphics,java.awt.MenuItem,java.awt.TexturePaint,java.awt.CardLayout,java.awt.Graphics2D,java.awt.MenuShortcut,java.awt.Toolkit,java.awt.Checkbox,java.awt.GraphicsConfigTemplate,java.awt.MouseInfo,java.awt.Transparency,java.awt.CheckboxGroup,java.awt.GraphicsConfiguration,java.awt.MultipleGradientPaint,java.awt.TrayIcon,java.awt.CheckboxMenuItem,java.awt.GraphicsDevice,java.awt.PageAttributes,java.awt.Window,java.awt.Choice,java.awt.GraphicsEnvironment,java.awt.Paint,java.awt.color,java.awt.Color,java.awt.GridBagConstraints,java.awt.PaintContext,java.awt.datatransfer,java.awt.Component,java.awt.GridBagLayout,java.awt.Panel,java.awt.dnd,java.awt.ComponentOrientation,java.awt.GridBagLayoutInfo,java.awt.Point,java.awt.event,java.awt.Composite,java.awt.GridLayout,java.awt.PointerInfo,java.awt.font,java.awt.CompositeContext,java.awt.HeadlessException,java.awt.Polygon,java.awt.geom,java.awt.Container,java.awt.IllegalComponentStateException,java.awt.PopupMenu,java.awt.im,java.awt.ContainerOrderFocusTraversalPolicy,java.awt.Image,java.awt.PrintGraphics,java.awt.image,java.awt.Cursor,java.awt.ImageCapabilities,java.awt.PrintJob,java.awt.peer,java.awt.DefaultFocusTraversalPolicy,java.awt.Insets,java.awt.RadialGradientPaint,java.awt.print,java.awt.DefaultKeyboardFocusManager,java.awt.ItemSelectable,java.awt.Rectangle,java.awt.Desktop,java.awt.JobAttributes,java.awt.RenderingHints EOF From e4453e29a853c009a3c65877a1b8cec2f77af4b3 Mon Sep 17 00:00:00 2001 From: Som Snytt Date: Mon, 25 Jun 2018 12:54:11 -0700 Subject: [PATCH 057/143] REPL prints long results Previously, when REPL has many results to output, it would print `a + b + etc`, a potentially large expression tree. `s"${a}${b}etc` is also a tree too large for refchecks conversion; so just use a string builder to build the string to print, if there is more than one result. --- .../scala/tools/nsc/interpreter/IMain.scala | 40 ++++++++++--------- test/files/run/repl-colon-type.check | 2 +- test/files/run/repl-trim-stack-trace.check | 2 +- test/files/run/t10956.check | 39 ++++++++++++++++++ test/files/run/t10956.scala | 17 ++++++++ test/files/run/t7747-repl.check | 11 ++--- 6 files changed, 83 insertions(+), 28 deletions(-) create mode 100644 test/files/run/t10956.check create mode 100644 test/files/run/t10956.scala diff --git a/src/repl/scala/tools/nsc/interpreter/IMain.scala b/src/repl/scala/tools/nsc/interpreter/IMain.scala index 59d566387d14..d2f06ca249db 100644 --- a/src/repl/scala/tools/nsc/interpreter/IMain.scala +++ b/src/repl/scala/tools/nsc/interpreter/IMain.scala @@ -846,25 +846,27 @@ class IMain(val settings: Settings, parentClassLoaderOverride: Option[ClassLoade // The symbol defined by the last member handler val resValSym = value - val extractionCode = - lineRep.packaged(stringFromWriter { code => - // first line evaluates object to make sure constructor is run - // initial "" so later code can uniformly be: + etc - code.println(s""" - |object ${lineRep.evalName} { - | ${if (resValSym != NoSymbol) s"lazy val ${lineRep.resultName} = ${originalPath(resValSym)}" else ""} - | lazy val ${lineRep.printName}: _root_.java.lang.String = $executionWrapper { - | $fullAccessPath - | ( "" """.stripMargin) // the result extraction code will emit code to append strings to this initial "" - - contributors map (_.resultExtractionCode(this)) foreach code.println - - code.println(""" - | ) - | } - |} - """.stripMargin) - }) + val extractionCode = stringFromWriter { code => + code.println(s""" + |${lineRep.packageDecl} { + |object ${lineRep.evalName} { + | ${if (resValSym != NoSymbol) s"lazy val ${lineRep.resultName} = ${originalPath(resValSym)}" else ""} + | lazy val ${lineRep.printName}: _root_.java.lang.String = $executionWrapper { + | $fullAccessPath + |""".stripMargin) + if (contributors.lengthCompare(1) > 0) { + code.println("val sb = new _root_.scala.StringBuilder") + contributors foreach (x => code.println(s"""sb.append("" ${x.resultExtractionCode(this)})""")) + code.println("sb.toString") + } else { + code.print(""""" """) // start with empty string + contributors foreach (x => code.print(x.resultExtractionCode(this))) + code.println() + } + code.println(s""" + | } + |}}""".stripMargin) + } showCode(extractionCode) diff --git a/test/files/run/repl-colon-type.check b/test/files/run/repl-colon-type.check index b74c8b578a00..1e119793b995 100644 --- a/test/files/run/repl-colon-type.check +++ b/test/files/run/repl-colon-type.check @@ -37,7 +37,7 @@ scala> :type protected lazy val f = 5 lazy val $result = $line16.$read.$iw.$iw.f ^ -:5: error: lazy value f cannot be accessed in object $iw +:4: error: lazy value f cannot be accessed in object $iw Access to protected lazy value f not permitted because enclosing object $eval in package $line16 is not a subclass of object $iw where target is defined diff --git a/test/files/run/repl-trim-stack-trace.check b/test/files/run/repl-trim-stack-trace.check index 7308aacdecf6..c85805788c63 100644 --- a/test/files/run/repl-trim-stack-trace.check +++ b/test/files/run/repl-trim-stack-trace.check @@ -25,7 +25,7 @@ java.lang.Exception scala> null.asInstanceOf java.lang.NullPointerException - at .$print$lzycompute(:9) + at .$print$lzycompute(:8) ... ??? elided scala> :quit diff --git a/test/files/run/t10956.check b/test/files/run/t10956.check new file mode 100644 index 000000000000..e52daede735f --- /dev/null +++ b/test/files/run/t10956.check @@ -0,0 +1,39 @@ + +scala> :paste < EOF +// Entering paste mode (EOF to finish) + +import java.awt.AWTError,java.awt.Dialog,java.awt.KeyEventDispatcher,java.awt.Robot,java.awt.AWTEvent,java.awt.Dimension,java.awt.KeyEventPostProcessor,java.awt.ScrollPane,java.awt.AWTEventMulticaster,java.awt.DisplayMode,java.awt.KeyboardFocusManager,java.awt.ScrollPaneAdjustable,java.awt.AWTException,java.awt.Event,java.awt.Label,java.awt.Scrollbar,java.awt.AWTKeyStroke,java.awt.EventQueue,java.awt.LayoutManager,java.awt.SecondaryLoop,java.awt.AWTPermission,java.awt.FileDialog,java.awt.LayoutManager2,java.awt.Shape,java.awt.ActiveEvent,java.awt.FlowLayout,java.awt.LinearGradientPaint,java.awt.SplashScreen,java.awt.Adjustable,java.awt.FocusTraversalPolicy,java.awt.List,java.awt.Stroke,java.awt.AlphaComposite,java.awt.Font,java.awt.MediaTracker,java.awt.SystemColor,java.awt.BasicStroke,java.awt.FontFormatException,java.awt.Menu,java.awt.SystemTray,java.awt.BorderLayout,java.awt.FontMetrics,java.awt.MenuBar,java.awt.TextArea,java.awt.BufferCapabilities,java.awt.Frame,java.awt.MenuComponent,java.awt.TextComponent,java.awt.Button,java.awt.GradientPaint,java.awt.MenuContainer,java.awt.TextField,java.awt.Canvas,java.awt.Graphics,java.awt.MenuItem,java.awt.TexturePaint,java.awt.CardLayout,java.awt.Graphics2D,java.awt.MenuShortcut,java.awt.Toolkit,java.awt.Checkbox,java.awt.GraphicsConfigTemplate,java.awt.MouseInfo,java.awt.Transparency,java.awt.CheckboxGroup,java.awt.GraphicsConfiguration,java.awt.MultipleGradientPaint,java.awt.TrayIcon,java.awt.CheckboxMenuItem,java.awt.GraphicsDevice,java.awt.PageAttributes,java.awt.Window,java.awt.Choice,java.awt.GraphicsEnvironment,java.awt.Paint,java.awt.color,java.awt.Color,java.awt.GridBagConstraints,java.awt.PaintContext,java.awt.datatransfer,java.awt.Component,java.awt.GridBagLayout,java.awt.Panel,java.awt.dnd,java.awt.ComponentOrientation,java.awt.GridBagLayoutInfo,java.awt.Point,java.awt.event,java.awt.Composite,java.awt.GridLayout,java.awt.PointerInfo,java.awt.font,java.awt.CompositeContext,java.awt.HeadlessException,java.awt.Polygon,java.awt.geom,java.awt.Container,java.awt.IllegalComponentStateException,java.awt.PopupMenu,java.awt.im,java.awt.ContainerOrderFocusTraversalPolicy,java.awt.Image,java.awt.PrintGraphics,java.awt.image,java.awt.Cursor,java.awt.ImageCapabilities,java.awt.PrintJob,java.awt.peer,java.awt.DefaultFocusTraversalPolicy,java.awt.Insets,java.awt.RadialGradientPaint,java.awt.print,java.awt.DefaultKeyboardFocusManager,java.awt.ItemSelectable,java.awt.Rectangle,java.awt.Desktop,java.awt.JobAttributes,java.awt.RenderingHints +EOF + +// Exiting paste mode, now interpreting. + +import java.awt.AWTError +import java.awt.Dialog +import java.awt.KeyEventDispatcher +import java.awt.Robot +import java.awt.AWTEvent +import java.awt.Dimension +import java.awt.KeyEventPostProcessor +import java.awt.ScrollPane +import java.awt.AWTEventMulticaster +import java.awt.DisplayMode +import java.awt.KeyboardFocusManager +import java.awt.ScrollPaneAdjustable +import java.awt.AWTException +import java.awt.Event +import java.awt.Label +import java.awt.Scrollbar +import java.awt.AWTKeyStroke +import java.awt.EventQueue +import java.awt.LayoutManager +import java.awt.SecondaryLoop +import java.awt.AWTPermission +import java.awt.FileDialog +import java.awt.LayoutManager2 +import java.awt.Shape +import java.awt.ActiveEvent +import java.awt.FlowLayout +import java.awt.LinearGradientPaint +import java.awt.Splash... + +scala> :quit diff --git a/test/files/run/t10956.scala b/test/files/run/t10956.scala new file mode 100644 index 000000000000..88377dde4ee6 --- /dev/null +++ b/test/files/run/t10956.scala @@ -0,0 +1,17 @@ + +import scala.tools.partest.ReplTest +import scala.tools.nsc.Settings + + +/* + * Huge import clause resulted in long "result string" construction. + * That would blow the stack on typecheck or refchecks. + */ +object Test extends ReplTest { + def code = + """ +:paste < EOF +import java.awt.AWTError,java.awt.Dialog,java.awt.KeyEventDispatcher,java.awt.Robot,java.awt.AWTEvent,java.awt.Dimension,java.awt.KeyEventPostProcessor,java.awt.ScrollPane,java.awt.AWTEventMulticaster,java.awt.DisplayMode,java.awt.KeyboardFocusManager,java.awt.ScrollPaneAdjustable,java.awt.AWTException,java.awt.Event,java.awt.Label,java.awt.Scrollbar,java.awt.AWTKeyStroke,java.awt.EventQueue,java.awt.LayoutManager,java.awt.SecondaryLoop,java.awt.AWTPermission,java.awt.FileDialog,java.awt.LayoutManager2,java.awt.Shape,java.awt.ActiveEvent,java.awt.FlowLayout,java.awt.LinearGradientPaint,java.awt.SplashScreen,java.awt.Adjustable,java.awt.FocusTraversalPolicy,java.awt.List,java.awt.Stroke,java.awt.AlphaComposite,java.awt.Font,java.awt.MediaTracker,java.awt.SystemColor,java.awt.BasicStroke,java.awt.FontFormatException,java.awt.Menu,java.awt.SystemTray,java.awt.BorderLayout,java.awt.FontMetrics,java.awt.MenuBar,java.awt.TextArea,java.awt.BufferCapabilities,java.awt.Frame,java.awt.MenuComponent,java.awt.TextComponent,java.awt.Button,java.awt.GradientPaint,java.awt.MenuContainer,java.awt.TextField,java.awt.Canvas,java.awt.Graphics,java.awt.MenuItem,java.awt.TexturePaint,java.awt.CardLayout,java.awt.Graphics2D,java.awt.MenuShortcut,java.awt.Toolkit,java.awt.Checkbox,java.awt.GraphicsConfigTemplate,java.awt.MouseInfo,java.awt.Transparency,java.awt.CheckboxGroup,java.awt.GraphicsConfiguration,java.awt.MultipleGradientPaint,java.awt.TrayIcon,java.awt.CheckboxMenuItem,java.awt.GraphicsDevice,java.awt.PageAttributes,java.awt.Window,java.awt.Choice,java.awt.GraphicsEnvironment,java.awt.Paint,java.awt.color,java.awt.Color,java.awt.GridBagConstraints,java.awt.PaintContext,java.awt.datatransfer,java.awt.Component,java.awt.GridBagLayout,java.awt.Panel,java.awt.dnd,java.awt.ComponentOrientation,java.awt.GridBagLayoutInfo,java.awt.Point,java.awt.event,java.awt.Composite,java.awt.GridLayout,java.awt.PointerInfo,java.awt.font,java.awt.CompositeContext,java.awt.HeadlessException,java.awt.Polygon,java.awt.geom,java.awt.Container,java.awt.IllegalComponentStateException,java.awt.PopupMenu,java.awt.im,java.awt.ContainerOrderFocusTraversalPolicy,java.awt.Image,java.awt.PrintGraphics,java.awt.image,java.awt.Cursor,java.awt.ImageCapabilities,java.awt.PrintJob,java.awt.peer,java.awt.DefaultFocusTraversalPolicy,java.awt.Insets,java.awt.RadialGradientPaint,java.awt.print,java.awt.DefaultKeyboardFocusManager,java.awt.ItemSelectable,java.awt.Rectangle,java.awt.Desktop,java.awt.JobAttributes,java.awt.RenderingHints +EOF + """ +} diff --git a/test/files/run/t7747-repl.check b/test/files/run/t7747-repl.check index 5e0c537a8a43..6e493c48964b 100644 --- a/test/files/run/t7747-repl.check +++ b/test/files/run/t7747-repl.check @@ -268,20 +268,17 @@ package $line10 { val INSTANCE = new $read. } } -package $line10 - +package $line10 { object $eval { lazy val $result = $line10.$read.INSTANCE.$iw.$iw.res3 lazy val $print: _root_.java.lang.String = { $line10.$read.INSTANCE.$iw.$iw - ( "" - + "res3: List[Product with Serializable] = " + _root_.scala.runtime.ScalaRunTime.replStringOf($line10.$read.INSTANCE.$iw.$iw.res3, 1000) - ) - } -} +"" + "res3: List[Product with Serializable] = " + _root_.scala.runtime.ScalaRunTime.replStringOf($line10.$read.INSTANCE.$iw.$iw.res3, 1000) + } +}} res3: List[Product with Serializable] = List(BippyBups(), PuppyPups(), Bingo()) scala> case class Sum(exp: String, exp2: String) From 7aaff78506d803865c4b44368b0dd0ef403b46df Mon Sep 17 00:00:00 2001 From: Som Snytt Date: Tue, 17 Jul 2018 15:24:33 -0700 Subject: [PATCH 058/143] No truncation in REPL tests As they say when R2D2 is trying to shut down the trash compactor, Shut them all down! --- .../tools/nsc/interpreter/shell/ILoop.scala | 21 ++++- test/files/run/t10956.check | 92 ++++++++++++++++++- 2 files changed, 111 insertions(+), 2 deletions(-) diff --git a/src/repl-frontend/scala/tools/nsc/interpreter/shell/ILoop.scala b/src/repl-frontend/scala/tools/nsc/interpreter/shell/ILoop.scala index 3ad87f8c3dd2..dc4aa8e28ded 100644 --- a/src/repl-frontend/scala/tools/nsc/interpreter/shell/ILoop.scala +++ b/src/repl-frontend/scala/tools/nsc/interpreter/shell/ILoop.scala @@ -1012,6 +1012,25 @@ class ILoop(config: ShellConfig, inOverride: BufferedReader = null, object ILoop { implicit def loopToInterpreter(repl: ILoop): Repl = repl.intp + def testConfig(settings: Settings) = + new ShellConfig { + private val delegate = ShellConfig(settings) + + val filesToPaste: List[String] = delegate.filesToPaste + val filesToLoad: List[String] = delegate.filesToLoad + val batchText: String = delegate.batchText + val batchMode: Boolean = delegate.batchMode + val doCompletion: Boolean = delegate.doCompletion + val haveInteractiveConsole: Boolean = delegate.haveInteractiveConsole + + // No truncated output, because the result changes on Windows because of line endings + override val maxPrintString = { + val p = sys.Prop[Int]("wtf") + p.set("0") + p + } + } + // Designed primarily for use by test code: take a String with a // bunch of code, and prints out a transcript of what it would look // like if you'd just typed it into the repl. @@ -1043,7 +1062,7 @@ object ILoop { } } - val config = ShellConfig(settings) + val config = testConfig(settings) val repl = new ILoop(config, input, output) { // remove welcome message as it has versioning info (for reproducible test results), override def welcome = "" diff --git a/test/files/run/t10956.check b/test/files/run/t10956.check index e52daede735f..efb03d233afe 100644 --- a/test/files/run/t10956.check +++ b/test/files/run/t10956.check @@ -34,6 +34,96 @@ import java.awt.Shape import java.awt.ActiveEvent import java.awt.FlowLayout import java.awt.LinearGradientPaint -import java.awt.Splash... +import java.awt.SplashScreen +import java.awt.Adjustable +import java.awt.FocusTraversalPolicy +import java.awt.List +import java.awt.Stroke +import java.awt.AlphaComposite +import java.awt.Font +import java.awt.MediaTracker +import java.awt.SystemColor +import java.awt.BasicStroke +import java.awt.FontFormatException +import java.awt.Menu +import java.awt.SystemTray +import java.awt.BorderLayout +import java.awt.FontMetrics +import java.awt.MenuBar +import java.awt.TextArea +import java.awt.BufferCapabilities +import java.awt.Frame +import java.awt.MenuComponent +import java.awt.TextComponent +import java.awt.Button +import java.awt.GradientPaint +import java.awt.MenuContainer +import java.awt.TextField +import java.awt.Canvas +import java.awt.Graphics +import java.awt.MenuItem +import java.awt.TexturePaint +import java.awt.CardLayout +import java.awt.Graphics2D +import java.awt.MenuShortcut +import java.awt.Toolkit +import java.awt.Checkbox +import java.awt.GraphicsConfigTemplate +import java.awt.MouseInfo +import java.awt.Transparency +import java.awt.CheckboxGroup +import java.awt.GraphicsConfiguration +import java.awt.MultipleGradientPaint +import java.awt.TrayIcon +import java.awt.CheckboxMenuItem +import java.awt.GraphicsDevice +import java.awt.PageAttributes +import java.awt.Window +import java.awt.Choice +import java.awt.GraphicsEnvironment +import java.awt.Paint +import java.awt.color +import java.awt.Color +import java.awt.GridBagConstraints +import java.awt.PaintContext +import java.awt.datatransfer +import java.awt.Component +import java.awt.GridBagLayout +import java.awt.Panel +import java.awt.dnd +import java.awt.ComponentOrientation +import java.awt.GridBagLayoutInfo +import java.awt.Point +import java.awt.event +import java.awt.Composite +import java.awt.GridLayout +import java.awt.PointerInfo +import java.awt.font +import java.awt.CompositeContext +import java.awt.HeadlessException +import java.awt.Polygon +import java.awt.geom +import java.awt.Container +import java.awt.IllegalComponentStateException +import java.awt.PopupMenu +import java.awt.im +import java.awt.ContainerOrderFocusTraversalPolicy +import java.awt.Image +import java.awt.PrintGraphics +import java.awt.image +import java.awt.Cursor +import java.awt.ImageCapabilities +import java.awt.PrintJob +import java.awt.peer +import java.awt.DefaultFocusTraversalPolicy +import java.awt.Insets +import java.awt.RadialGradientPaint +import java.awt.print +import java.awt.DefaultKeyboardFocusManager +import java.awt.ItemSelectable +import java.awt.Rectangle +import java.awt.Desktop +import java.awt.JobAttributes +import java.awt.RenderingHints scala> :quit From 609eafe9db3a088cffa6463bbfab1744266bdafe Mon Sep 17 00:00:00 2001 From: Isaac Levy Date: Mon, 16 Jul 2018 15:35:16 -0400 Subject: [PATCH 059/143] StringBuilder micro opts Also add `append()` --- .../scala/collection/mutable/Builder.scala | 48 +++++++++++++++++-- 1 file changed, 43 insertions(+), 5 deletions(-) diff --git a/src/library/scala/collection/mutable/Builder.scala b/src/library/scala/collection/mutable/Builder.scala index 05beb40b8f07..77022c528d07 100644 --- a/src/library/scala/collection/mutable/Builder.scala +++ b/src/library/scala/collection/mutable/Builder.scala @@ -3,6 +3,16 @@ package scala.collection.mutable import java.lang.String import scala.collection.IterableOnce +import scala.collection.immutable.WrappedString + +import scala.Predef.{ // unimport char-related implicit conversions to avoid triggering them accidentally + genericArrayOps => _, + charArrayOps => _, + genericWrapArray => _, + wrapCharArray => _, + wrapString => _, + _ +} /** Base trait for collection builders */ trait Builder[-A, +To] extends Growable[A] { self => @@ -114,12 +124,12 @@ final class StringBuilder(val underlying: java.lang.StringBuilder) extends Abstr def apply(i: Int): Char = underlying.charAt(i) override protected def fromSpecificIterable(coll: scala.collection.Iterable[Char]): StringBuilder = - new StringBuilder() ++= coll + new StringBuilder() appendAll coll override protected def newSpecificBuilder: Builder[Char, StringBuilder] = new GrowableBuilder(new StringBuilder()) - def length: Int = underlying.length + @inline def length: Int = underlying.length def length_=(n: Int): Unit = underlying.setLength(n) @@ -181,6 +191,21 @@ final class StringBuilder(val underlying: java.lang.StringBuilder) extends Abstr this } + /** Appends the given CharSequence to this sequence. + * + * @param cs a CharSequence. + * @return this StringBuilder. + */ + def append(cs: java.lang.CharSequence): StringBuilder = { + underlying.append(cs match { + // Both cases call into append(), but java SB + // looks up type at runtime and has fast path for SB. + case s: StringBuilder => s.underlying + case _ => cs + }) + this + } + /** Appends the specified string builder to this sequence. * * @param s @@ -196,7 +221,20 @@ final class StringBuilder(val underlying: java.lang.StringBuilder) extends Abstr * @param xs the characters to be appended. * @return this StringBuilder. */ - def appendAll(xs: IterableOnce[Char]): StringBuilder = appendAll(ArrayBuffer.from(xs).toArray) + def appendAll(xs: IterableOnce[Char]): StringBuilder = { + val ks = xs.knownSize + val b = underlying + if (ks != 0) xs match { + case x: WrappedString => b append x.self + case x: ArraySeq.ofChar => b append x.array + case x: StringBuilder => b append x.underlying + case _ => + if (ks > 0) b.ensureCapacity(b.length + ks) + val it = xs.iterator + while (it.hasNext) { b append it.next() } + } + this + } /** Appends all the Chars in the given Array[Char] to this sequence. * @@ -426,7 +464,7 @@ final class StringBuilder(val underlying: java.lang.StringBuilder) extends Abstr * @return The new String. * @throws IndexOutOfBoundsException if the index is out of bounds. */ - def substring(start: Int): String = substring(start, length) + def substring(start: Int): String = underlying.substring(start, length) /** Returns a new String made up of a subsequence of this sequence, * beginning at the start index (inclusive) and extending to the @@ -445,7 +483,7 @@ final class StringBuilder(val underlying: java.lang.StringBuilder) extends Abstr /** For implementing CharSequence. */ def subSequence(start: Int, end: Int): java.lang.CharSequence = - substring(start, end) + underlying.substring(start, end) /** Finds the index of the first occurrence of the specified substring. * From c13e15230039fcc66ef6d6e50901c121eefbcafc Mon Sep 17 00:00:00 2001 From: Som Snytt Date: Mon, 16 Jul 2018 10:46:18 -0700 Subject: [PATCH 060/143] Update javaReflection check for jdk10 --- test/files/jvm/javaReflection.check | 51 +++++------------------------ 1 file changed, 9 insertions(+), 42 deletions(-) diff --git a/test/files/jvm/javaReflection.check b/test/files/jvm/javaReflection.check index 9fb45dde076a..f047ee0797f1 100644 --- a/test/files/jvm/javaReflection.check +++ b/test/files/jvm/javaReflection.check @@ -208,218 +208,185 @@ A / A (canon) / A (simple) - declared cls: List(class A$B, interface A$C, class A$D$) - enclosing : null (declaring cls) / null (cls) / null (constr) / null (meth) - properties : false (local) / false (member) -isAnonymous? false A$$anon$2 / null (canon) / (simple) - declared cls: List() - enclosing : null (declaring cls) / class A (cls) / null (constr) / null (meth) - properties : false (local) / false (member) -isAnonymous? true +assert not class A$$anon$2 is anonymous assert not class A$$anon$2 A$$anon$3 / null (canon) / (simple) - declared cls: List() - enclosing : null (declaring cls) / class A (cls) / null (constr) / public java.lang.Object A.f() (meth) - properties : false (local) / false (member) -isAnonymous? true +assert not class A$$anon$3 is anonymous assert not class A$$anon$3 A$$anon$4 / null (canon) / (simple) - declared cls: List() - enclosing : null (declaring cls) / class A (cls) / null (constr) / public java.lang.Object A.f() (meth) - properties : false (local) / false (member) -isAnonymous? true +assert not class A$$anon$4 is anonymous assert not class A$$anon$4 A$$anon$5 / null (canon) / (simple) - declared cls: List() - enclosing : null (declaring cls) / class A (cls) / null (constr) / null (meth) - properties : false (local) / false (member) -isAnonymous? true +assert not class A$$anon$5 is anonymous assert not class A$$anon$5 A$$anon$6 / null (canon) / (simple) - declared cls: List() - enclosing : null (declaring cls) / class A (cls) / null (constr) / null (meth) - properties : false (local) / false (member) -isAnonymous? true +assert not class A$$anon$6 is anonymous assert not class A$$anon$6 A$$anon$7 / null (canon) / (simple) - declared cls: List() - enclosing : null (declaring cls) / class A (cls) / public A(int) (constr) / null (meth) - properties : false (local) / false (member) -isAnonymous? true +assert not class A$$anon$7 is anonymous assert not class A$$anon$7 A$B / A.B (canon) / B (simple) - declared cls: List() - enclosing : class A (declaring cls) / class A (cls) / null (constr) / null (meth) - properties : false (local) / true (member) -isAnonymous? false A$C / A.C (canon) / C (simple) - declared cls: List() - enclosing : class A (declaring cls) / class A (cls) / null (constr) / null (meth) - properties : false (local) / true (member) -isAnonymous? false A$D$ / A.D$ (canon) / D$ (simple) - declared cls: List(class A$D$B, interface A$D$C, class A$D$D$) - enclosing : class A (declaring cls) / class A (cls) / null (constr) / null (meth) - properties : false (local) / true (member) -isAnonymous? false A$D$$anon$1 / null (canon) / (simple) - declared cls: List() - enclosing : null (declaring cls) / class A$D$ (cls) / null (constr) / null (meth) - properties : false (local) / false (member) -isAnonymous? true +assert not class A$D$$anon$1 is anonymous assert not class A$D$$anon$1 A$D$B / A.D$.B (canon) / B (simple) - declared cls: List() - enclosing : class A$D$ (declaring cls) / class A$D$ (cls) / null (constr) / null (meth) - properties : false (local) / true (member) -isAnonymous? false A$D$C / A.D$.C (canon) / C (simple) - declared cls: List() - enclosing : class A$D$ (declaring cls) / class A$D$ (cls) / null (constr) / null (meth) - properties : false (local) / true (member) -isAnonymous? false A$D$D$ / A.D$.D$ (canon) / D$ (simple) - declared cls: List() - enclosing : class A$D$ (declaring cls) / class A$D$ (cls) / null (constr) / null (meth) - properties : false (local) / true (member) -isAnonymous? false A$D$KB$1 / null (canon) / KB$1 (simple) - declared cls: List() - enclosing : null (declaring cls) / class A$D$ (cls) / null (constr) / public void A$D$.f() (meth) - properties : true (local) / false (member) -isAnonymous? false A$E$1 / null (canon) / E$1 (simple) - declared cls: List() - enclosing : null (declaring cls) / class A (cls) / null (constr) / public java.lang.Object A.f() (meth) - properties : true (local) / false (member) -isAnonymous? false A$F$1 / null (canon) / F$1 (simple) - declared cls: List() - enclosing : null (declaring cls) / class A (cls) / null (constr) / public java.lang.Object A.f() (meth) - properties : true (local) / false (member) -isAnonymous? false A$G$1$ / null (canon) / G$1$ (simple) - declared cls: List() - enclosing : null (declaring cls) / class A (cls) / null (constr) / public java.lang.Object A.f() (meth) - properties : true (local) / false (member) -isAnonymous? false A$H$1 / null (canon) / H$1 (simple) - declared cls: List() - enclosing : null (declaring cls) / class A (cls) / null (constr) / public java.lang.Object A.f() (meth) - properties : true (local) / false (member) -isAnonymous? false A$I$1 / null (canon) / I$1 (simple) - declared cls: List() - enclosing : null (declaring cls) / class A (cls) / null (constr) / public java.lang.Object A.f() (meth) - properties : true (local) / false (member) -isAnonymous? false A$J$1$ / null (canon) / J$1$ (simple) - declared cls: List() - enclosing : null (declaring cls) / class A (cls) / null (constr) / public java.lang.Object A.f() (meth) - properties : true (local) / false (member) -isAnonymous? false A$K$1 / null (canon) / K$1 (simple) - declared cls: List() - enclosing : null (declaring cls) / class A (cls) / null (constr) / null (meth) - properties : true (local) / false (member) -isAnonymous? false A$L$1 / null (canon) / L$1 (simple) - declared cls: List() - enclosing : null (declaring cls) / class A (cls) / null (constr) / null (meth) - properties : true (local) / false (member) -isAnonymous? false A$M$1$ / null (canon) / M$1$ (simple) - declared cls: List() - enclosing : null (declaring cls) / class A (cls) / null (constr) / null (meth) - properties : true (local) / false (member) -isAnonymous? false A$N$1 / null (canon) / N$1 (simple) - declared cls: List() - enclosing : null (declaring cls) / class A (cls) / null (constr) / null (meth) - properties : true (local) / false (member) -isAnonymous? false A$O$1 / null (canon) / O$1 (simple) - declared cls: List() - enclosing : null (declaring cls) / class A (cls) / null (constr) / null (meth) - properties : true (local) / false (member) -isAnonymous? false A$P$1$ / null (canon) / P$1$ (simple) - declared cls: List() - enclosing : null (declaring cls) / class A (cls) / null (constr) / null (meth) - properties : true (local) / false (member) -isAnonymous? false A$Q$1 / null (canon) / Q$1 (simple) - declared cls: List() - enclosing : null (declaring cls) / class A (cls) / public A(int) (constr) / null (meth) - properties : true (local) / false (member) -isAnonymous? false A$R$1 / null (canon) / R$1 (simple) - declared cls: List() - enclosing : null (declaring cls) / class A (cls) / public A(int) (constr) / null (meth) - properties : true (local) / false (member) -isAnonymous? false A$S$1$ / null (canon) / S$1$ (simple) - declared cls: List() - enclosing : null (declaring cls) / class A (cls) / public A(int) (constr) / null (meth) - properties : true (local) / false (member) -isAnonymous? false AO / AO (canon) / AO (simple) - declared cls: List(class AO$B, interface AO$C, class AO$D$) - enclosing : null (declaring cls) / null (cls) / null (constr) / null (meth) - properties : false (local) / false (member) -isAnonymous? false AO$ / AO$ (canon) / AO$ (simple) - declared cls: List() - enclosing : null (declaring cls) / null (cls) / null (constr) / null (meth) - properties : false (local) / false (member) -isAnonymous? false AO$$anon$8 / null (canon) / (simple) - declared cls: List() - enclosing : null (declaring cls) / class AO$ (cls) / null (constr) / null (meth) - properties : false (local) / false (member) -isAnonymous? true +assert not class AO$$anon$8 is anonymous assert not class AO$$anon$8 AO$B / AO.B (canon) / B (simple) - declared cls: List() - enclosing : class AO (declaring cls) / class AO (cls) / null (constr) / null (meth) - properties : false (local) / true (member) -isAnonymous? false AO$C / AO.C (canon) / C (simple) - declared cls: List() - enclosing : class AO (declaring cls) / class AO (cls) / null (constr) / null (meth) - properties : false (local) / true (member) -isAnonymous? false AO$D$ / AO.D$ (canon) / D$ (simple) - declared cls: List() - enclosing : class AO (declaring cls) / class AO (cls) / null (constr) / null (meth) - properties : false (local) / true (member) -isAnonymous? false AT / AT (canon) / AT (simple) - declared cls: List(class AT$B, interface AT$C, class AT$D$) - enclosing : null (declaring cls) / null (cls) / null (constr) / null (meth) - properties : false (local) / false (member) -isAnonymous? false AT$$anon$9 / null (canon) / (simple) - declared cls: List() - enclosing : null (declaring cls) / interface AT (cls) / null (constr) / null (meth) - properties : false (local) / false (member) -isAnonymous? true +assert not class AT$$anon$9 is anonymous assert not class AT$$anon$9 AT$B / AT.B (canon) / B (simple) - declared cls: List() - enclosing : interface AT (declaring cls) / interface AT (cls) / null (constr) / null (meth) - properties : false (local) / true (member) -isAnonymous? false AT$C / AT.C (canon) / C (simple) - declared cls: List() - enclosing : interface AT (declaring cls) / interface AT (cls) / null (constr) / null (meth) - properties : false (local) / true (member) -isAnonymous? false AT$D$ / AT.D$ (canon) / D$ (simple) - declared cls: List() - enclosing : interface AT (declaring cls) / interface AT (cls) / null (constr) / null (meth) - properties : false (local) / true (member) -isAnonymous? false T / T (canon) / T (simple) - declared cls: List() - enclosing : null (declaring cls) / null (cls) / null (constr) / null (meth) - properties : false (local) / false (member) -isAnonymous? false From 7228a8790ddd48b7d2a94e628e081fef95541b7a Mon Sep 17 00:00:00 2001 From: Som Snytt Date: Sun, 1 Jul 2018 08:36:15 -0700 Subject: [PATCH 061/143] More lint pushback It's like cutting back the brush during fire season. Included harmless local parens on methods. --- src/compiler/scala/tools/nsc/ScriptRunner.scala | 2 +- src/compiler/scala/tools/nsc/backend/jvm/BCodeHelpers.scala | 3 +-- src/compiler/scala/tools/nsc/backend/jvm/BTypes.scala | 2 -- .../scala/tools/nsc/backend/jvm/analysis/BackendUtils.scala | 2 +- src/compiler/scala/tools/nsc/profile/Profiler.scala | 2 +- src/compiler/scala/tools/nsc/transform/Erasure.scala | 2 +- 6 files changed, 5 insertions(+), 8 deletions(-) diff --git a/src/compiler/scala/tools/nsc/ScriptRunner.scala b/src/compiler/scala/tools/nsc/ScriptRunner.scala index d5536bd0d10e..e504b82d0e65 100644 --- a/src/compiler/scala/tools/nsc/ScriptRunner.scala +++ b/src/compiler/scala/tools/nsc/ScriptRunner.scala @@ -5,7 +5,7 @@ package scala.tools.nsc -import scala.reflect.io.{Directory, File, Path} +import scala.reflect.io.{Directory, File} import scala.tools.nsc.classpath.DirectoryClassPath import scala.tools.nsc.reporters.{Reporter,ConsoleReporter} import scala.util.control.NonFatal diff --git a/src/compiler/scala/tools/nsc/backend/jvm/BCodeHelpers.scala b/src/compiler/scala/tools/nsc/backend/jvm/BCodeHelpers.scala index a31cc12e2345..0b35b8978477 100644 --- a/src/compiler/scala/tools/nsc/backend/jvm/BCodeHelpers.scala +++ b/src/compiler/scala/tools/nsc/backend/jvm/BCodeHelpers.scala @@ -9,8 +9,7 @@ package backend.jvm import scala.tools.asm import BackendReporting._ -import scala.reflect.internal.Flags -import scala.tools.asm.{ByteVector, ClassWriter} +import scala.tools.asm.ClassWriter import scala.tools.nsc.backend.jvm.BCodeHelpers.ScalaSigBytes import scala.tools.nsc.reporters.NoReporter diff --git a/src/compiler/scala/tools/nsc/backend/jvm/BTypes.scala b/src/compiler/scala/tools/nsc/backend/jvm/BTypes.scala index 59a64a9b338c..564fed864ed4 100644 --- a/src/compiler/scala/tools/nsc/backend/jvm/BTypes.scala +++ b/src/compiler/scala/tools/nsc/backend/jvm/BTypes.scala @@ -6,8 +6,6 @@ package scala.tools.nsc package backend.jvm -import scala.collection.generic.Clearable -import scala.collection.concurrent import scala.tools.asm import scala.tools.asm.Opcodes import scala.tools.nsc.backend.jvm.BTypes.{InlineInfo, InternalName} diff --git a/src/compiler/scala/tools/nsc/backend/jvm/analysis/BackendUtils.scala b/src/compiler/scala/tools/nsc/backend/jvm/analysis/BackendUtils.scala index 0f684b1e3dfb..00309ade46b0 100644 --- a/src/compiler/scala/tools/nsc/backend/jvm/analysis/BackendUtils.scala +++ b/src/compiler/scala/tools/nsc/backend/jvm/analysis/BackendUtils.scala @@ -13,7 +13,7 @@ import scala.tools.asm import scala.tools.asm.Opcodes._ import scala.tools.asm.tree._ import scala.tools.asm.tree.analysis._ -import scala.tools.asm.{Handle, Label, Type} +import scala.tools.asm.{Handle, Type} import scala.tools.nsc.backend.jvm.BTypes._ import scala.tools.nsc.backend.jvm.GenBCode._ import scala.tools.nsc.backend.jvm.analysis.BackendUtils._ diff --git a/src/compiler/scala/tools/nsc/profile/Profiler.scala b/src/compiler/scala/tools/nsc/profile/Profiler.scala index 79b9d3dc8f13..aad73f026ae1 100644 --- a/src/compiler/scala/tools/nsc/profile/Profiler.scala +++ b/src/compiler/scala/tools/nsc/profile/Profiler.scala @@ -124,7 +124,7 @@ private [profile] class RealProfiler(reporter : ProfileReporter, val settings: S } private def readHeapUsage() = RealProfiler.memoryMx.getHeapMemoryUsage.getUsed - private def doGC: Unit = { + private def doGC(): Unit = { System.gc() System.runFinalization() } diff --git a/src/compiler/scala/tools/nsc/transform/Erasure.scala b/src/compiler/scala/tools/nsc/transform/Erasure.scala index aa2bd39059a0..ef0bb02194a5 100644 --- a/src/compiler/scala/tools/nsc/transform/Erasure.scala +++ b/src/compiler/scala/tools/nsc/transform/Erasure.scala @@ -272,7 +272,7 @@ abstract class Erasure extends InfoTransform case _ => boxedSig(tp) } - def classSig: Unit = { + def classSig(): Unit = { markClassUsed(sym) val preRebound = pre.baseType(sym.owner) // #2585 if (needsJavaSig(preRebound, Nil)) { From 0f1980598da6e9639f4fe8f1f78cdcbf042ded16 Mon Sep 17 00:00:00 2001 From: Som Snytt Date: Tue, 3 Jul 2018 22:03:04 -0700 Subject: [PATCH 062/143] -Xlint:serial,implicit-not-found Promote linting implicitNotFound and implicitAmbiguous to -Xlint. Also put warnings about serialVersionUID behind -Xlint. --- .../scala/tools/nsc/settings/Warnings.scala | 4 ++++ .../scala/tools/nsc/typechecker/RefChecks.scala | 13 +++++++------ test/files/jvm/t10610.check | 2 +- test/files/jvm/t10610.scala | 4 +++- test/files/neg/implicit-ambiguous-invalid.scala | 2 +- test/files/neg/t2462b.scala | 2 +- test/files/neg/t6289.flags | 1 - test/files/neg/warn-useless-svuid.scala | 2 +- 8 files changed, 18 insertions(+), 12 deletions(-) delete mode 100644 test/files/neg/t6289.flags diff --git a/src/compiler/scala/tools/nsc/settings/Warnings.scala b/src/compiler/scala/tools/nsc/settings/Warnings.scala index 5cb339b12f5f..2ebe837c875a 100644 --- a/src/compiler/scala/tools/nsc/settings/Warnings.scala +++ b/src/compiler/scala/tools/nsc/settings/Warnings.scala @@ -98,6 +98,8 @@ trait Warnings { val Constant = LintWarning("constant", "Evaluation of a constant arithmetic expression results in an error.") val Unused = LintWarning("unused", "Enable -Ywarn-unused:imports,privates,locals,implicits.") val NonlocalReturn = LintWarning("nonlocal-return", "A return statement used an exception for flow control.") + val ImplicitNotFound = LintWarning("implicit-not-found", "Check @implicitNotFound and @implicitAmbiguous messages.") + val Serial = LintWarning("serial", "@SerialVersionUID on traits and non-serializable classes.") def allLintWarnings = values.toSeq.asInstanceOf[Seq[LintWarning]] } @@ -120,6 +122,8 @@ trait Warnings { def warnConstant = lint contains Constant def lintUnused = lint contains Unused def warnNonlocalReturn = lint contains NonlocalReturn + def lintImplicitNotFound = lint contains ImplicitNotFound + def warnSerialization = lint contains Serial // The Xlint warning group. val lint = MultiChoiceSetting( diff --git a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala index dcf53704266c..1e2ea2e215d8 100644 --- a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala +++ b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala @@ -1416,14 +1416,15 @@ abstract class RefChecks extends Transform { val sym = m.symbol applyChecks(sym.annotations) - def messageWarning(name: String)(warn: String) = - reporter.warning(tree.pos, f"Invalid $name message for ${sym}%s${sym.locationString}%s:%n$warn") - // validate implicitNotFoundMessage and implicitAmbiguousMessage - analyzer.ImplicitNotFoundMsg.check(sym) foreach messageWarning("implicitNotFound") - analyzer.ImplicitAmbiguousMsg.check(sym) foreach messageWarning("implicitAmbiguous") + if (settings.lintImplicitNotFound) { + def messageWarning(name: String)(warn: String) = + reporter.warning(tree.pos, s"Invalid $name message for ${sym}${sym.locationString}:\n$warn") + analyzer.ImplicitNotFoundMsg.check(sym) foreach messageWarning("implicitNotFound") + analyzer.ImplicitAmbiguousMsg.check(sym) foreach messageWarning("implicitAmbiguous") + } - if (sym.isClass && sym.hasAnnotation(SerialVersionUIDAttr)) { + if (settings.warnSerialization && sym.isClass && sym.hasAnnotation(SerialVersionUIDAttr)) { def warn(what: String) = reporter.warning(tree.pos, s"@SerialVersionUID has no effect on $what") diff --git a/test/files/jvm/t10610.check b/test/files/jvm/t10610.check index 20545710cacf..77f552caee30 100644 --- a/test/files/jvm/t10610.check +++ b/test/files/jvm/t10610.check @@ -1,3 +1,3 @@ -t10610.scala:2: warning: @SerialVersionUID has no effect on traits +t10610.scala:4: warning: @SerialVersionUID has no effect on traits trait T ^ diff --git a/test/files/jvm/t10610.scala b/test/files/jvm/t10610.scala index 0ae5bb3b7940..a697bc941c88 100644 --- a/test/files/jvm/t10610.scala +++ b/test/files/jvm/t10610.scala @@ -1,3 +1,5 @@ +// scalac: -Xlint:serial +// @SerialVersionUID(0L) // should have no effect trait T @@ -8,4 +10,4 @@ object Test extends App { } catch { case nsfe: NoSuchFieldException => } -} \ No newline at end of file +} diff --git a/test/files/neg/implicit-ambiguous-invalid.scala b/test/files/neg/implicit-ambiguous-invalid.scala index 1773225297a9..465cd9163d98 100644 --- a/test/files/neg/implicit-ambiguous-invalid.scala +++ b/test/files/neg/implicit-ambiguous-invalid.scala @@ -1,4 +1,4 @@ -// scalac: -Xfatal-warnings +// scalac: -Xlint:implicit-not-found -Xfatal-warnings // object Test { trait =!=[C, D] diff --git a/test/files/neg/t2462b.scala b/test/files/neg/t2462b.scala index 119db2ccbd86..5c80e62dfd34 100644 --- a/test/files/neg/t2462b.scala +++ b/test/files/neg/t2462b.scala @@ -1,4 +1,4 @@ -// scalac: -Xfatal-warnings +// scalac: -Xlint:implicit-not-found -Xfatal-warnings // package test diff --git a/test/files/neg/t6289.flags b/test/files/neg/t6289.flags deleted file mode 100644 index 85d8eb2ba295..000000000000 --- a/test/files/neg/t6289.flags +++ /dev/null @@ -1 +0,0 @@ --Xfatal-warnings diff --git a/test/files/neg/warn-useless-svuid.scala b/test/files/neg/warn-useless-svuid.scala index 41ae14f9fb47..25882dc1bcd6 100644 --- a/test/files/neg/warn-useless-svuid.scala +++ b/test/files/neg/warn-useless-svuid.scala @@ -1,4 +1,4 @@ -// scalac: -Xfatal-warnings +// scalac: -Xlint:serial -Xfatal-warnings // @SerialVersionUID(1L) class X From 510c66d975339ac02ce5294a463d4cb861e8a0b6 Mon Sep 17 00:00:00 2001 From: Som Snytt Date: Wed, 4 Jul 2018 14:44:25 -0700 Subject: [PATCH 063/143] Deprecate early definitions Under -Xsource:2.14, offer trait parameters, otherwise the mirage of a distant oasis. Delete some flags files to balance additional check files. --- .../scala/tools/nsc/ast/parser/Parsers.scala | 5 ++ test/files/neg/early-type-defs.check | 8 +- test/files/neg/early-type-defs.scala | 3 +- test/files/neg/t2796.check | 15 +++- test/files/neg/t2796.scala | 1 + test/files/neg/t6595.check | 6 ++ test/files/{pos => neg}/t6595.scala | 2 +- test/files/neg/warn-unused-privates.check | 83 ++++++++++--------- test/files/neg/warn-unused-privates.scala | 3 +- test/files/presentation/doc.check | 1 + test/files/run/analyzerPlugins.check | 1 + test/files/run/ctor-order.check | 1 + test/files/run/delay-bad.check | 4 +- test/files/run/delay-good.check | 1 + .../files/run/deprecate-early-type-defs.check | 3 + test/files/run/outertest.check | 1 + test/files/run/preinits.check | 1 + test/files/run/t0911.check | 1 + test/files/run/t4680.check | 4 +- test/files/run/t5603.check | 1 + test/files/run/t6259.check | 1 + test/files/run/t6309.check | 1 + test/files/specialized/spec-early.check | 3 +- test/scaladoc/run/t7767.check | 1 + 24 files changed, 100 insertions(+), 51 deletions(-) create mode 100644 test/files/neg/t6595.check rename test/files/{pos => neg}/t6595.scala (91%) create mode 100644 test/files/run/outertest.check create mode 100644 test/files/run/t0911.check create mode 100644 test/files/run/t6259.check diff --git a/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala b/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala index 501be6f489f6..64ed3697994e 100644 --- a/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala +++ b/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala @@ -3000,9 +3000,14 @@ self => def template(): (List[Tree], ValDef, List[Tree]) = { newLineOptWhenFollowedBy(LBRACE) if (in.token == LBRACE) { + val braceOffset = in.offset // @S: pre template body cannot stub like post body can! val (self, body) = templateBody(isPre = true) if (in.token == WITH && (self eq noSelfType)) { + val advice = + if (settings.isScala214) "use trait parameters instead." + else "they will be replaced by trait parameters in 2.14, see the migration guide on avoiding var/val in traits." + deprecationWarning(braceOffset, s"early initializers are deprecated; $advice", "2.13.0") val earlyDefs: List[Tree] = body.map(ensureEarlyDef).filter(_.nonEmpty) in.nextToken() val parents = templateParents() diff --git a/test/files/neg/early-type-defs.check b/test/files/neg/early-type-defs.check index cb2f99837182..a98871104a4f 100644 --- a/test/files/neg/early-type-defs.check +++ b/test/files/neg/early-type-defs.check @@ -1,4 +1,8 @@ -early-type-defs.scala:3: error: early type members are unsupported: move them to the regular body; the semantics are the same -object Test extends { type A1 = Int } with App +early-type-defs.scala:4: warning: early initializers are deprecated; use trait parameters instead. +object Test extends { type A1 = Int } with Runnable { def run() = () } + ^ +early-type-defs.scala:4: error: early type members are unsupported: move them to the regular body; the semantics are the same +object Test extends { type A1 = Int } with Runnable { def run() = () } ^ +one warning found one error found diff --git a/test/files/neg/early-type-defs.scala b/test/files/neg/early-type-defs.scala index 6b01ceb8d01d..2ab2505a0d38 100644 --- a/test/files/neg/early-type-defs.scala +++ b/test/files/neg/early-type-defs.scala @@ -1,3 +1,4 @@ +// // scalac: -deprecation -Xsource:2.14 // -object Test extends { type A1 = Int } with App +object Test extends { type A1 = Int } with Runnable { def run() = () } diff --git a/test/files/neg/t2796.check b/test/files/neg/t2796.check index cc2376449526..375024a5b284 100644 --- a/test/files/neg/t2796.check +++ b/test/files/neg/t2796.check @@ -1,9 +1,18 @@ -t2796.scala:13: warning: early type members are deprecated: move them to the regular body; the semantics are the same +t2796.scala:9: warning: early initializers are deprecated; they will be replaced by trait parameters in 2.14, see the migration guide on avoiding var/val in traits. +trait T1 extends { + ^ +t2796.scala:13: warning: early initializers are deprecated; they will be replaced by trait parameters in 2.14, see the migration guide on avoiding var/val in traits. +trait T2 extends { + ^ +t2796.scala:14: warning: early type members are deprecated: move them to the regular body; the semantics are the same type X = Int // warn ^ -t2796.scala:9: warning: Implementation restriction: early definitions in traits are not initialized before the super class is initialized. +t2796.scala:17: warning: early initializers are deprecated; they will be replaced by trait parameters in 2.14, see the migration guide on avoiding var/val in traits. +class C1 extends { + ^ +t2796.scala:10: warning: Implementation restriction: early definitions in traits are not initialized before the super class is initialized. val abstractVal = "T1.abstractVal" // warn ^ error: No warnings can be incurred under -Xfatal-warnings. -two warnings found +5 warnings found one error found diff --git a/test/files/neg/t2796.scala b/test/files/neg/t2796.scala index 89a5e36c78df..4bf0d2168baf 100644 --- a/test/files/neg/t2796.scala +++ b/test/files/neg/t2796.scala @@ -1,3 +1,4 @@ +// // scalac: -deprecation -Xfatal-warnings // trait Base { diff --git a/test/files/neg/t6595.check b/test/files/neg/t6595.check new file mode 100644 index 000000000000..4b3bb27cf0e9 --- /dev/null +++ b/test/files/neg/t6595.check @@ -0,0 +1,6 @@ +t6595.scala:5: warning: early initializers are deprecated; they will be replaced by trait parameters in 2.14, see the migration guide on avoiding var/val in traits. +class Foo extends { + ^ +error: No warnings can be incurred under -Xfatal-warnings. +one warning found +one error found diff --git a/test/files/pos/t6595.scala b/test/files/neg/t6595.scala similarity index 91% rename from test/files/pos/t6595.scala rename to test/files/neg/t6595.scala index 2371f9780737..f64275ba794b 100644 --- a/test/files/pos/t6595.scala +++ b/test/files/neg/t6595.scala @@ -1,4 +1,4 @@ -// scalac: -Xfatal-warnings +// scalac: -Xfatal-warnings -deprecation // import scala.annotation.switch diff --git a/test/files/neg/warn-unused-privates.check b/test/files/neg/warn-unused-privates.check index 6eafbc7fafa5..2312bd991716 100644 --- a/test/files/neg/warn-unused-privates.check +++ b/test/files/neg/warn-unused-privates.check @@ -1,120 +1,123 @@ -warn-unused-privates.scala:4: warning: private constructor in class Bippy is never used +warn-unused-privates.scala:31: warning: early initializers are deprecated; they will be replaced by trait parameters in 2.14, see the migration guide on avoiding var/val in traits. +class Boppy extends { + ^ +warn-unused-privates.scala:5: warning: private constructor in class Bippy is never used private def this(c: Int) = this(c, c) // warn ^ -warn-unused-privates.scala:6: warning: private method boop in class Bippy is never used +warn-unused-privates.scala:7: warning: private method boop in class Bippy is never used private def boop(x: Int) = x+a+b // warn ^ -warn-unused-privates.scala:8: warning: private val MILLIS2 in class Bippy is never used +warn-unused-privates.scala:9: warning: private val MILLIS2 in class Bippy is never used final private val MILLIS2: Int = 1000 // warn ^ -warn-unused-privates.scala:15: warning: private val HEY_INSTANCE in object Bippy is never used +warn-unused-privates.scala:16: warning: private val HEY_INSTANCE in object Bippy is never used private val HEY_INSTANCE: Int = 1000 // warn ^ -warn-unused-privates.scala:16: warning: private val BOOL in object Bippy is never used +warn-unused-privates.scala:17: warning: private val BOOL in object Bippy is never used private lazy val BOOL: Boolean = true // warn ^ -warn-unused-privates.scala:40: warning: private val hummer in class Boppy is never used +warn-unused-privates.scala:41: warning: private val hummer in class Boppy is never used private val hummer = "def" // warn ^ -warn-unused-privates.scala:47: warning: private var v1 in trait Accessors is never used +warn-unused-privates.scala:48: warning: private var v1 in trait Accessors is never used private var v1: Int = 0 // warn ^ -warn-unused-privates.scala:48: warning: private var v2 in trait Accessors is never used +warn-unused-privates.scala:49: warning: private var v2 in trait Accessors is never used private var v2: Int = 0 // warn, never set ^ -warn-unused-privates.scala:49: warning: private var v3 in trait Accessors is never used +warn-unused-privates.scala:50: warning: private var v3 in trait Accessors is never used private var v3: Int = 0 // warn, never got ^ -warn-unused-privates.scala:60: warning: private var s1 in class StableAccessors is never used +warn-unused-privates.scala:61: warning: private var s1 in class StableAccessors is never used private var s1: Int = 0 // warn ^ -warn-unused-privates.scala:61: warning: private var s2 in class StableAccessors is never updated: consider using immutable val +warn-unused-privates.scala:62: warning: private var s2 in class StableAccessors is never updated: consider using immutable val private var s2: Int = 0 // warn, never set ^ -warn-unused-privates.scala:62: warning: private var s3 in class StableAccessors is never used +warn-unused-privates.scala:63: warning: private var s3 in class StableAccessors is never used private var s3: Int = 0 // warn, never got ^ -warn-unused-privates.scala:74: warning: private default argument in trait DefaultArgs is never used +warn-unused-privates.scala:75: warning: private default argument in trait DefaultArgs is never used private def bippy(x1: Int, x2: Int = 10, x3: Int = 15): Int = x1 + x2 + x3 ^ -warn-unused-privates.scala:74: warning: private default argument in trait DefaultArgs is never used +warn-unused-privates.scala:75: warning: private default argument in trait DefaultArgs is never used private def bippy(x1: Int, x2: Int = 10, x3: Int = 15): Int = x1 + x2 + x3 ^ -warn-unused-privates.scala:90: warning: local var x in method f0 is never used +warn-unused-privates.scala:91: warning: local var x in method f0 is never used var x = 1 // warn ^ -warn-unused-privates.scala:97: warning: local val b in method f1 is never used +warn-unused-privates.scala:98: warning: local val b in method f1 is never used val b = new Outer // warn ^ -warn-unused-privates.scala:107: warning: private object Dongo in object Types is never used +warn-unused-privates.scala:108: warning: private object Dongo in object Types is never used private object Dongo { def f = this } // warn ^ -warn-unused-privates.scala:117: warning: local object HiObject in method l1 is never used +warn-unused-privates.scala:118: warning: local object HiObject in method l1 is never used object HiObject { def f = this } // warn ^ -warn-unused-privates.scala:140: warning: private method x_= in class OtherNames is never used +warn-unused-privates.scala:141: warning: private method x_= in class OtherNames is never used private def x_=(i: Int): Unit = () ^ -warn-unused-privates.scala:141: warning: private method x in class OtherNames is never used +warn-unused-privates.scala:142: warning: private method x in class OtherNames is never used private def x: Int = 42 ^ -warn-unused-privates.scala:142: warning: private method y_= in class OtherNames is never used +warn-unused-privates.scala:143: warning: private method y_= in class OtherNames is never used private def y_=(i: Int): Unit = () ^ -warn-unused-privates.scala:101: warning: local var x in method f2 is never updated: consider using immutable val +warn-unused-privates.scala:102: warning: local var x in method f2 is never updated: consider using immutable val var x = 100 // warn about it being a var ^ -warn-unused-privates.scala:108: warning: private class Bar1 in object Types is never used +warn-unused-privates.scala:109: warning: private class Bar1 in object Types is never used private class Bar1 // warn ^ -warn-unused-privates.scala:110: warning: private type Alias1 in object Types is never used +warn-unused-privates.scala:111: warning: private type Alias1 in object Types is never used private type Alias1 = String // warn ^ -warn-unused-privates.scala:118: warning: local class Hi is never used +warn-unused-privates.scala:119: warning: local class Hi is never used class Hi { // warn ^ -warn-unused-privates.scala:122: warning: local class DingDongDoobie is never used +warn-unused-privates.scala:123: warning: local class DingDongDoobie is never used class DingDongDoobie // warn ^ -warn-unused-privates.scala:125: warning: local type OtherThing is never used +warn-unused-privates.scala:126: warning: local type OtherThing is never used type OtherThing = String // warn ^ -warn-unused-privates.scala:220: warning: private class for your eyes only in object not even using companion privates is never used +warn-unused-privates.scala:221: warning: private class for your eyes only in object not even using companion privates is never used private implicit class `for your eyes only`(i: Int) { // warn ^ -warn-unused-privates.scala:236: warning: private class D in class nonprivate alias is enclosing is never used +warn-unused-privates.scala:237: warning: private class D in class nonprivate alias is enclosing is never used private class D extends C2 // warn ^ -warn-unused-privates.scala:157: warning: pattern var x in method f is never used; `x@_' suppresses this warning +warn-unused-privates.scala:158: warning: pattern var x in method f is never used; `x@_' suppresses this warning val C(x, y, Some(z)) = c // warn ^ -warn-unused-privates.scala:157: warning: pattern var y in method f is never used; `y@_' suppresses this warning +warn-unused-privates.scala:158: warning: pattern var y in method f is never used; `y@_' suppresses this warning val C(x, y, Some(z)) = c // warn ^ -warn-unused-privates.scala:157: warning: pattern var z in method f is never used; `z@_' suppresses this warning +warn-unused-privates.scala:158: warning: pattern var z in method f is never used; `z@_' suppresses this warning val C(x, y, Some(z)) = c // warn ^ -warn-unused-privates.scala:165: warning: pattern var z in method h is never used; `z@_' suppresses this warning +warn-unused-privates.scala:166: warning: pattern var z in method h is never used; `z@_' suppresses this warning val C(x @ _, y @ _, z @ Some(_)) = c // warn for z? ^ -warn-unused-privates.scala:170: warning: pattern var x in method v is never used; `x@_' suppresses this warning +warn-unused-privates.scala:171: warning: pattern var x in method v is never used; `x@_' suppresses this warning val D(x) = d // warn ^ -warn-unused-privates.scala:205: warning: pattern var z in method f is never used; `z@_' suppresses this warning +warn-unused-privates.scala:206: warning: pattern var z in method f is never used; `z@_' suppresses this warning case z => "warn" ^ -warn-unused-privates.scala:212: warning: pattern var z in method f is never used; `z@_' suppresses this warning +warn-unused-privates.scala:213: warning: pattern var z in method f is never used; `z@_' suppresses this warning case Some(z) => "warn" ^ -warn-unused-privates.scala:22: warning: parameter value msg0 in class B3 is never used +warn-unused-privates.scala:23: warning: parameter value msg0 in class B3 is never used class B3(msg0: String) extends A("msg") ^ -warn-unused-privates.scala:140: warning: parameter value i in method x_= is never used +warn-unused-privates.scala:141: warning: parameter value i in method x_= is never used private def x_=(i: Int): Unit = () ^ -warn-unused-privates.scala:142: warning: parameter value i in method y_= is never used +warn-unused-privates.scala:143: warning: parameter value i in method y_= is never used private def y_=(i: Int): Unit = () ^ error: No warnings can be incurred under -Xfatal-warnings. -39 warnings found +40 warnings found one error found diff --git a/test/files/neg/warn-unused-privates.scala b/test/files/neg/warn-unused-privates.scala index 2b0fcee460c7..a9c4981e57b3 100644 --- a/test/files/neg/warn-unused-privates.scala +++ b/test/files/neg/warn-unused-privates.scala @@ -1,4 +1,5 @@ -// scalac: -Ywarn-unused -Xfatal-warnings +// +// scalac: -deprecation -Ywarn-unused -Xfatal-warnings // class Bippy(a: Int, b: Int) { private def this(c: Int) = this(c, c) // warn diff --git a/test/files/presentation/doc.check b/test/files/presentation/doc.check index 5a3ff13151de..13de0fe7dfe4 100644 --- a/test/files/presentation/doc.check +++ b/test/files/presentation/doc.check @@ -1 +1,2 @@ +warning: there was one deprecation warning (since 2.13.0); re-run with -deprecation for details reload: Base.scala, Class.scala, Derived.scala diff --git a/test/files/run/analyzerPlugins.check b/test/files/run/analyzerPlugins.check index 8142bde0f660..248196bfb872 100644 --- a/test/files/run/analyzerPlugins.check +++ b/test/files/run/analyzerPlugins.check @@ -1,3 +1,4 @@ +warning: there was one deprecation warning (since 2.13.0); re-run with -deprecation for details adaptBoundsToAnnots(List( <: Int), List(type T), List(Int @testAnn)) [2] annotationsConform(Boolean @testAnn, Boolean @testAnn) [2] annotationsConform(Boolean @testAnn, Boolean) [1] diff --git a/test/files/run/ctor-order.check b/test/files/run/ctor-order.check index b2f7f08c1707..1fdf99fa3d90 100644 --- a/test/files/run/ctor-order.check +++ b/test/files/run/ctor-order.check @@ -1,2 +1,3 @@ +warning: there was one deprecation warning (since 2.13.0); re-run with -deprecation for details 10 10 diff --git a/test/files/run/delay-bad.check b/test/files/run/delay-bad.check index bf41c79a3a6c..066272abea32 100644 --- a/test/files/run/delay-bad.check +++ b/test/files/run/delay-bad.check @@ -4,7 +4,9 @@ delay-bad.scala:53: warning: a pure expression does nothing in statement positio delay-bad.scala:73: warning: a pure expression does nothing in statement position; multiline expressions may require enclosing parentheses f(new { val x = 5 } with E() { 5 }) ^ -warning: there was one deprecation warning (since 2.11.0); re-run with -deprecation for details +warning: there was one deprecation warning (since 2.11.0) +warning: there were four deprecation warnings (since 2.13.0) +warning: there were 5 deprecation warnings in total; re-run with -deprecation for details // new C { } diff --git a/test/files/run/delay-good.check b/test/files/run/delay-good.check index ed35b9225ffb..6f3afc5d8d9e 100644 --- a/test/files/run/delay-good.check +++ b/test/files/run/delay-good.check @@ -4,6 +4,7 @@ delay-good.scala:53: warning: a pure expression does nothing in statement positi delay-good.scala:73: warning: a pure expression does nothing in statement position; multiline expressions may require enclosing parentheses f(new { val x = 5 } with E() { 5 }) ^ +warning: there were four deprecation warnings (since 2.13.0); re-run with -deprecation for details // new C { } diff --git a/test/files/run/deprecate-early-type-defs.check b/test/files/run/deprecate-early-type-defs.check index 45af8442a088..89e64a9fb6d8 100644 --- a/test/files/run/deprecate-early-type-defs.check +++ b/test/files/run/deprecate-early-type-defs.check @@ -1,3 +1,6 @@ +deprecate-early-type-defs.scala:3: warning: early initializers are deprecated; they will be replaced by trait parameters in 2.14, see the migration guide on avoiding var/val in traits. +object Test extends { type T = Int } with App + ^ deprecate-early-type-defs.scala:3: warning: early type members are deprecated: move them to the regular body; the semantics are the same object Test extends { type T = Int } with App ^ diff --git a/test/files/run/outertest.check b/test/files/run/outertest.check new file mode 100644 index 000000000000..39cf8903b75d --- /dev/null +++ b/test/files/run/outertest.check @@ -0,0 +1 @@ +warning: there was one deprecation warning (since 2.13.0); re-run with -deprecation for details diff --git a/test/files/run/preinits.check b/test/files/run/preinits.check index e97a14b77f5c..4c3ba61f3025 100644 --- a/test/files/run/preinits.check +++ b/test/files/run/preinits.check @@ -4,6 +4,7 @@ trait B extends { override val x = 1 } with A { println("B") } preinits.scala:3: warning: Implementation restriction: early definitions in traits are not initialized before the super class is initialized. trait C extends { override val x = 2 } with A ^ +warning: there were two deprecation warnings (since 2.13.0); re-run with -deprecation for details A B 2 diff --git a/test/files/run/t0911.check b/test/files/run/t0911.check new file mode 100644 index 000000000000..39cf8903b75d --- /dev/null +++ b/test/files/run/t0911.check @@ -0,0 +1 @@ +warning: there was one deprecation warning (since 2.13.0); re-run with -deprecation for details diff --git a/test/files/run/t4680.check b/test/files/run/t4680.check index 749ce4c62734..b30a15feef66 100644 --- a/test/files/run/t4680.check +++ b/test/files/run/t4680.check @@ -4,7 +4,9 @@ t4680.scala:51: warning: a pure expression does nothing in statement position; m t4680.scala:69: warning: a pure expression does nothing in statement position; multiline expressions may require enclosing parentheses new { val x = 5 } with E() { 5 } ^ -warning: there was one deprecation warning (since 2.11.0); re-run with -deprecation for details +warning: there was one deprecation warning (since 2.11.0) +warning: there were four deprecation warnings (since 2.13.0) +warning: there were 5 deprecation warnings in total; re-run with -deprecation for details // new C { } diff --git a/test/files/run/t5603.check b/test/files/run/t5603.check index 760a92567ca7..0b848fc4b786 100644 --- a/test/files/run/t5603.check +++ b/test/files/run/t5603.check @@ -27,3 +27,4 @@ } } +warning: there was one deprecation warning (since 2.13.0); re-run with -deprecation for details diff --git a/test/files/run/t6259.check b/test/files/run/t6259.check new file mode 100644 index 000000000000..39cf8903b75d --- /dev/null +++ b/test/files/run/t6259.check @@ -0,0 +1 @@ +warning: there was one deprecation warning (since 2.13.0); re-run with -deprecation for details diff --git a/test/files/run/t6309.check b/test/files/run/t6309.check index 7f8f011eb73d..2ea752191f42 100644 --- a/test/files/run/t6309.check +++ b/test/files/run/t6309.check @@ -1 +1,2 @@ +warning: there was one deprecation warning (since 2.13.0); re-run with -deprecation for details 7 diff --git a/test/files/specialized/spec-early.check b/test/files/specialized/spec-early.check index 9c578a1af1fc..147d056bf1f5 100644 --- a/test/files/specialized/spec-early.check +++ b/test/files/specialized/spec-early.check @@ -1,5 +1,6 @@ +warning: there was one deprecation warning (since 2.13.0); re-run with -deprecation for details a abc 42 abc -2 \ No newline at end of file +2 diff --git a/test/scaladoc/run/t7767.check b/test/scaladoc/run/t7767.check index 619c56180bb9..ccd3bc7fb74e 100644 --- a/test/scaladoc/run/t7767.check +++ b/test/scaladoc/run/t7767.check @@ -1 +1,2 @@ +warning: there were two deprecation warnings (since 2.13.0); re-run with -deprecation for details Done. From 6cac1203a1e1d432bde41a6ced9f12bea1fa4654 Mon Sep 17 00:00:00 2001 From: xuwei-k <6b656e6a69@gmail.com> Date: Fri, 20 Jul 2018 09:46:33 +0900 Subject: [PATCH 064/143] override Range#distinct Range does not have duplicate element --- src/library/scala/collection/immutable/Range.scala | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/library/scala/collection/immutable/Range.scala b/src/library/scala/collection/immutable/Range.scala index 5a8a41051189..315014e57bd8 100644 --- a/src/library/scala/collection/immutable/Range.scala +++ b/src/library/scala/collection/immutable/Range.scala @@ -382,6 +382,8 @@ sealed abstract class Range( final override protected[this] def writeReplace(): AnyRef = this override protected[this] def className = "Range" + + override def distinct: Range = this } /** From 4070df494d749feb7e796750871b2814c46b4ccd Mon Sep 17 00:00:00 2001 From: Stefan Zeiger Date: Thu, 28 Jun 2018 11:38:50 +0200 Subject: [PATCH 065/143] Build speclib/instrumented.jar for partest - Build automatically from sources instead of fetching a pre-built binary which can get out of date and needs to be updated manually - Remove outdated build script (from the ant days) --- build.sbt | 37 +- project/plugins.sbt | 3 +- .../library/scala/runtime/BoxesRunTime.java | 778 ------------------ .../library/scala/runtime/ScalaRunTime.scala | 290 ------- test/instrumented/mkinstrumented.sh | 50 -- 5 files changed, 35 insertions(+), 1123 deletions(-) delete mode 100644 test/instrumented/library/scala/runtime/BoxesRunTime.java delete mode 100644 test/instrumented/library/scala/runtime/ScalaRunTime.scala delete mode 100755 test/instrumented/mkinstrumented.sh diff --git a/build.sbt b/build.sbt index 1b9e729d34b7..fc3527531bc6 100644 --- a/build.sbt +++ b/build.sbt @@ -57,8 +57,7 @@ val partestDependencies = Seq( "methvsfield" -> "be8454d5e7751b063ade201c225dcedefd252775", "nest" -> "cd33e0a0ea249eb42363a2f8ba531186345ff68c" ).map(bootstrapDep("test/files/lib")) ++ Seq( - bootstrapDep("test/files/codelib")("code" -> "e737b123d31eede5594ceda07caafed1673ec472") % "test", - bootstrapDep("test/files/speclib")("instrumented" -> "d015eff38243f1c2edb44ac3b6a0ce99bc5656db") % "test" + bootstrapDep("test/files/codelib")("code" -> "e737b123d31eede5594ceda07caafed1673ec472") % "test" ) lazy val publishSettings : Seq[Setting[_]] = Seq( @@ -552,6 +551,36 @@ lazy val scalacheckLib = project.in(file("src") / "scalacheck") libraryDependencies += testInterfaceDep ) +// An instrumented version of BoxesRunTime and ScalaRunTime for partest's "specialized" test category +lazy val specLib = project.in(file("test") / "instrumented") + .dependsOn(library, reflect, compiler) + .settings(clearSourceAndResourceDirectories) + .settings(commonSettings) + .settings(disableDocs) + .settings(disablePublishing) + .settings( + sourceGenerators in Compile += Def.task { + import scala.collection.JavaConverters._ + val srcBase = (sourceDirectories in Compile in library).value.head / "scala/runtime" + val targetBase = (sourceManaged in Compile).value / "scala/runtime" + def patch(srcFile: String, patchFile: String): File = try { + val p = difflib.DiffUtils.parseUnifiedDiff(IO.readLines(baseDirectory.value / patchFile).asJava) + val r = difflib.DiffUtils.patch(IO.readLines(srcBase / srcFile).asJava, p) + val target = targetBase / srcFile + IO.writeLines(target, r.asScala) + target + } catch { case ex: Exception => + streams.value.log.error(s"Error patching $srcFile: $ex") + throw ex + } + IO.createDirectory(targetBase) + Seq( + patch("BoxesRunTime.java", "boxes.patch"), + patch("ScalaRunTime.scala", "srt.patch") + ) + }.taskValue + ) + // The scala version used by the benchmark suites, leave undefined to use the ambient version.") def benchmarkScalaVersion = System.getProperty("benchmark.scala.version", "") @@ -703,9 +732,9 @@ lazy val test = project testOptions in IntegrationTest += Tests.Setup { () => val cp = (dependencyClasspath in Test).value val baseDir = (baseDirectory in ThisBuild).value - // Copy code.jar and instrumented.jar (resolved in the otherwise unused scope "test") to the location where partest expects them + // Copy code.jar (resolved in the otherwise unused scope "test") and instrumented.jar (from specLib) to the location where partest expects them copyBootstrapJar(cp, baseDir, "test/files/codelib", "code") - copyBootstrapJar(cp, baseDir, "test/files/speclib", "instrumented") + IO.copyFile((packagedArtifact in (LocalProject("specLib"), Compile, packageBin)).value._2, baseDir / "test/files/speclib/instrumented.jar") }, definedTests in IntegrationTest += new sbt.TestDefinition( "partest", diff --git a/project/plugins.sbt b/project/plugins.sbt index 05042d223eaa..e6fe74547ebc 100644 --- a/project/plugins.sbt +++ b/project/plugins.sbt @@ -23,7 +23,8 @@ addSbtPlugin("com.typesafe" % "sbt-mima-plugin" % "0.1.15") libraryDependencies ++= Seq( "org.eclipse.jgit" % "org.eclipse.jgit" % "4.6.0.201612231935-r", - "org.slf4j" % "slf4j-nop" % "1.7.23" + "org.slf4j" % "slf4j-nop" % "1.7.23", + "com.googlecode.java-diff-utils" % "diffutils" % "1.3.0" ) concurrentRestrictions in Global := Seq( diff --git a/test/instrumented/library/scala/runtime/BoxesRunTime.java b/test/instrumented/library/scala/runtime/BoxesRunTime.java deleted file mode 100644 index d79a99b88c43..000000000000 --- a/test/instrumented/library/scala/runtime/BoxesRunTime.java +++ /dev/null @@ -1,778 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2006-2013, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -/* INSTRUMENTED VERSION */ - -package scala.runtime; - -import scala.math.ScalaNumber; - -/** An object (static class) that defines methods used for creating, - * reverting, and calculating with, boxed values. There are four classes - * of methods in this object: - * - Convenience boxing methods which call the static valueOf method - * on the boxed class, thus utilizing the JVM boxing cache. - * - Convenience unboxing methods returning default value on null. - * - The generalised comparison method to be used when an object may - * be a boxed value. - * - Standard value operators for boxed number and quasi-number values. - * - * @author Gilles Dubochet - * @author Martin Odersky - * @contributor Stepan Koltsov - * @version 2.0 */ -public final class BoxesRunTime -{ - private static final int CHAR = 0, /* BYTE = 1, SHORT = 2, */ INT = 3, LONG = 4, FLOAT = 5, DOUBLE = 6, OTHER = 7; - - /** We don't need to return BYTE and SHORT, as everything which might - * care widens to INT. - */ - private static int typeCode(Object a) { - if (a instanceof java.lang.Integer) return INT; - if (a instanceof java.lang.Double) return DOUBLE; - if (a instanceof java.lang.Long) return LONG; - if (a instanceof java.lang.Character) return CHAR; - if (a instanceof java.lang.Float) return FLOAT; - if ((a instanceof java.lang.Byte) || (a instanceof java.lang.Short)) return INT; - return OTHER; - } - -/* BOXING ... BOXING ... BOXING ... BOXING ... BOXING ... BOXING ... BOXING ... BOXING */ - public static int booleanBoxCount = 0; - public static int characterBoxCount = 0; - public static int byteBoxCount = 0; - public static int shortBoxCount = 0; - public static int integerBoxCount = 0; - public static int longBoxCount = 0; - public static int floatBoxCount = 0; - public static int doubleBoxCount = 0; - - public static java.lang.Boolean boxToBoolean(boolean b) { - booleanBoxCount += 1; - return java.lang.Boolean.valueOf(b); - } - - public static java.lang.Character boxToCharacter(char c) { - characterBoxCount += 1; - return java.lang.Character.valueOf(c); - } - - public static java.lang.Byte boxToByte(byte b) { - byteBoxCount += 1; - return java.lang.Byte.valueOf(b); - } - - public static java.lang.Short boxToShort(short s) { - shortBoxCount += 1; - return java.lang.Short.valueOf(s); - } - - public static java.lang.Integer boxToInteger(int i) { - integerBoxCount += 1; - return java.lang.Integer.valueOf(i); - } - - public static java.lang.Long boxToLong(long l) { - longBoxCount += 1; - return java.lang.Long.valueOf(l); - } - - public static java.lang.Float boxToFloat(float f) { - floatBoxCount += 1; - return java.lang.Float.valueOf(f); - } - - public static java.lang.Double boxToDouble(double d) { - // System.out.println("box " + d); - // (new Throwable()).printStackTrace(); - doubleBoxCount += 1; - return java.lang.Double.valueOf(d); - } - -/* UNBOXING ... UNBOXING ... UNBOXING ... UNBOXING ... UNBOXING ... UNBOXING ... UNBOXING */ - - public static boolean unboxToBoolean(Object b) { - return b == null ? false : ((java.lang.Boolean)b).booleanValue(); - } - - public static char unboxToChar(Object c) { - return c == null ? 0 : ((java.lang.Character)c).charValue(); - } - - public static byte unboxToByte(Object b) { - return b == null ? 0 : ((java.lang.Byte)b).byteValue(); - } - - public static short unboxToShort(Object s) { - return s == null ? 0 : ((java.lang.Short)s).shortValue(); - } - - public static int unboxToInt(Object i) { - return i == null ? 0 : ((java.lang.Integer)i).intValue(); - } - - public static long unboxToLong(Object l) { - return l == null ? 0 : ((java.lang.Long)l).longValue(); - } - - public static float unboxToFloat(Object f) { - return f == null ? 0.0f : ((java.lang.Float)f).floatValue(); - } - - public static double unboxToDouble(Object d) { - // System.out.println("unbox " + d); - return d == null ? 0.0d : ((java.lang.Double)d).doubleValue(); - } - - /* COMPARISON ... COMPARISON ... COMPARISON ... COMPARISON ... COMPARISON ... COMPARISON */ - - public static boolean equals(Object x, Object y) { - if (x == y) return true; - return equals2(x, y); - } - - /** Since all applicable logic has to be present in the equals method of a ScalaNumber - * in any case, we dispatch to it as soon as we spot one on either side. - */ - public static boolean equals2(Object x, Object y) { - if (x instanceof java.lang.Number) - return equalsNumObject((java.lang.Number)x, y); - if (x instanceof java.lang.Character) - return equalsCharObject((java.lang.Character)x, y); - if (x == null) - return y == null; - - return x.equals(y); - } - - public static boolean equalsNumObject(java.lang.Number xn, Object y) { - if (y instanceof java.lang.Number) - return equalsNumNum(xn, (java.lang.Number)y); - if (y instanceof java.lang.Character) - return equalsNumChar(xn, (java.lang.Character)y); - if (xn == null) - return y == null; - - return xn.equals(y); - } - - public static boolean equalsNumNum(java.lang.Number xn, java.lang.Number yn) { - int xcode = typeCode(xn); - int ycode = typeCode(yn); - switch (ycode > xcode ? ycode : xcode) { - case INT: - return xn.intValue() == yn.intValue(); - case LONG: - return xn.longValue() == yn.longValue(); - case FLOAT: - return xn.floatValue() == yn.floatValue(); - case DOUBLE: - return xn.doubleValue() == yn.doubleValue(); - default: - if ((yn instanceof ScalaNumber) && !(xn instanceof ScalaNumber)) - return yn.equals(xn); - } - if (xn == null) - return yn == null; - - return xn.equals(yn); - } - - public static boolean equalsCharObject(java.lang.Character xc, Object y) { - if (y instanceof java.lang.Character) - return xc.charValue() == ((java.lang.Character)y).charValue(); - if (y instanceof java.lang.Number) - return equalsNumChar((java.lang.Number)y, xc); - if (xc == null) - return y == null; - - return xc.equals(y); - } - - public static boolean equalsNumChar(java.lang.Number xn, java.lang.Character yc) { - if (yc == null) - return xn == null; - - char ch = yc.charValue(); - switch (typeCode(xn)) { - case INT: - return xn.intValue() == ch; - case LONG: - return xn.longValue() == ch; - case FLOAT: - return xn.floatValue() == ch; - case DOUBLE: - return xn.doubleValue() == ch; - default: - return xn.equals(yc); - } - } - - private static int unboxCharOrInt(Object arg1, int code) { - if (code == CHAR) - return ((java.lang.Character) arg1).charValue(); - else - return ((java.lang.Number) arg1).intValue(); - } - private static long unboxCharOrLong(Object arg1, int code) { - if (code == CHAR) - return ((java.lang.Character) arg1).charValue(); - else - return ((java.lang.Number) arg1).longValue(); - } - private static float unboxCharOrFloat(Object arg1, int code) { - if (code == CHAR) - return ((java.lang.Character) arg1).charValue(); - else - return ((java.lang.Number) arg1).floatValue(); - } - private static double unboxCharOrDouble(Object arg1, int code) { - if (code == CHAR) - return ((java.lang.Character) arg1).charValue(); - else - return ((java.lang.Number) arg1).doubleValue(); - } - -/* OPERATORS ... OPERATORS ... OPERATORS ... OPERATORS ... OPERATORS ... OPERATORS ... OPERATORS ... OPERATORS */ - - /** arg1 + arg2 */ - public static Object add(Object arg1, Object arg2) throws NoSuchMethodException { - int code1 = typeCode(arg1); - int code2 = typeCode(arg2); - int maxcode = (code1 < code2) ? code2 : code1; - if (maxcode <= INT) { - return boxToInteger(unboxCharOrInt(arg1, code1) + unboxCharOrInt(arg2, code2)); - } - if (maxcode <= LONG) { - return boxToLong(unboxCharOrLong(arg1, code1) + unboxCharOrLong(arg2, code2)); - } - if (maxcode <= FLOAT) { - return boxToFloat(unboxCharOrFloat(arg1, code1) + unboxCharOrFloat(arg2, code2)); - } - if (maxcode <= DOUBLE) { - return boxToDouble(unboxCharOrDouble(arg1, code1) + unboxCharOrDouble(arg2, code2)); - } - throw new NoSuchMethodException(); - } - - /** arg1 - arg2 */ - public static Object subtract(Object arg1, Object arg2) throws NoSuchMethodException { - int code1 = typeCode(arg1); - int code2 = typeCode(arg2); - int maxcode = (code1 < code2) ? code2 : code1; - if (maxcode <= INT) { - return boxToInteger(unboxCharOrInt(arg1, code1) - unboxCharOrInt(arg2, code2)); - } - if (maxcode <= LONG) { - return boxToLong(unboxCharOrLong(arg1, code1) - unboxCharOrLong(arg2, code2)); - } - if (maxcode <= FLOAT) { - return boxToFloat(unboxCharOrFloat(arg1, code1) - unboxCharOrFloat(arg2, code2)); - } - if (maxcode <= DOUBLE) { - return boxToDouble(unboxCharOrDouble(arg1, code1) - unboxCharOrDouble(arg2, code2)); - } - throw new NoSuchMethodException(); - } - - /** arg1 * arg2 */ - public static Object multiply(Object arg1, Object arg2) throws NoSuchMethodException { - int code1 = typeCode(arg1); - int code2 = typeCode(arg2); - int maxcode = (code1 < code2) ? code2 : code1; - if (maxcode <= INT) { - return boxToInteger(unboxCharOrInt(arg1, code1) * unboxCharOrInt(arg2, code2)); - } - if (maxcode <= LONG) { - return boxToLong(unboxCharOrLong(arg1, code1) * unboxCharOrLong(arg2, code2)); - } - if (maxcode <= FLOAT) { - return boxToFloat(unboxCharOrFloat(arg1, code1) * unboxCharOrFloat(arg2, code2)); - } - if (maxcode <= DOUBLE) { - return boxToDouble(unboxCharOrDouble(arg1, code1) * unboxCharOrDouble(arg2, code2)); - } - throw new NoSuchMethodException(); - } - - /** arg1 / arg2 */ - public static Object divide(Object arg1, Object arg2) throws NoSuchMethodException { - int code1 = typeCode(arg1); - int code2 = typeCode(arg2); - int maxcode = (code1 < code2) ? code2 : code1; - - if (maxcode <= INT) - return boxToInteger(unboxCharOrInt(arg1, code1) / unboxCharOrInt(arg2, code2)); - if (maxcode <= LONG) - return boxToLong(unboxCharOrLong(arg1, code1) / unboxCharOrLong(arg2, code2)); - if (maxcode <= FLOAT) - return boxToFloat(unboxCharOrFloat(arg1, code1) / unboxCharOrFloat(arg2, code2)); - if (maxcode <= DOUBLE) - return boxToDouble(unboxCharOrDouble(arg1, code1) / unboxCharOrDouble(arg2, code2)); - - throw new NoSuchMethodException(); - } - - /** arg1 % arg2 */ - public static Object takeModulo(Object arg1, Object arg2) throws NoSuchMethodException { - int code1 = typeCode(arg1); - int code2 = typeCode(arg2); - int maxcode = (code1 < code2) ? code2 : code1; - - if (maxcode <= INT) - return boxToInteger(unboxCharOrInt(arg1, code1) % unboxCharOrInt(arg2, code2)); - if (maxcode <= LONG) - return boxToLong(unboxCharOrLong(arg1, code1) % unboxCharOrLong(arg2, code2)); - if (maxcode <= FLOAT) - return boxToFloat(unboxCharOrFloat(arg1, code1) % unboxCharOrFloat(arg2, code2)); - if (maxcode <= DOUBLE) - return boxToDouble(unboxCharOrDouble(arg1, code1) % unboxCharOrDouble(arg2, code2)); - - throw new NoSuchMethodException(); - } - - /** arg1 >> arg2 */ - public static Object shiftSignedRight(Object arg1, Object arg2) throws NoSuchMethodException { - int code1 = typeCode(arg1); - int code2 = typeCode(arg2); - if (code1 <= INT) { - int val1 = unboxCharOrInt(arg1, code1); - if (code2 <= INT) { - int val2 = unboxCharOrInt(arg2, code2); - return boxToInteger(val1 >> val2); - } - if (code2 <= LONG) { - long val2 = unboxCharOrLong(arg2, code2); - return boxToInteger(val1 >> val2); - } - } - if (code1 <= LONG) { - long val1 = unboxCharOrLong(arg1, code1); - if (code2 <= INT) { - int val2 = unboxCharOrInt(arg2, code2); - return boxToLong(val1 >> val2); - } - if (code2 <= LONG) { - long val2 = unboxCharOrLong(arg2, code2); - return boxToLong(val1 >> val2); - } - } - throw new NoSuchMethodException(); - } - - /** arg1 << arg2 */ - public static Object shiftSignedLeft(Object arg1, Object arg2) throws NoSuchMethodException { - int code1 = typeCode(arg1); - int code2 = typeCode(arg2); - if (code1 <= INT) { - int val1 = unboxCharOrInt(arg1, code1); - if (code2 <= INT) { - int val2 = unboxCharOrInt(arg2, code2); - return boxToInteger(val1 << val2); - } - if (code2 <= LONG) { - long val2 = unboxCharOrLong(arg2, code2); - return boxToInteger(val1 << val2); - } - } - if (code1 <= LONG) { - long val1 = unboxCharOrLong(arg1, code1); - if (code2 <= INT) { - int val2 = unboxCharOrInt(arg2, code2); - return boxToLong(val1 << val2); - } - if (code2 <= LONG) { - long val2 = unboxCharOrLong(arg2, code2); - return boxToLong(val1 << val2); - } - } - throw new NoSuchMethodException(); - } - - /** arg1 >>> arg2 */ - public static Object shiftLogicalRight(Object arg1, Object arg2) throws NoSuchMethodException { - int code1 = typeCode(arg1); - int code2 = typeCode(arg2); - if (code1 <= INT) { - int val1 = unboxCharOrInt(arg1, code1); - if (code2 <= INT) { - int val2 = unboxCharOrInt(arg2, code2); - return boxToInteger(val1 >>> val2); - } - if (code2 <= LONG) { - long val2 = unboxCharOrLong(arg2, code2); - return boxToInteger(val1 >>> val2); - } - } - if (code1 <= LONG) { - long val1 = unboxCharOrLong(arg1, code1); - if (code2 <= INT) { - int val2 = unboxCharOrInt(arg2, code2); - return boxToLong(val1 >>> val2); - } - if (code2 <= LONG) { - long val2 = unboxCharOrLong(arg2, code2); - return boxToLong(val1 >>> val2); - } - } - throw new NoSuchMethodException(); - } - - /** -arg */ - public static Object negate(Object arg) throws NoSuchMethodException { - int code = typeCode(arg); - if (code <= INT) { - int val = unboxCharOrInt(arg, code); - return boxToInteger(-val); - } - if (code <= LONG) { - long val = unboxCharOrLong(arg, code); - return boxToLong(-val); - } - if (code <= FLOAT) { - float val = unboxCharOrFloat(arg, code); - return boxToFloat(-val); - } - if (code <= DOUBLE) { - double val = unboxCharOrDouble(arg, code); - return boxToDouble(-val); - } - throw new NoSuchMethodException(); - } - - /** +arg */ - public static Object positive(Object arg) throws NoSuchMethodException { - int code = typeCode(arg); - if (code <= INT) { - return boxToInteger(+unboxCharOrInt(arg, code)); - } - if (code <= LONG) { - return boxToLong(+unboxCharOrLong(arg, code)); - } - if (code <= FLOAT) { - return boxToFloat(+unboxCharOrFloat(arg, code)); - } - if (code <= DOUBLE) { - return boxToDouble(+unboxCharOrDouble(arg, code)); - } - throw new NoSuchMethodException(); - } - - /** arg1 & arg2 */ - public static Object takeAnd(Object arg1, Object arg2) throws NoSuchMethodException { - if ((arg1 instanceof Boolean) || (arg2 instanceof Boolean)) { - if ((arg1 instanceof Boolean) && (arg2 instanceof Boolean)) - return boxToBoolean(((java.lang.Boolean) arg1).booleanValue() & ((java.lang.Boolean) arg2).booleanValue()); - else - throw new NoSuchMethodException(); - } - int code1 = typeCode(arg1); - int code2 = typeCode(arg2); - int maxcode = (code1 < code2) ? code2 : code1; - - if (maxcode <= INT) - return boxToInteger(unboxCharOrInt(arg1, code1) & unboxCharOrInt(arg2, code2)); - if (maxcode <= LONG) - return boxToLong(unboxCharOrLong(arg1, code1) & unboxCharOrLong(arg2, code2)); - - throw new NoSuchMethodException(); - } - - /** arg1 | arg2 */ - public static Object takeOr(Object arg1, Object arg2) throws NoSuchMethodException { - if ((arg1 instanceof Boolean) || (arg2 instanceof Boolean)) { - if ((arg1 instanceof Boolean) && (arg2 instanceof Boolean)) - return boxToBoolean(((java.lang.Boolean) arg1).booleanValue() | ((java.lang.Boolean) arg2).booleanValue()); - else - throw new NoSuchMethodException(); - } - int code1 = typeCode(arg1); - int code2 = typeCode(arg2); - int maxcode = (code1 < code2) ? code2 : code1; - - if (maxcode <= INT) - return boxToInteger(unboxCharOrInt(arg1, code1) | unboxCharOrInt(arg2, code2)); - if (maxcode <= LONG) - return boxToLong(unboxCharOrLong(arg1, code1) | unboxCharOrLong(arg2, code2)); - - throw new NoSuchMethodException(); - } - - /** arg1 ^ arg2 */ - public static Object takeXor(Object arg1, Object arg2) throws NoSuchMethodException { - if ((arg1 instanceof Boolean) || (arg2 instanceof Boolean)) { - if ((arg1 instanceof Boolean) && (arg2 instanceof Boolean)) - return boxToBoolean(((java.lang.Boolean) arg1).booleanValue() ^ ((java.lang.Boolean) arg2).booleanValue()); - else - throw new NoSuchMethodException(); - } - int code1 = typeCode(arg1); - int code2 = typeCode(arg2); - int maxcode = (code1 < code2) ? code2 : code1; - - if (maxcode <= INT) - return boxToInteger(unboxCharOrInt(arg1, code1) ^ unboxCharOrInt(arg2, code2)); - if (maxcode <= LONG) - return boxToLong(unboxCharOrLong(arg1, code1) ^ unboxCharOrLong(arg2, code2)); - - throw new NoSuchMethodException(); - } - - /** arg1 && arg2 */ - public static Object takeConditionalAnd(Object arg1, Object arg2) throws NoSuchMethodException { - if ((arg1 instanceof Boolean) && (arg2 instanceof Boolean)) { - return boxToBoolean(((java.lang.Boolean) arg1).booleanValue() && ((java.lang.Boolean) arg2).booleanValue()); - } - throw new NoSuchMethodException(); - } - - /** arg1 || arg2 */ - public static Object takeConditionalOr(Object arg1, Object arg2) throws NoSuchMethodException { - if ((arg1 instanceof Boolean) && (arg2 instanceof Boolean)) { - return boxToBoolean(((java.lang.Boolean) arg1).booleanValue() || ((java.lang.Boolean) arg2).booleanValue()); - } - throw new NoSuchMethodException(); - } - - /** ~arg */ - public static Object complement(Object arg) throws NoSuchMethodException { - int code = typeCode(arg); - if (code <= INT) { - return boxToInteger(~unboxCharOrInt(arg, code)); - } - if (code <= LONG) { - return boxToLong(~unboxCharOrLong(arg, code)); - } - throw new NoSuchMethodException(); - } - - /** !arg */ - public static Object takeNot(Object arg) throws NoSuchMethodException { - if (arg instanceof Boolean) { - return boxToBoolean(!((java.lang.Boolean) arg).booleanValue()); - } - throw new NoSuchMethodException(); - } - - public static Object testEqual(Object arg1, Object arg2) throws NoSuchMethodException { - return boxToBoolean(arg1 == arg2); - } - - public static Object testNotEqual(Object arg1, Object arg2) throws NoSuchMethodException { - return boxToBoolean(arg1 != arg2); - } - - public static Object testLessThan(Object arg1, Object arg2) throws NoSuchMethodException { - int code1 = typeCode(arg1); - int code2 = typeCode(arg2); - int maxcode = (code1 < code2) ? code2 : code1; - if (maxcode <= INT) { - int val1 = unboxCharOrInt(arg1, code1); - int val2 = unboxCharOrInt(arg2, code2); - return boxToBoolean(val1 < val2); - } - if (maxcode <= LONG) { - long val1 = unboxCharOrLong(arg1, code1); - long val2 = unboxCharOrLong(arg2, code2); - return boxToBoolean(val1 < val2); - } - if (maxcode <= FLOAT) { - float val1 = unboxCharOrFloat(arg1, code1); - float val2 = unboxCharOrFloat(arg2, code2); - return boxToBoolean(val1 < val2); - } - if (maxcode <= DOUBLE) { - double val1 = unboxCharOrDouble(arg1, code1); - double val2 = unboxCharOrDouble(arg2, code2); - return boxToBoolean(val1 < val2); - } - throw new NoSuchMethodException(); - } - - public static Object testLessOrEqualThan(Object arg1, Object arg2) throws NoSuchMethodException { - int code1 = typeCode(arg1); - int code2 = typeCode(arg2); - int maxcode = (code1 < code2) ? code2 : code1; - if (maxcode <= INT) { - int val1 = unboxCharOrInt(arg1, code1); - int val2 = unboxCharOrInt(arg2, code2); - return boxToBoolean(val1 <= val2); - } - if (maxcode <= LONG) { - long val1 = unboxCharOrLong(arg1, code1); - long val2 = unboxCharOrLong(arg2, code2); - return boxToBoolean(val1 <= val2); - } - if (maxcode <= FLOAT) { - float val1 = unboxCharOrFloat(arg1, code1); - float val2 = unboxCharOrFloat(arg2, code2); - return boxToBoolean(val1 <= val2); - } - if (maxcode <= DOUBLE) { - double val1 = unboxCharOrDouble(arg1, code1); - double val2 = unboxCharOrDouble(arg2, code2); - return boxToBoolean(val1 <= val2); - } - throw new NoSuchMethodException(); - } - - public static Object testGreaterOrEqualThan(Object arg1, Object arg2) throws NoSuchMethodException { - int code1 = typeCode(arg1); - int code2 = typeCode(arg2); - int maxcode = (code1 < code2) ? code2 : code1; - if (maxcode <= INT) { - int val1 = unboxCharOrInt(arg1, code1); - int val2 = unboxCharOrInt(arg2, code2); - return boxToBoolean(val1 >= val2); - } - if (maxcode <= LONG) { - long val1 = unboxCharOrLong(arg1, code1); - long val2 = unboxCharOrLong(arg2, code2); - return boxToBoolean(val1 >= val2); - } - if (maxcode <= FLOAT) { - float val1 = unboxCharOrFloat(arg1, code1); - float val2 = unboxCharOrFloat(arg2, code2); - return boxToBoolean(val1 >= val2); - } - if (maxcode <= DOUBLE) { - double val1 = unboxCharOrDouble(arg1, code1); - double val2 = unboxCharOrDouble(arg2, code2); - return boxToBoolean(val1 >= val2); - } - throw new NoSuchMethodException(); - } - - public static Object testGreaterThan(Object arg1, Object arg2) throws NoSuchMethodException { - int code1 = typeCode(arg1); - int code2 = typeCode(arg2); - int maxcode = (code1 < code2) ? code2 : code1; - if (maxcode <= INT) { - int val1 = unboxCharOrInt(arg1, code1); - int val2 = unboxCharOrInt(arg2, code2); - return boxToBoolean(val1 > val2); - } - if (maxcode <= LONG) { - long val1 = unboxCharOrLong(arg1, code1); - long val2 = unboxCharOrLong(arg2, code2); - return boxToBoolean(val1 > val2); - } - if (maxcode <= FLOAT) { - float val1 = unboxCharOrFloat(arg1, code1); - float val2 = unboxCharOrFloat(arg2, code2); - return boxToBoolean(val1 > val2); - } - if (maxcode <= DOUBLE) { - double val1 = unboxCharOrDouble(arg1, code1); - double val2 = unboxCharOrDouble(arg2, code2); - return boxToBoolean(val1 > val2); - } - throw new NoSuchMethodException(); - } - - public static boolean isBoxedNumberOrBoolean(Object arg) { - return (arg instanceof java.lang.Boolean) || isBoxedNumber(arg); - } - public static boolean isBoxedNumber(Object arg) { - return ( - (arg instanceof java.lang.Integer) - || (arg instanceof java.lang.Long) - || (arg instanceof java.lang.Double) - || (arg instanceof java.lang.Float) - || (arg instanceof java.lang.Short) - || (arg instanceof java.lang.Character) - || (arg instanceof java.lang.Byte) - ); - } - - /** arg.toChar */ - public static java.lang.Character toCharacter(Object arg) throws NoSuchMethodException { - if (arg instanceof java.lang.Integer) return boxToCharacter((char)unboxToInt(arg)); - if (arg instanceof java.lang.Short) return boxToCharacter((char)unboxToShort(arg)); - if (arg instanceof java.lang.Character) return (java.lang.Character)arg; - if (arg instanceof java.lang.Long) return boxToCharacter((char)unboxToLong(arg)); - if (arg instanceof java.lang.Byte) return boxToCharacter((char)unboxToByte(arg)); - if (arg instanceof java.lang.Float) return boxToCharacter((char)unboxToFloat(arg)); - if (arg instanceof java.lang.Double) return boxToCharacter((char)unboxToDouble(arg)); - throw new NoSuchMethodException(); - } - - /** arg.toByte */ - public static java.lang.Byte toByte(Object arg) throws NoSuchMethodException { - if (arg instanceof java.lang.Integer) return boxToByte((byte)unboxToInt(arg)); - if (arg instanceof java.lang.Character) return boxToByte((byte)unboxToChar(arg)); - if (arg instanceof java.lang.Byte) return (java.lang.Byte)arg; - if (arg instanceof java.lang.Long) return boxToByte((byte)unboxToLong(arg)); - if (arg instanceof java.lang.Short) return boxToByte((byte)unboxToShort(arg)); - if (arg instanceof java.lang.Float) return boxToByte((byte)unboxToFloat(arg)); - if (arg instanceof java.lang.Double) return boxToByte((byte)unboxToDouble(arg)); - throw new NoSuchMethodException(); - } - - /** arg.toShort */ - public static java.lang.Short toShort(Object arg) throws NoSuchMethodException { - if (arg instanceof java.lang.Integer) return boxToShort((short)unboxToInt(arg)); - if (arg instanceof java.lang.Long) return boxToShort((short)unboxToLong(arg)); - if (arg instanceof java.lang.Character) return boxToShort((short)unboxToChar(arg)); - if (arg instanceof java.lang.Byte) return boxToShort((short)unboxToByte(arg)); - if (arg instanceof java.lang.Short) return (java.lang.Short)arg; - if (arg instanceof java.lang.Float) return boxToShort((short)unboxToFloat(arg)); - if (arg instanceof java.lang.Double) return boxToShort((short)unboxToDouble(arg)); - throw new NoSuchMethodException(); - } - - /** arg.toInt */ - public static java.lang.Integer toInteger(Object arg) throws NoSuchMethodException { - if (arg instanceof java.lang.Integer) return (java.lang.Integer)arg; - if (arg instanceof java.lang.Long) return boxToInteger((int)unboxToLong(arg)); - if (arg instanceof java.lang.Double) return boxToInteger((int)unboxToDouble(arg)); - if (arg instanceof java.lang.Float) return boxToInteger((int)unboxToFloat(arg)); - if (arg instanceof java.lang.Character) return boxToInteger((int)unboxToChar(arg)); - if (arg instanceof java.lang.Byte) return boxToInteger((int)unboxToByte(arg)); - if (arg instanceof java.lang.Short) return boxToInteger((int)unboxToShort(arg)); - throw new NoSuchMethodException(); - } - - /** arg.toLong */ - public static java.lang.Long toLong(Object arg) throws NoSuchMethodException { - if (arg instanceof java.lang.Integer) return boxToLong((long)unboxToInt(arg)); - if (arg instanceof java.lang.Double) return boxToLong((long)unboxToDouble(arg)); - if (arg instanceof java.lang.Float) return boxToLong((long)unboxToFloat(arg)); - if (arg instanceof java.lang.Long) return (java.lang.Long)arg; - if (arg instanceof java.lang.Character) return boxToLong((long)unboxToChar(arg)); - if (arg instanceof java.lang.Byte) return boxToLong((long)unboxToByte(arg)); - if (arg instanceof java.lang.Short) return boxToLong((long)unboxToShort(arg)); - throw new NoSuchMethodException(); - } - - /** arg.toFloat */ - public static java.lang.Float toFloat(Object arg) throws NoSuchMethodException { - if (arg instanceof java.lang.Integer) return boxToFloat((float)unboxToInt(arg)); - if (arg instanceof java.lang.Long) return boxToFloat((float)unboxToLong(arg)); - if (arg instanceof java.lang.Float) return (java.lang.Float)arg; - if (arg instanceof java.lang.Double) return boxToFloat((float)unboxToDouble(arg)); - if (arg instanceof java.lang.Character) return boxToFloat((float)unboxToChar(arg)); - if (arg instanceof java.lang.Byte) return boxToFloat((float)unboxToByte(arg)); - if (arg instanceof java.lang.Short) return boxToFloat((float)unboxToShort(arg)); - throw new NoSuchMethodException(); - } - - /** arg.toDouble */ - public static java.lang.Double toDouble(Object arg) throws NoSuchMethodException { - if (arg instanceof java.lang.Integer) return boxToDouble((double)unboxToInt(arg)); - if (arg instanceof java.lang.Float) return boxToDouble((double)unboxToFloat(arg)); - if (arg instanceof java.lang.Double) return (java.lang.Double)arg; - if (arg instanceof java.lang.Long) return boxToDouble((double)unboxToLong(arg)); - if (arg instanceof java.lang.Character) return boxToDouble((double)unboxToChar(arg)); - if (arg instanceof java.lang.Byte) return boxToDouble((double)unboxToByte(arg)); - if (arg instanceof java.lang.Short) return boxToDouble((double)unboxToShort(arg)); - throw new NoSuchMethodException(); - } - -} diff --git a/test/instrumented/library/scala/runtime/ScalaRunTime.scala b/test/instrumented/library/scala/runtime/ScalaRunTime.scala deleted file mode 100644 index 55baa0c135b1..000000000000 --- a/test/instrumented/library/scala/runtime/ScalaRunTime.scala +++ /dev/null @@ -1,290 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2002-2013, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -/* INSTRUMENTED VERSION */ - -package scala -package runtime - -import scala.collection.{ AbstractIterator, AnyConstr, SortedOps, StrictOptimizedIterableOps, StringOps, StringView, View } -import scala.collection.generic.IsIterableLike -import scala.collection.immutable.{ NumericRange, ArraySeq } -import scala.collection.mutable.StringBuilder -import scala.reflect.{ ClassTag, classTag } -import java.lang.{ Class => jClass } - -import java.lang.reflect.{ Method => JMethod } - -/** The object ScalaRunTime provides support methods required by - * the scala runtime. All these methods should be considered - * outside the API and subject to change or removal without notice. - */ -object ScalaRunTime { - def isArray(x: Any, atLevel: Int = 1): Boolean = - x != null && isArrayClass(x.getClass, atLevel) - - private def isArrayClass(clazz: jClass[_], atLevel: Int): Boolean = - clazz.isArray && (atLevel == 1 || isArrayClass(clazz.getComponentType, atLevel - 1)) - - // A helper method to make my life in the pattern matcher a lot easier. - def drop[Repr](coll: Repr, num: Int)(implicit iterable: IsIterableLike[Repr]): Repr = - iterable conversion coll drop num - - /** Return the class object representing an array with element class `clazz`. - */ - def arrayClass(clazz: jClass[_]): jClass[_] = { - // newInstance throws an exception if the erasure is Void.TYPE. see scala/bug#5680 - if (clazz == java.lang.Void.TYPE) classOf[Array[Unit]] - else java.lang.reflect.Array.newInstance(clazz, 0).getClass - } - - /** Return the class object representing an unboxed value type, - * e.g., classOf[int], not classOf[java.lang.Integer]. The compiler - * rewrites expressions like 5.getClass to come here. - */ - def anyValClass[T <: AnyVal : ClassTag](value: T): jClass[T] = - classTag[T].runtimeClass.asInstanceOf[jClass[T]] - - var arrayApplyCount = 0 - - /** Retrieve generic array element */ - def array_apply(xs: AnyRef, idx: Int): Any = { - arrayApplyCount += 1 - xs match { - case x: Array[AnyRef] => x(idx).asInstanceOf[Any] - case x: Array[Int] => x(idx).asInstanceOf[Any] - case x: Array[Double] => x(idx).asInstanceOf[Any] - case x: Array[Long] => x(idx).asInstanceOf[Any] - case x: Array[Float] => x(idx).asInstanceOf[Any] - case x: Array[Char] => x(idx).asInstanceOf[Any] - case x: Array[Byte] => x(idx).asInstanceOf[Any] - case x: Array[Short] => x(idx).asInstanceOf[Any] - case x: Array[Boolean] => x(idx).asInstanceOf[Any] - case x: Array[Unit] => x(idx).asInstanceOf[Any] - case null => throw new NullPointerException - } - } - - var arrayUpdateCount = 0 - - /** update generic array element */ - def array_update(xs: AnyRef, idx: Int, value: Any): Unit = { - arrayUpdateCount += 1 - xs match { - case x: Array[AnyRef] => x(idx) = value.asInstanceOf[AnyRef] - case x: Array[Int] => x(idx) = value.asInstanceOf[Int] - case x: Array[Double] => x(idx) = value.asInstanceOf[Double] - case x: Array[Long] => x(idx) = value.asInstanceOf[Long] - case x: Array[Float] => x(idx) = value.asInstanceOf[Float] - case x: Array[Char] => x(idx) = value.asInstanceOf[Char] - case x: Array[Byte] => x(idx) = value.asInstanceOf[Byte] - case x: Array[Short] => x(idx) = value.asInstanceOf[Short] - case x: Array[Boolean] => x(idx) = value.asInstanceOf[Boolean] - case x: Array[Unit] => x(idx) = value.asInstanceOf[Unit] - case null => throw new NullPointerException - } - } - - /** Get generic array length */ - def array_length(xs: AnyRef): Int = xs match { - case x: Array[AnyRef] => x.length - case x: Array[Int] => x.length - case x: Array[Double] => x.length - case x: Array[Long] => x.length - case x: Array[Float] => x.length - case x: Array[Char] => x.length - case x: Array[Byte] => x.length - case x: Array[Short] => x.length - case x: Array[Boolean] => x.length - case x: Array[Unit] => x.length - case null => throw new NullPointerException - } - - def array_clone(xs: AnyRef): AnyRef = xs match { - case x: Array[AnyRef] => x.clone() - case x: Array[Int] => x.clone() - case x: Array[Double] => x.clone() - case x: Array[Long] => x.clone() - case x: Array[Float] => x.clone() - case x: Array[Char] => x.clone() - case x: Array[Byte] => x.clone() - case x: Array[Short] => x.clone() - case x: Array[Boolean] => x.clone() - case x: Array[Unit] => x - case null => throw new NullPointerException - } - - /** Convert an array to an object array. - * Needed to deal with vararg arguments of primitive types that are passed - * to a generic Java vararg parameter T ... - */ - def toObjectArray(src: AnyRef): Array[Object] = src match { - case x: Array[AnyRef] => x - case _ => - val length = array_length(src) - val dest = new Array[Object](length) - for (i <- 0 until length) - array_update(dest, i, array_apply(src, i)) - dest - } - - def toArray[T](xs: scala.collection.Seq[T]) = { - val arr = new Array[AnyRef](xs.length) - var i = 0 - for (x <- xs) { - arr(i) = x.asInstanceOf[AnyRef] - i += 1 - } - arr - } - - // Java bug: https://bugs.java.com/view_bug.do?bug_id=4071957 - // More background at ticket #2318. - def ensureAccessible(m: JMethod): JMethod = scala.reflect.ensureAccessible(m) - - def _toString(x: Product): String = - x.productIterator.mkString(x.productPrefix + "(", ",", ")") - - def _hashCode(x: Product): Int = scala.util.hashing.MurmurHash3.productHash(x) - - /** A helper for case classes. */ - def typedProductIterator[T](x: Product): Iterator[T] = { - new AbstractIterator[T] { - private var c: Int = 0 - private val cmax = x.productArity - def hasNext = c < cmax - def next() = { - val result = x.productElement(c) - c += 1 - result.asInstanceOf[T] - } - } - } - - /** Given any Scala value, convert it to a String. - * - * The primary motivation for this method is to provide a means for - * correctly obtaining a String representation of a value, while - * avoiding the pitfalls of naively calling toString on said value. - * In particular, it addresses the fact that (a) toString cannot be - * called on null and (b) depending on the apparent type of an - * array, toString may or may not print it in a human-readable form. - * - * @param arg the value to stringify - * @return a string representation of arg. - */ - def stringOf(arg: Any): String = stringOf(arg, scala.Int.MaxValue) - def stringOf(arg: Any, maxElements: Int): String = { - def packageOf(x: AnyRef) = x.getClass.getPackage match { - case null => "" - case p => p.getName - } - def isScalaClass(x: AnyRef) = packageOf(x) startsWith "scala." - def isScalaCompilerClass(x: AnyRef) = packageOf(x) startsWith "scala.tools.nsc." - - // includes specialized subclasses and future proofed against hypothetical TupleN (for N > 22) - def isTuple(x: Any) = x != null && x.getClass.getName.startsWith("scala.Tuple") - - // We use reflection because the scala.xml package might not be available - def isSubClassOf(potentialSubClass: Class[_], ofClass: String) = - try { - val classLoader = potentialSubClass.getClassLoader - val clazz = Class.forName(ofClass, /*initialize =*/ false, classLoader) - clazz.isAssignableFrom(potentialSubClass) - } catch { - case cnfe: ClassNotFoundException => false - } - def isXmlNode(potentialSubClass: Class[_]) = isSubClassOf(potentialSubClass, "scala.xml.Node") - def isXmlMetaData(potentialSubClass: Class[_]) = isSubClassOf(potentialSubClass, "scala.xml.MetaData") - - // When doing our own iteration is dangerous - def useOwnToString(x: Any) = x match { - // Range/NumericRange have a custom toString to avoid walking a gazillion elements - case _: Range | _: NumericRange[_] => true - // Sorted collections to the wrong thing (for us) on iteration - ticket #3493 - case _: SortedOps[_, _] => true - // StringBuilder(a, b, c) and similar not so attractive - case _: StringView | _: StringOps | _: StringBuilder => true - // Don't want to evaluate any elements in a view - case _: View[_] => true - // Node extends NodeSeq extends Seq[Node] and MetaData extends Iterable[MetaData] - // -> catch those by isXmlNode and isXmlMetaData. - // Don't want to a) traverse infinity or b) be overly helpful with peoples' custom - // collections which may have useful toString methods - ticket #3710 - // or c) print AbstractFiles which are somehow also Iterable[AbstractFile]s. - case x: Iterable[_] => (!x.isInstanceOf[StrictOptimizedIterableOps[_, AnyConstr, _]]) || !isScalaClass(x) || isScalaCompilerClass(x) || isXmlNode(x.getClass) || isXmlMetaData(x.getClass) - // Otherwise, nothing could possibly go wrong - case _ => false - } - - // A variation on inner for maps so they print -> instead of bare tuples - def mapInner(arg: Any): String = arg match { - case (k, v) => inner(k) + " -> " + inner(v) - case _ => inner(arg) - } - - // Special casing Unit arrays, the value class which uses a reference array type. - def arrayToString(x: AnyRef) = { - if (x.getClass.getComponentType == classOf[BoxedUnit]) - 0 until (array_length(x) min maxElements) map (_ => "()") mkString ("Array(", ", ", ")") - else - x.asInstanceOf[Array[_]].iterator.take(maxElements).map(inner).mkString("Array(", ", ", ")") - } - - // The recursively applied attempt to prettify Array printing. - // Note that iterator is used if possible and foreach is used as a - // last resort, because the parallel collections "foreach" in a - // random order even on sequences. - def inner(arg: Any): String = arg match { - case null => "null" - case "" => "\"\"" - case x: String => if (x.head.isWhitespace || x.last.isWhitespace) "\"" + x + "\"" else x - case x if useOwnToString(x) => x.toString - case x: AnyRef if isArray(x) => arrayToString(x) - case x: scala.collection.Map[_, _] => x.iterator take maxElements map mapInner mkString (x.className + "(", ", ", ")") - case x: Iterable[_] => x.iterator take maxElements map inner mkString (x.className + "(", ", ", ")") - case x: Product1[_] if isTuple(x) => "(" + inner(x._1) + ",)" // that special trailing comma - case x: Product if isTuple(x) => x.productIterator map inner mkString ("(", ",", ")") - case x => x.toString - } - - // The try/catch is defense against iterables which aren't actually designed - // to be iterated, such as some scala.tools.nsc.io.AbstractFile derived classes. - try inner(arg) - catch { - case _: UnsupportedOperationException | _: AssertionError => "" + arg - } - } - - /** stringOf formatted for use in a repl result. */ - def replStringOf(arg: Any, maxElements: Int): String = { - val s = stringOf(arg, maxElements) - val nl = if (s contains "\n") "\n" else "" - - nl + s + "\n" - } - - // Convert arrays to ArraySeq for use with Java varargs: - def genericWrapArray[T](xs: Array[T]): ArraySeq[T] = - if (xs eq null) null - else ArraySeq.unsafeWrapArray(xs) - def wrapRefArray[T <: AnyRef](xs: Array[T]): ArraySeq[T] = { - if (xs eq null) null - else if (xs.length == 0) ArraySeq.empty[AnyRef].asInstanceOf[ArraySeq[T]] - else new ArraySeq.ofRef[T](xs) - } - def wrapIntArray(xs: Array[Int]): ArraySeq[Int] = if (xs ne null) new ArraySeq.ofInt(xs) else null - def wrapDoubleArray(xs: Array[Double]): ArraySeq[Double] = if (xs ne null) new ArraySeq.ofDouble(xs) else null - def wrapLongArray(xs: Array[Long]): ArraySeq[Long] = if (xs ne null) new ArraySeq.ofLong(xs) else null - def wrapFloatArray(xs: Array[Float]): ArraySeq[Float] = if (xs ne null) new ArraySeq.ofFloat(xs) else null - def wrapCharArray(xs: Array[Char]): ArraySeq[Char] = if (xs ne null) new ArraySeq.ofChar(xs) else null - def wrapByteArray(xs: Array[Byte]): ArraySeq[Byte] = if (xs ne null) new ArraySeq.ofByte(xs) else null - def wrapShortArray(xs: Array[Short]): ArraySeq[Short] = if (xs ne null) new ArraySeq.ofShort(xs) else null - def wrapBooleanArray(xs: Array[Boolean]): ArraySeq[Boolean] = if (xs ne null) new ArraySeq.ofBoolean(xs) else null - def wrapUnitArray(xs: Array[Unit]): ArraySeq[Unit] = if (xs ne null) new ArraySeq.ofUnit(xs) else null -} diff --git a/test/instrumented/mkinstrumented.sh b/test/instrumented/mkinstrumented.sh deleted file mode 100755 index 73161670fdf3..000000000000 --- a/test/instrumented/mkinstrumented.sh +++ /dev/null @@ -1,50 +0,0 @@ -#!/bin/bash - -# Used to compile a jar with instrumented versions of certain classes. - -set -e - -run () { - echo "% $@" - "$@" -} - -if [ $# -ne 1 ] -then - echo "Must provide build dir ('target' or 'build')." - exit 1 -fi - -scriptDir=$(cd $(dirname $0) && pwd) - -TOPDIR="$scriptDir/../.." -RUNTIME="$TOPDIR/src/library/scala/runtime" -SOURCES="$RUNTIME/BoxesRunTime.java $RUNTIME/ScalaRunTime.scala" -SCALAC=$TOPDIR/$1/pack/bin/scalac -SRC_DIR="$scriptDir/library/scala/runtime" -SCALALIB=$TOPDIR/$1/pack/lib/scala-library.jar -CLASSDIR="$scriptDir/classes" -ARTIFACT=instrumented.jar -DESTINATION="$TOPDIR/test/files/speclib" - -[[ -x "$SCALAC" ]] || exit 1; - -# compile it -run rm -rf $CLASSDIR && mkdir $CLASSDIR -run cp $SOURCES $SRC_DIR -( cd $SRC_DIR && run patch BoxesRunTime.java $scriptDir/boxes.patch && run patch ScalaRunTime.scala $scriptDir/srt.patch ) - -ORIG=$(find $SRC_DIR -name '*.orig') -[[ -z "$ORIG" ]] || rm -f $ORIG - -JSOURCES=$(find $SRC_DIR -name "*.java" -print) -SOURCES=$(find $SRC_DIR -type f -print) -# echo $SOURCES -run $SCALAC -d $CLASSDIR $SOURCES -run javac -cp $SCALALIB -d $CLASSDIR $JSOURCES - -# jar it up -run cd $CLASSDIR -run jar cf $ARTIFACT . -run mv -f $ARTIFACT "$DESTINATION" -echo "$(cd "$DESTINATION" && pwd)/$ARTIFACT has been created." \ No newline at end of file From 8c67170fe9c5a83a131a356be05696bd14df64b4 Mon Sep 17 00:00:00 2001 From: Martijn Hoekstra Date: Fri, 20 Jul 2018 13:56:27 +0200 Subject: [PATCH 066/143] fix searching --- src/library/scala/collection/IndexedSeq.scala | 7 +++-- src/library/scala/collection/Seq.scala | 7 +++-- test/junit/scala/collection/SeqTests.scala | 31 +++++++++++++++++++ .../collection/immutable/ArraySeqTest.scala | 2 ++ .../scala/collection/immutable/ListTest.scala | 2 ++ .../collection/immutable/VectorTest.scala | 3 ++ 6 files changed, 48 insertions(+), 4 deletions(-) create mode 100644 test/junit/scala/collection/SeqTests.scala diff --git a/src/library/scala/collection/IndexedSeq.scala b/src/library/scala/collection/IndexedSeq.scala index b69cff729760..46f02c5fe9c1 100644 --- a/src/library/scala/collection/IndexedSeq.scala +++ b/src/library/scala/collection/IndexedSeq.scala @@ -65,8 +65,11 @@ trait IndexedSeqOps[+A, +CC[_], +C] extends Any with SeqOps[A, CC, C] { self => @tailrec private[this] def binarySearch[B >: A](elem: B, from: Int, to: Int) (implicit ord: Ordering[B]): SearchResult = { - if (to == from) InsertionPoint(from) else { - val idx = from+(to-from-1)/2 + if (from < 0) binarySearch(elem, 0, to) + else if (to > length) binarySearch(elem, from, length) + else if (to <= from) InsertionPoint(from) + else { + val idx = from + (to - from - 1) / 2 math.signum(ord.compare(elem, apply(idx))) match { case -1 => binarySearch(elem, from, idx)(ord) case 1 => binarySearch(elem, idx + 1, to)(ord) diff --git a/src/library/scala/collection/Seq.scala b/src/library/scala/collection/Seq.scala index 37d5d47351fe..27b45acff67b 100644 --- a/src/library/scala/collection/Seq.scala +++ b/src/library/scala/collection/Seq.scala @@ -853,9 +853,12 @@ trait SeqOps[+A, +CC[_], +C] extends Any * @return a `Found` value containing the index corresponding to the element in the * sequence, or the `InsertionPoint` where the element would be inserted if * the element is not in the sequence. + * + * @note if `to <= from`, the search space is empty, and an `InsertionPoint` at `from` + * is returned */ - def search[B >: A](elem: B, from: Int, to: Int) (implicit ord: Ordering[B]): SearchResult = - linearSearch(view.slice(from, to), elem, from)(ord) + def search[B >: A](elem: B, from: Int, to: Int) (implicit ord: Ordering[B]): SearchResult = + linearSearch(view.slice(from, to), elem, math.max(0, from))(ord) private[this] def linearSearch[B >: A](c: View[A], elem: B, offset: Int) (implicit ord: Ordering[B]): SearchResult = { diff --git a/test/junit/scala/collection/SeqTests.scala b/test/junit/scala/collection/SeqTests.scala new file mode 100644 index 000000000000..b4f04ac34a7d --- /dev/null +++ b/test/junit/scala/collection/SeqTests.scala @@ -0,0 +1,31 @@ +package scala.collection.immutable + +import org.junit.{Assert, Test} + +object SeqTests { + def checkSearch[A](seq: Seq[A], needle: A, ord: Ordering[A]): Unit = { + import scala.collection.Searching.{Found, InsertionPoint} + val size = seq.size + val indices = List(-1, -10, -99, Int.MinValue, 0, size -1, size, size + 1, size + 10, Int.MaxValue) + for { + from <- indices + to <- indices + } { + val sorted = seq.sorted(ord) + sorted.search(needle, from, to)(ord) match { + case Found(foundIndex: Int) => { + val found = sorted(foundIndex) + Assert.assertTrue(s"found value $found not equivalent to searched value $needle in List(0-1000) between indices $from and $to", ord.equiv(found, needle)) + } + case InsertionPoint(insertionPoint: Int) => + for ((e, i) <- sorted.zipWithIndex) { + if(i >= from && i < to) { + if(i < insertionPoint) Assert.assertFalse(s"a value before the insertion point was greater than $needle", ord.gt(e, needle)) + else Assert.assertFalse(s"a values past the insertion point was smaller than $needle", ord.lt(e, needle)) + } + //else we don't want to make any statements for values out of that range + } + } + } + } +} \ No newline at end of file diff --git a/test/junit/scala/collection/immutable/ArraySeqTest.scala b/test/junit/scala/collection/immutable/ArraySeqTest.scala index affc8d536940..e42d2134877f 100644 --- a/test/junit/scala/collection/immutable/ArraySeqTest.scala +++ b/test/junit/scala/collection/immutable/ArraySeqTest.scala @@ -73,4 +73,6 @@ class ArraySeqTest { assertEquals(ArraySeq.empty[T], array.slice(1, 1)) assertEquals(ArraySeq.empty[T], array.slice(2, 1)) } + + @Test def checkSearch: Unit = SeqTests.checkSearch(ArraySeq(0 to 1000: _*), 15, implicitly[Ordering[Int]]) } \ No newline at end of file diff --git a/test/junit/scala/collection/immutable/ListTest.scala b/test/junit/scala/collection/immutable/ListTest.scala index d600887f4ebb..c15d4ae5cca1 100644 --- a/test/junit/scala/collection/immutable/ListTest.scala +++ b/test/junit/scala/collection/immutable/ListTest.scala @@ -65,4 +65,6 @@ class ListTest { case e: IndexOutOfBoundsException => () } } + + @Test def checkSearch: Unit = SeqTests.checkSearch(List(0 to 1000: _*), 15, implicitly[Ordering[Int]]) } diff --git a/test/junit/scala/collection/immutable/VectorTest.scala b/test/junit/scala/collection/immutable/VectorTest.scala index 06f123084f14..92d109b82416 100644 --- a/test/junit/scala/collection/immutable/VectorTest.scala +++ b/test/junit/scala/collection/immutable/VectorTest.scala @@ -39,4 +39,7 @@ class VectorTest { assertEquals(els, prefix.toList ++: suffix) } } + + @Test def checkSearch: Unit = SeqTests.checkSearch(Vector(0 to 1000: _*), 15, implicitly[Ordering[Int]]) + } From a7ac9013ad4ad2b95f8a5bb550f9880cd4c538b7 Mon Sep 17 00:00:00 2001 From: Stefan Zeiger Date: Tue, 5 Jun 2018 20:01:10 +0200 Subject: [PATCH 067/143] Use applyOrElse for PartialFunctions This avoids evaluating the guards twice. It can be significantly (25% in my benchmarks) slower in the worst case (a PF with a single clause with very efficient guard that usually does not match) but can have much larger performance gains in other scenarios. All flatMap-based implementations suitable for lazy collection types are replaced by a new `View.Collect` primitive that uses an Iterator instead, which is considerably faster. --- src/library/scala/collection/Iterable.scala | 5 +--- src/library/scala/collection/Iterator.scala | 14 +++++++--- src/library/scala/collection/Map.scala | 5 +--- src/library/scala/collection/SortedMap.scala | 5 +--- src/library/scala/collection/SortedSet.scala | 5 +--- .../StrictOptimizedIterableOps.scala | 7 ++--- .../StrictOptimizedSortedSetOps.scala | 1 + src/library/scala/collection/View.scala | 6 +++++ .../scala/collection/immutable/IntMap.scala | 2 +- .../scala/collection/immutable/LongMap.scala | 2 +- .../scala/collection/mutable/AnyRefMap.scala | 5 +--- .../scala/collection/mutable/LongMap.scala | 2 +- src/library/scala/runtime/Statics.java | 3 +++ src/library/scala/util/Try.scala | 26 ++++++++++++++----- 14 files changed, 52 insertions(+), 36 deletions(-) diff --git a/src/library/scala/collection/Iterable.scala b/src/library/scala/collection/Iterable.scala index 89cbc9e48b91..d6bb509cf054 100644 --- a/src/library/scala/collection/Iterable.scala +++ b/src/library/scala/collection/Iterable.scala @@ -564,10 +564,7 @@ trait IterableOps[+A, +CC[_], +C] extends Any with IterableOnce[A] with Iterable fromIterable(new View.FlatMap(this, asIterable)) def collect[B](pf: PartialFunction[A, B]): CC[B] = - flatMap { a => - if (pf.isDefinedAt(a)) new View.Single(pf(a)) - else View.Empty - } + fromIterable(new View.Collect(this, pf)) /** Returns a new $coll containing the elements from the left hand operand followed by the elements from the * right hand operand. The element type of the $coll is the most specific superclass encompassing diff --git a/src/library/scala/collection/Iterator.scala b/src/library/scala/collection/Iterator.scala index 9c426f526e7a..4657560a54a6 100644 --- a/src/library/scala/collection/Iterator.scala +++ b/src/library/scala/collection/Iterator.scala @@ -5,6 +5,7 @@ import java.io.{ObjectInputStream, ObjectOutputStream} import scala.collection.mutable.{ArrayBuffer, Builder, ImmutableBuilder} import scala.annotation.tailrec import scala.annotation.unchecked.uncheckedVariance +import scala.runtime.Statics /** Iterators are data structures that allow to iterate over a sequence * of elements. They have a `hasNext` method for checking @@ -477,7 +478,7 @@ trait Iterator[+A] extends IterableOnce[A] with IterableOnceOps[A, Iterator, Ite def collect[B](pf: PartialFunction[A, B]): Iterator[B] = new AbstractIterator[B] { // Manually buffer to avoid extra layer of wrapping with buffered - private[this] var hd: A = _ + private[this] var hd: B = _ // Little state machine to keep track of where we are // Seek = 0; Found = 1; Empty = -1 @@ -486,16 +487,21 @@ trait Iterator[+A] extends IterableOnce[A] with IterableOnceOps[A, Iterator, Ite private[this] var status = 0/*Seek*/ def hasNext = { + val marker = Statics.pfMarker while (status == 0/*Seek*/) { if (self.hasNext) { - hd = self.next() - if (pf.isDefinedAt(hd)) status = 1/*Found*/ + val x = self.next() + val v = pf.applyOrElse(x, ((x: A) => marker).asInstanceOf[A => B]) + if (marker ne v.asInstanceOf[AnyRef]) { + hd = v + status = 1/*Found*/ + } } else status = -1/*Empty*/ } status == 1/*Found*/ } - def next() = if (hasNext) { status = 0/*Seek*/; pf(hd) } else Iterator.empty.next() + def next() = if (hasNext) { status = 0/*Seek*/; hd } else Iterator.empty.next() } /** diff --git a/src/library/scala/collection/Map.scala b/src/library/scala/collection/Map.scala index b9971740052c..b889769d3aa5 100644 --- a/src/library/scala/collection/Map.scala +++ b/src/library/scala/collection/Map.scala @@ -255,10 +255,7 @@ trait MapOps[K, +V, +CC[_, _] <: IterableOps[_, AnyConstr, _], +C] * The order of the elements is preserved. */ def collect[K2, V2](pf: PartialFunction[(K, V), (K2, V2)]): CC[K2, V2] = - flatMap { a => - if (pf.isDefinedAt(a)) new View.Single(pf(a)) - else View.Empty - } + mapFactory.from(new View.Collect(toIterable, pf)) /** Builds a new map by applying a function to all elements of this $coll * and using the elements of the resulting collections. diff --git a/src/library/scala/collection/SortedMap.scala b/src/library/scala/collection/SortedMap.scala index fb061985b895..83f40e635c76 100644 --- a/src/library/scala/collection/SortedMap.scala +++ b/src/library/scala/collection/SortedMap.scala @@ -166,10 +166,7 @@ trait SortedMapOps[K, +V, +CC[X, Y] <: Map[X, Y] with SortedMapOps[X, Y, CC, _], * The order of the elements is preserved. */ def collect[K2, V2](pf: PartialFunction[(K, V), (K2, V2)])(implicit @implicitNotFound(SortedMapOps.ordMsg) ordering: Ordering[K2]): CC[K2, V2] = - flatMap { kv => - if (pf.isDefinedAt(kv)) new View.Single(pf(kv)) - else View.Empty - } + sortedMapFactory.from(new View.Collect(toIterable, pf)) override def concat[V2 >: V](xs: Iterable[(K, V2)]): CC[K, V2] = sortedMapFactory.from(new View.Concat(toIterable, xs)) diff --git a/src/library/scala/collection/SortedSet.scala b/src/library/scala/collection/SortedSet.scala index 4d36ffc6c377..dc7804540068 100644 --- a/src/library/scala/collection/SortedSet.scala +++ b/src/library/scala/collection/SortedSet.scala @@ -135,10 +135,7 @@ trait SortedSetOps[A, +CC[X] <: SortedSet[X], +C <: SortedSetOps[A, CC, C]] * The order of the elements is preserved. */ def collect[B](pf: scala.PartialFunction[A, B])(implicit @implicitNotFound(SortedSetOps.ordMsg) ev: Ordering[B]): CC[B] = - flatMap(a => - if (pf.isDefinedAt(a)) new View.Single(pf(a)) - else View.Empty) - + sortedFromIterable(new View.Collect(toIterable, pf)) } object SortedSetOps { diff --git a/src/library/scala/collection/StrictOptimizedIterableOps.scala b/src/library/scala/collection/StrictOptimizedIterableOps.scala index f838b2e04b20..5ecd78a76d0b 100644 --- a/src/library/scala/collection/StrictOptimizedIterableOps.scala +++ b/src/library/scala/collection/StrictOptimizedIterableOps.scala @@ -3,6 +3,7 @@ package collection import scala.annotation.unchecked.uncheckedVariance import scala.language.higherKinds +import scala.runtime.Statics /** * Trait that overrides iterable operations to take advantage of strict builders. @@ -136,12 +137,12 @@ trait StrictOptimizedIterableOps[+A, +CC[_], +C] * @return The resulting collection */ @inline protected[this] final def strictOptimizedCollect[B, C2](b: mutable.Builder[B, C2], pf: PartialFunction[A, B]): C2 = { + val marker = Statics.pfMarker val it = iterator while (it.hasNext) { val elem = it.next() - if (pf.isDefinedAt(elem)) { - b += pf.apply(elem) - } + val v = pf.applyOrElse(elem, ((x: A) => marker).asInstanceOf[Function[A, B]]) + if (marker ne v.asInstanceOf[AnyRef]) b += v } b.result() } diff --git a/src/library/scala/collection/StrictOptimizedSortedSetOps.scala b/src/library/scala/collection/StrictOptimizedSortedSetOps.scala index 48a350275131..b9713f19b3ce 100644 --- a/src/library/scala/collection/StrictOptimizedSortedSetOps.scala +++ b/src/library/scala/collection/StrictOptimizedSortedSetOps.scala @@ -5,6 +5,7 @@ package collection import scala.annotation.implicitNotFound import scala.annotation.unchecked.uncheckedVariance import scala.language.higherKinds +import scala.runtime.Statics /** * Trait that overrides sorted set operations to take advantage of strict builders. diff --git a/src/library/scala/collection/View.scala b/src/library/scala/collection/View.scala index d7d18b71efde..2cbf45981e9f 100644 --- a/src/library/scala/collection/View.scala +++ b/src/library/scala/collection/View.scala @@ -219,6 +219,12 @@ object View extends IterableFactory[View] { def iterator = underlying.iterator.flatMap(f) } + /** A view that collects elements of the underlying collection. */ + @SerialVersionUID(3L) + class Collect[+A, B](underlying: SomeIterableOps[A], pf: PartialFunction[A, B]) extends AbstractView[B] { + def iterator = underlying.iterator.collect(pf) + } + /** A view that concatenates elements of the prefix collection or iterator with the elements * of the suffix collection or iterator. */ diff --git a/src/library/scala/collection/immutable/IntMap.scala b/src/library/scala/collection/immutable/IntMap.scala index a939fe900fb2..8c74ea694843 100644 --- a/src/library/scala/collection/immutable/IntMap.scala +++ b/src/library/scala/collection/immutable/IntMap.scala @@ -328,7 +328,7 @@ sealed abstract class IntMap[+T] extends AbstractMap[Int, T] override def ++ [V1 >: T](that: collection.Iterable[(Int, V1)]): IntMap[V1] = concat(that) def collect[V2](pf: PartialFunction[(Int, T), (Int, V2)]): IntMap[V2] = - flatMap(kv => if (pf.isDefinedAt(kv)) new View.Single(pf(kv)) else View.Empty) + strictOptimizedCollect(IntMap.newBuilder[V2], pf) /** * Updates the map, using the provided function to resolve conflicts if the key is already present. diff --git a/src/library/scala/collection/immutable/LongMap.scala b/src/library/scala/collection/immutable/LongMap.scala index be52ebd66f34..c980c107309a 100644 --- a/src/library/scala/collection/immutable/LongMap.scala +++ b/src/library/scala/collection/immutable/LongMap.scala @@ -479,7 +479,7 @@ sealed abstract class LongMap[+T] extends AbstractMap[Long, T] override def ++ [V1 >: T](that: scala.collection.Iterable[(Long, V1)]): LongMap[V1] = concat(that) def collect[V2](pf: PartialFunction[(Long, T), (Long, V2)]): LongMap[V2] = - flatMap(kv => if (pf.isDefinedAt(kv)) new View.Single(pf(kv)) else View.Empty) + strictOptimizedCollect(LongMap.newBuilder[V2], pf) override protected[this] def writeReplace(): AnyRef = new DefaultSerializationProxy(LongMap.toFactory[T](LongMap), this) } diff --git a/src/library/scala/collection/mutable/AnyRefMap.scala b/src/library/scala/collection/mutable/AnyRefMap.scala index 0eaf5eb6a125..9c260ac34f22 100644 --- a/src/library/scala/collection/mutable/AnyRefMap.scala +++ b/src/library/scala/collection/mutable/AnyRefMap.scala @@ -432,10 +432,7 @@ class AnyRefMap[K <: AnyRef, V] private[collection] (defaultEntry: K => V, initi def flatMap[K2 <: AnyRef, V2](f: ((K with AnyRef, V)) => IterableOnce[(K2, V2)]): AnyRefMap[K2, V2] = AnyRefMap.from(new View.FlatMap(toIterable, f)) def collect[K2 <: AnyRef, V2](pf: PartialFunction[(K with AnyRef, V), (K2, V2)]): AnyRefMap[K2, V2] = - flatMap { kv: (K with AnyRef, V) => - if (pf.isDefinedAt(kv)) new View.Single(pf(kv)) - else View.Empty - } + strictOptimizedCollect(AnyRefMap.newBuilder[K2, V2], pf) override protected[this] def writeReplace(): AnyRef = new DefaultSerializationProxy(AnyRefMap.toFactory[K, V](AnyRefMap), this) diff --git a/src/library/scala/collection/mutable/LongMap.scala b/src/library/scala/collection/mutable/LongMap.scala index 403469e62701..e7eacca39b5e 100644 --- a/src/library/scala/collection/mutable/LongMap.scala +++ b/src/library/scala/collection/mutable/LongMap.scala @@ -526,7 +526,7 @@ final class LongMap[V] private[collection] (defaultEntry: Long => V, initialBuff def flatMap[V2](f: ((Long, V)) => IterableOnce[(Long, V2)]): LongMap[V2] = LongMap.from(new View.FlatMap(coll, f)) def collect[V2](pf: PartialFunction[(Long, V), (Long, V2)]): LongMap[V2] = - flatMap(kv => if (pf.isDefinedAt(kv)) new View.Single(pf(kv)) else View.Empty) + strictOptimizedCollect(LongMap.newBuilder[V2], pf) override protected[this] def writeReplace(): AnyRef = new DefaultSerializationProxy(LongMap.toFactory[V](LongMap), this) diff --git a/src/library/scala/runtime/Statics.java b/src/library/scala/runtime/Statics.java index 62390cb9d030..85d20a5e2e05 100644 --- a/src/library/scala/runtime/Statics.java +++ b/src/library/scala/runtime/Statics.java @@ -114,4 +114,7 @@ public static int anyHash(Object x) { return x.hashCode(); } + + /** Used as a marker object to return from PartialFunctions */ + public static final Object pfMarker = new Object(); } diff --git a/src/library/scala/util/Try.scala b/src/library/scala/util/Try.scala index 675236e08877..26a4567e29e4 100644 --- a/src/library/scala/util/Try.scala +++ b/src/library/scala/util/Try.scala @@ -9,6 +9,7 @@ package scala package util +import scala.runtime.Statics import scala.util.control.NonFatal /** @@ -225,10 +226,20 @@ final case class Failure[+T](exception: Throwable) extends Try[T] { override def map[U](f: T => U): Try[U] = this.asInstanceOf[Try[U]] override def collect[U](pf: PartialFunction[T, U]): Try[U] = this.asInstanceOf[Try[U]] override def filter(p: T => Boolean): Try[T] = this - override def recover[U >: T](pf: PartialFunction[Throwable, U]): Try[U] = - try { if (pf isDefinedAt exception) Success(pf(exception)) else this } catch { case NonFatal(e) => Failure(e) } - override def recoverWith[U >: T](pf: PartialFunction[Throwable, Try[U]]): Try[U] = - try { if (pf isDefinedAt exception) pf(exception) else this } catch { case NonFatal(e) => Failure(e) } + override def recover[U >: T](pf: PartialFunction[Throwable, U]): Try[U] = { + val marker = Statics.pfMarker + try { + val v = pf.applyOrElse(exception, ((x: Throwable) => marker).asInstanceOf[Function[Throwable, U]]) + if (marker ne v.asInstanceOf[AnyRef]) Success(v) else this + } catch { case NonFatal(e) => Failure(e) } + } + override def recoverWith[U >: T](pf: PartialFunction[Throwable, Try[U]]): Try[U] = { + val marker = Statics.pfMarker + try { + val v = pf.applyOrElse(exception, ((x: Throwable) => marker).asInstanceOf[Function[Throwable, Try[U]]]) + if (marker ne v.asInstanceOf[AnyRef]) v else this + } catch { case NonFatal(e) => Failure(e) } + } override def failed: Try[Throwable] = Success(exception) override def toOption: Option[T] = None override def toEither: Either[Throwable, T] = Left(exception) @@ -248,11 +259,14 @@ final case class Success[+T](value: T) extends Try[T] { override def foreach[U](f: T => U): Unit = f(value) override def transform[U](s: T => Try[U], f: Throwable => Try[U]): Try[U] = this flatMap s override def map[U](f: T => U): Try[U] = Try[U](f(value)) - override def collect[U](pf: PartialFunction[T, U]): Try[U] = + override def collect[U](pf: PartialFunction[T, U]): Try[U] = { + val marker = Statics.pfMarker try { - if (pf isDefinedAt value) Success(pf(value)) + val v = pf.applyOrElse(value, ((x: T) => marker).asInstanceOf[Function[T, U]]) + if (marker ne v.asInstanceOf[AnyRef]) Success(v) else Failure(new NoSuchElementException("Predicate does not hold for " + value)) } catch { case NonFatal(e) => Failure(e) } + } override def filter(p: T => Boolean): Try[T] = try { if (p(value)) this else Failure(new NoSuchElementException("Predicate does not hold for " + value)) From 73bea15b9dc811a80043762699892e5bee0538ea Mon Sep 17 00:00:00 2001 From: NthPortal Date: Fri, 20 Jul 2018 15:49:45 -0400 Subject: [PATCH 068/143] [bug#11028] Fix CCE in StringOps.toArray[Any] --- src/library/scala/collection/StringOps.scala | 5 +++-- test/junit/scala/collection/StringOpsTest.scala | 4 ++++ 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/src/library/scala/collection/StringOps.scala b/src/library/scala/collection/StringOps.scala index dab9b857f146..7f65d32863eb 100644 --- a/src/library/scala/collection/StringOps.scala +++ b/src/library/scala/collection/StringOps.scala @@ -864,8 +864,9 @@ final class StringOps(private val s: String) extends AnyVal { else if (s.equalsIgnoreCase("false")) false else throw new IllegalArgumentException("For input string: \""+s+"\"") - def toArray[B >: Char : ClassTag]: Array[B] = - s.toCharArray.asInstanceOf[Array[B]] + def toArray[B >: Char](implicit tag: ClassTag[B]): Array[B] = + if (tag == ClassTag.Char) s.toCharArray.asInstanceOf[Array[B]] + else new WrappedString(s).toArray[B] private[this] def unwrapArg(arg: Any): AnyRef = arg match { case x: ScalaNumber => x.underlying diff --git a/test/junit/scala/collection/StringOpsTest.scala b/test/junit/scala/collection/StringOpsTest.scala index 8bc7860e5863..6884e49684ea 100644 --- a/test/junit/scala/collection/StringOpsTest.scala +++ b/test/junit/scala/collection/StringOpsTest.scala @@ -20,4 +20,8 @@ class StringOpsTest { assert("a".addString(new StringBuilder, ",").toString == "a") assert("".addString(new StringBuilder, "foo", ",", "bar").toString == "foobar") } + + @Test def toArray(): Unit = { + assert("".toArray[Any].length == 0) // should not throw + } } From da4b337922578bfa6fc8f29f8dc55e4f473be133 Mon Sep 17 00:00:00 2001 From: xuwei-k <6b656e6a69@gmail.com> Date: Sat, 21 Jul 2018 18:17:17 +0900 Subject: [PATCH 069/143] fix any2stringadd warnings --- .../collection/mutable/FlatHashTable.scala | 2 +- .../reflect/internal/AnnotationInfos.scala | 2 +- .../scala/reflect/internal/Definitions.scala | 2 +- .../scala/reflect/internal/Importers.scala | 2 +- src/reflect/scala/reflect/internal/Kinds.scala | 6 +++--- .../scala/reflect/internal/Symbols.scala | 2 +- .../scala/reflect/internal/TypeDebugging.scala | 2 +- src/reflect/scala/reflect/internal/Types.scala | 18 +++++++++--------- .../reflect/internal/tpe/TypeComparers.scala | 2 +- .../reflect/internal/util/SourceFile.scala | 2 +- .../internal/util/TraceSymbolActivity.scala | 2 +- 11 files changed, 21 insertions(+), 21 deletions(-) diff --git a/src/library/scala/collection/mutable/FlatHashTable.scala b/src/library/scala/collection/mutable/FlatHashTable.scala index f3ab7ede40d4..cddaec3c7cf6 100644 --- a/src/library/scala/collection/mutable/FlatHashTable.scala +++ b/src/library/scala/collection/mutable/FlatHashTable.scala @@ -224,7 +224,7 @@ private[mutable] final class FlatHashTable[A] extends FlatHashTable.HashUtils[A] private def checkConsistent() = { for (i <- 0 until table.length) if (table(i) != null && !containsElem(entryToElem(table(i)))) - assert(assertion = false, i+" "+table(i)+" "+table.mkString) + assert(assertion = false, s"$i ${table(i)} ${table.mkString}") } diff --git a/src/reflect/scala/reflect/internal/AnnotationInfos.scala b/src/reflect/scala/reflect/internal/AnnotationInfos.scala index 9e3d4a935c30..dd7c94849a22 100644 --- a/src/reflect/scala/reflect/internal/AnnotationInfos.scala +++ b/src/reflect/scala/reflect/internal/AnnotationInfos.scala @@ -158,7 +158,7 @@ trait AnnotationInfos extends api.Annotations { self: SymbolTable => private[scala] def completeAnnotationToString(annInfo: AnnotationInfo) = { import annInfo._ val s_args = if (!args.isEmpty) args.mkString("(", ", ", ")") else "" - val s_assocs = if (!assocs.isEmpty) (assocs map { case (x, y) => x+" = "+y } mkString ("(", ", ", ")")) else "" + val s_assocs = if (!assocs.isEmpty) (assocs map { case (x, y) => s"$x = $y" } mkString ("(", ", ", ")")) else "" s"${atp}${s_args}${s_assocs}" } diff --git a/src/reflect/scala/reflect/internal/Definitions.scala b/src/reflect/scala/reflect/internal/Definitions.scala index 6df1c2a87e53..43d4336c50b8 100644 --- a/src/reflect/scala/reflect/internal/Definitions.scala +++ b/src/reflect/scala/reflect/internal/Definitions.scala @@ -1224,7 +1224,7 @@ trait Definitions extends api.StandardDefinitions { } private def fatalMissingSymbol(owner: Symbol, name: Name, what: String = "member", addendum: String = "") = { - throw new FatalError(owner + " does not have a " + what + " " + name + addendum) + throw new FatalError(s"$owner does not have a $what ${name}${addendum}") } def getLanguageFeature(name: String, owner: Symbol = languageFeatureModule): Symbol = getMember(owner, newTypeName(name)) diff --git a/src/reflect/scala/reflect/internal/Importers.scala b/src/reflect/scala/reflect/internal/Importers.scala index 5b49496f4b4b..4bf3909dfa7f 100644 --- a/src/reflect/scala/reflect/internal/Importers.scala +++ b/src/reflect/scala/reflect/internal/Importers.scala @@ -193,7 +193,7 @@ trait Importers { to: SymbolTable => myexisting.orElse { val my = cachedRecreateSymbol(their) if (myscope != NoType) { - assert(myscope.decls.lookup(myname) == NoSymbol, myname+" "+myscope.decl(myname)+" "+myexisting) + assert(myscope.decls.lookup(myname) == NoSymbol, s"$myname ${myscope.decl(myname)} $myexisting") myscope.decls enter my } my diff --git a/src/reflect/scala/reflect/internal/Kinds.scala b/src/reflect/scala/reflect/internal/Kinds.scala index 7ef0b26daa29..a7e2b21f3478 100644 --- a/src/reflect/scala/reflect/internal/Kinds.scala +++ b/src/reflect/scala/reflect/internal/Kinds.scala @@ -47,7 +47,7 @@ trait Kinds { } } private def kindMessage(a: Symbol, p: Symbol)(f: (String, String) => String): String = - f(a+qualify(a,p), p+qualify(p,a)) + f(a.toString+qualify(a,p), p.toString+qualify(p,a)) // Normally it's nicer to print nothing rather than '>: Nothing <: Any' all over // the place, but here we need it for the message to make sense. @@ -74,7 +74,7 @@ trait Kinds { ) def errorMessage(targ: Type, tparam: Symbol): String = ( - (targ+"'s type parameters do not match "+tparam+"'s expected parameters:") + (s"${targ}'s type parameters do not match ${tparam}'s expected parameters:") + buildMessage(arity, arityMessage) + buildMessage(variance, varianceMessage) + buildMessage(strictness, strictnessMessage) @@ -335,7 +335,7 @@ trait Kinds { private[internal] def buildState(sym: Symbol, v: Variance)(s: StringState): StringState = { s.append(v.symbolicString).appendHead(order, sym).append(bounds.scalaNotation(_.toString)) } - def scalaNotation: String = Kind.Head(order, None, None) + bounds.scalaNotation(_.toString) + def scalaNotation: String = Kind.Head(order, None, None).toString + bounds.scalaNotation(_.toString) def starNotation: String = "*" + bounds.starNotation(_.toString) } object ProperTypeKind { diff --git a/src/reflect/scala/reflect/internal/Symbols.scala b/src/reflect/scala/reflect/internal/Symbols.scala index 739081dfbf8c..91b2ad6d6fb7 100644 --- a/src/reflect/scala/reflect/internal/Symbols.scala +++ b/src/reflect/scala/reflect/internal/Symbols.scala @@ -2580,7 +2580,7 @@ trait Symbols extends api.Symbols { self: SymbolTable => * (the initial Name) before falling back on id, which varies depending * on exactly when a symbol is loaded. */ - final def sealedSortName: String = initName + "#" + id + final def sealedSortName: String = initName.toString + "#" + id /** String representation of symbol's definition key word */ final def keyString: String = diff --git a/src/reflect/scala/reflect/internal/TypeDebugging.scala b/src/reflect/scala/reflect/internal/TypeDebugging.scala index b9b022945351..c6e04dc31031 100644 --- a/src/reflect/scala/reflect/internal/TypeDebugging.scala +++ b/src/reflect/scala/reflect/internal/TypeDebugging.scala @@ -114,7 +114,7 @@ trait TypeDebugging { } def ptTypeParam(td: TypeDef): String = { val TypeDef(_, name, tparams, rhs) = td - name + ptTypeParams(tparams) + ptTree(rhs) + name.toString + ptTypeParams(tparams) + ptTree(rhs) } def ptTypeParams(tparams: List[TypeDef]): String = str brackets (tparams map ptTypeParam) diff --git a/src/reflect/scala/reflect/internal/Types.scala b/src/reflect/scala/reflect/internal/Types.scala index 19610de9afec..23bcbd75e5c9 100644 --- a/src/reflect/scala/reflect/internal/Types.scala +++ b/src/reflect/scala/reflect/internal/Types.scala @@ -1594,7 +1594,7 @@ trait Types val period = tpe.baseClassesPeriod if (period == currentPeriod) { if (force && breakCycles) { - def what = tpe.typeSymbol + " in " + tpe.typeSymbol.owner.fullNameString + def what = tpe.typeSymbol.toString + " in " + tpe.typeSymbol.owner.fullNameString val bcs = computeBaseClasses(tpe) tpe.baseClassesCache = bcs warning(s"Breaking cycle in base class computation of $what ($bcs)") @@ -2445,7 +2445,7 @@ trait Types s"$lstr ${sym.decodedName} $rstr" } private def customToString = sym match { - case RepeatedParamClass | JavaRepeatedParamClass => args.head + "*" + case RepeatedParamClass | JavaRepeatedParamClass => args.head.toString + "*" case ByNameParamClass => "=> " + args.head case _ => if (isFunctionTypeDirect(this)) { @@ -2489,7 +2489,7 @@ trait Types else if (sym.isPackageClass || sym.isPackageObjectOrClass) sym.skipPackageObject.fullName + "." else if (isStable && nme.isSingletonName(sym.name)) - tpnme.dropSingletonName(sym.name) + "." + tpnme.dropSingletonName(sym.name).toString + "." else super.prefixString ) @@ -2884,10 +2884,10 @@ trait Types override def nameAndArgsString: String = underlying match { case TypeRef(_, sym, args) if !settings.debug && isRepresentableWithWildcards => - sym.name + wildcardArgsString(quantified.toSet, args).mkString("[", ",", "]") + sym.name.toString + wildcardArgsString(quantified.toSet, args).mkString("[", ",", "]") case TypeRef(_, sym, args) => - sym.name + args.mkString("[", ",", "]") + existentialClauses - case _ => underlying.typeSymbol.name + existentialClauses + sym.name.toString + args.mkString("[", ",", "]") + existentialClauses + case _ => underlying.typeSymbol.name.toString + existentialClauses } private def existentialClauses = { @@ -3558,7 +3558,7 @@ trait Types override def isTrivial: Boolean = underlying.isTrivial && annotations.forall(_.isTrivial) - override def safeToString = annotations.mkString(underlying + " @", " @", "") + override def safeToString = annotations.mkString(underlying.toString + " @", " @", "") override def filterAnnotations(p: AnnotationInfo => Boolean): Type = { val (yes, no) = annotations partition p @@ -3649,7 +3649,7 @@ trait Types * at the end of it. */ case class RepeatedType(tp: Type) extends Type { - override def safeToString: String = tp + ": _*" + override def safeToString: String = tp.toString + ": _*" // TODO is this needed? We only seem to get here in ContainsCollector in error message generation // override def mapOver(map: TypeMap): Type = map.apply(tp) } @@ -3879,7 +3879,7 @@ trait Types if (false && isDefinitionsInitialized) { assert(isUseableAsTypeArgs(args), { val tapp_s = s"""$tycon[${args mkString ", "}]""" - val arg_s = args filterNot isUseableAsTypeArg map (t => t + "/" + t.getClass) mkString ", " + val arg_s = args filterNot isUseableAsTypeArg map (t => t.toString + "/" + t.getClass) mkString ", " s"$tapp_s includes illegal type argument $arg_s" }) } diff --git a/src/reflect/scala/reflect/internal/tpe/TypeComparers.scala b/src/reflect/scala/reflect/internal/tpe/TypeComparers.scala index 7aba5b359f73..8b8bfc23f9af 100644 --- a/src/reflect/scala/reflect/internal/tpe/TypeComparers.scala +++ b/src/reflect/scala/reflect/internal/tpe/TypeComparers.scala @@ -28,7 +28,7 @@ trait TypeComparers { // // I added a tests to show that we detect the cycle: neg/t8146-no-finitary* - override def toString = tp1+" <:= " + length) + assert(offset < length, file.toString + ": " + offset + " >= " + length) Position.offset(this, offset) } diff --git a/src/reflect/scala/reflect/internal/util/TraceSymbolActivity.scala b/src/reflect/scala/reflect/internal/util/TraceSymbolActivity.scala index 3ee5e07981e9..5bdab6257e36 100644 --- a/src/reflect/scala/reflect/internal/util/TraceSymbolActivity.scala +++ b/src/reflect/scala/reflect/internal/util/TraceSymbolActivity.scala @@ -121,7 +121,7 @@ trait TraceSymbolActivity { "%4s owners (%s)".format( owners.size, - owners.take(3).map({ case (k, v) => v + "/" + k }).mkString(", ") + ", ..." + owners.take(3).map({ case (k, v) => s"${v}/${k}" }).mkString(", ") + ", ..." ) }) } From 757340adc2dba9ab46cbaf2eb974c55c59bf0bab Mon Sep 17 00:00:00 2001 From: xuwei-k <6b656e6a69@gmail.com> Date: Sun, 22 Jul 2018 10:59:32 +0900 Subject: [PATCH 070/143] add type parameter in foreachKey and foreachValue useful if parameter does not return `Unit` type ``` Welcome to Scala 2.13.0-M4 (Java HotSpot(TM) 64-Bit Server VM, Java 1.8.0_181). Type in expressions for evaluation. Or try :help. scala> def f[A]: A => A = { x => println(x); x } f: [A]=> A => A scala> collection.mutable.AnyRefMap("a" -> "b").foreachKey(f) a scala> collection.immutable.IntMap(1 -> 2).foreachKey(f) ^ error: type mismatch; found : scala.collection.immutable.IntMapUtils.Int => scala.collection.immutable.IntMapUtils.Int (which expands to) Int => Int required: scala.collection.immutable.IntMapUtils.Int => Unit (which expands to) Int => Unit scala> collection.immutable.IntMap(1 -> 2).foreachKey(f(_)) 1 ``` --- src/library/scala/collection/immutable/IntMap.scala | 4 ++-- src/library/scala/collection/immutable/LongMap.scala | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/library/scala/collection/immutable/IntMap.scala b/src/library/scala/collection/immutable/IntMap.scala index a939fe900fb2..4b66fa5236cd 100644 --- a/src/library/scala/collection/immutable/IntMap.scala +++ b/src/library/scala/collection/immutable/IntMap.scala @@ -235,7 +235,7 @@ sealed abstract class IntMap[+T] extends AbstractMap[Int, T] * * @param f The loop body */ - final def foreachKey(f: Int => Unit): Unit = this match { + final def foreachKey[U](f: Int => U): Unit = this match { case IntMap.Bin(_, _, left, right) => { left.foreachKey(f); right.foreachKey(f) } case IntMap.Tip(key, _) => f(key) case IntMap.Nil => @@ -252,7 +252,7 @@ sealed abstract class IntMap[+T] extends AbstractMap[Int, T] * * @param f The loop body */ - final def foreachValue(f: T => Unit): Unit = this match { + final def foreachValue[U](f: T => U): Unit = this match { case IntMap.Bin(_, _, left, right) => { left.foreachValue(f); right.foreachValue(f) } case IntMap.Tip(_, value) => f(value) case IntMap.Nil => diff --git a/src/library/scala/collection/immutable/LongMap.scala b/src/library/scala/collection/immutable/LongMap.scala index be52ebd66f34..36a452552f56 100644 --- a/src/library/scala/collection/immutable/LongMap.scala +++ b/src/library/scala/collection/immutable/LongMap.scala @@ -230,7 +230,7 @@ sealed abstract class LongMap[+T] extends AbstractMap[Long, T] * * @param f The loop body */ - final def foreachKey(f: Long => Unit): Unit = this match { + final def foreachKey[U](f: Long => U): Unit = this match { case LongMap.Bin(_, _, left, right) => { left.foreachKey(f); right.foreachKey(f) } case LongMap.Tip(key, _) => f(key) case LongMap.Nil => @@ -247,7 +247,7 @@ sealed abstract class LongMap[+T] extends AbstractMap[Long, T] * * @param f The loop body */ - final def foreachValue(f: T => Unit): Unit = this match { + final def foreachValue[U](f: T => U): Unit = this match { case LongMap.Bin(_, _, left, right) => { left.foreachValue(f); right.foreachValue(f) } case LongMap.Tip(_, value) => f(value) case LongMap.Nil => From 6be88fa875201d200609f96a82ce01563c99f727 Mon Sep 17 00:00:00 2001 From: xuwei-k <6b656e6a69@gmail.com> Date: Sat, 21 Jul 2018 17:54:02 +0900 Subject: [PATCH 071/143] add "since" argument for deprecated annotation --- src/library/scala/collection/immutable/LazyList.scala | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/library/scala/collection/immutable/LazyList.scala b/src/library/scala/collection/immutable/LazyList.scala index 36339426d681..ba67741b4fbf 100644 --- a/src/library/scala/collection/immutable/LazyList.scala +++ b/src/library/scala/collection/immutable/LazyList.scala @@ -747,13 +747,13 @@ sealed abstract class Stream[+A] extends AbstractSeq[A] with LinearSeq[A] with L if(headDefined && tailDefined) new LazyListOps.SerializationProxy[A, Stream](this) else this /** Prints elements of this stream one by one, separated by commas. */ - @deprecated("""Use print(stream.force.mkString(", ")) instead""") + @deprecated(message = """Use print(stream.force.mkString(", ")) instead""", since = "2.13.0") @inline def print(): Unit = Console.print(this.force.mkString(", ")) /** Prints elements of this stream one by one, separated by `sep`. * @param sep The separator string printed between consecutive elements. */ - @deprecated("Use print(stream.force.mkString(sep)) instead") + @deprecated(message = "Use print(stream.force.mkString(sep)) instead", since = "2.13.0") @inline def print(sep: String): Unit = Console.print(this.force.mkString(sep)) } From 38869f4985a215c24bc0fc05271c649dee4daabf Mon Sep 17 00:00:00 2001 From: Som Snytt Date: Mon, 23 Jul 2018 16:30:36 -0700 Subject: [PATCH 072/143] REPL load creates args For `:load file arg0 arg1`, always create a variable `args` to hold the args. Also use `CommandLineParser`. --- .../scala/tools/nsc/interpreter/shell/ILoop.scala | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/repl-frontend/scala/tools/nsc/interpreter/shell/ILoop.scala b/src/repl-frontend/scala/tools/nsc/interpreter/shell/ILoop.scala index 3ad87f8c3dd2..7b42c4c34195 100644 --- a/src/repl-frontend/scala/tools/nsc/interpreter/shell/ILoop.scala +++ b/src/repl-frontend/scala/tools/nsc/interpreter/shell/ILoop.scala @@ -659,15 +659,17 @@ class ILoop(config: ShellConfig, inOverride: BufferedReader = null, } def loadCommand(arg: String): Result = { - def run(file: String, verbose: Boolean) = withFile(file) { f => + import scala.tools.cmd.CommandLineParser + def run(file: String, args: List[String], verbose: Boolean) = withFile(file) { f => + intp.interpret(s"val args: Array[String] = ${ args.map("\"" + _ + "\"").mkString("Array(", ",", ")") }") interpretAllFrom(f, verbose) Result recording s":load $arg" } getOrElse Result.default - words(arg) match { - case "-v" :: file :: Nil => run(file, verbose = true) - case file :: Nil => run(file, verbose = false) - case _ => echo("usage: :load -v file") ; Result.default + CommandLineParser.tokenize(arg) match { + case "-v" :: file :: rest => run(file, rest, verbose = true) + case file :: rest => run(file, rest, verbose = false) + case _ => echo("usage: :load -v file") ; Result.default } } From e2480d82124d17b7811ce7f71354dd5b78a73e75 Mon Sep 17 00:00:00 2001 From: Jason Zaugg Date: Tue, 24 Jul 2018 10:00:20 +1000 Subject: [PATCH 073/143] Avoid needless storage/lookup for constants in Scope --- src/reflect/scala/reflect/internal/Scopes.scala | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/reflect/scala/reflect/internal/Scopes.scala b/src/reflect/scala/reflect/internal/Scopes.scala index b98cdff7ab3a..0c306d729587 100644 --- a/src/reflect/scala/reflect/internal/Scopes.scala +++ b/src/reflect/scala/reflect/internal/Scopes.scala @@ -83,12 +83,12 @@ trait Scopes extends api.Scopes { self: SymbolTable => /** size and mask of hash tables * todo: make hashtables grow? */ - private val HASHSIZE = 0x80 - private val HASHMASK = 0x7f + private final val HASHSIZE = 0x80 + private final val HASHMASK = 0x7f /** the threshold number of entries from which a hashtable is constructed. */ - private val MIN_HASH = 8 + private final val MIN_HASH = 8 /** Returns a new scope with the same content as this one. */ def cloneScope: Scope = newScopeWith(this.toList: _*) From 68161af6cbc622b17b14c929a3566460a6c0a4e0 Mon Sep 17 00:00:00 2001 From: NthPortal Date: Sat, 14 Jul 2018 15:21:19 -0400 Subject: [PATCH 074/143] Add size comparison methods to IterableOps Add IterableOps.sizeCompare(Int), .sizeCompare(Iterable[_]), and .sizeIs --- src/library/scala/collection/IndexedSeq.scala | 8 +- src/library/scala/collection/Iterable.scala | 102 ++++++++++++++++++ src/library/scala/collection/Seq.scala | 22 +--- ...rk.scala => SizeCompareOpsBenchmark.scala} | 12 +-- .../junit/scala/collection/IterableTest.scala | 32 +++++- 5 files changed, 150 insertions(+), 26 deletions(-) rename test/benchmarks/src/main/scala/scala/collection/{LengthCompareOpsBenchmark.scala => SizeCompareOpsBenchmark.scala} (72%) diff --git a/src/library/scala/collection/IndexedSeq.scala b/src/library/scala/collection/IndexedSeq.scala index 46f02c5fe9c1..7db3de2b7b0d 100644 --- a/src/library/scala/collection/IndexedSeq.scala +++ b/src/library/scala/collection/IndexedSeq.scala @@ -52,10 +52,16 @@ trait IndexedSeqOps[+A, +CC[_], +C] extends Any with SeqOps[A, CC, C] { self => override def last: A = apply(length - 1) - override def lengthCompare(len: Int): Int = Integer.compare(length, len) + override final def lengthCompare(len: Int): Int = Integer.compare(length, len) final override def knownSize: Int = length + override final def sizeCompare(that: Iterable[_]): Int = { + val res = that.sizeCompare(length) + // can't just invert the result, because `-Int.MinValue == Int.MinValue` + if (res == Int.MinValue) 1 else -res + } + override def search[B >: A](elem: B)(implicit ord: Ordering[B]): SearchResult = binarySearch(elem, 0, length)(ord) diff --git a/src/library/scala/collection/Iterable.scala b/src/library/scala/collection/Iterable.scala index 89cbc9e48b91..213ae0f0b166 100644 --- a/src/library/scala/collection/Iterable.scala +++ b/src/library/scala/collection/Iterable.scala @@ -228,6 +228,88 @@ trait IterableOps[+A, +CC[_], +C] extends Any with IterableOnce[A] with Iterable /** A view over the elements of this collection. */ def view: View[A] = View.fromIteratorProvider(() => iterator) + /** Compares the size of this $coll to a test value. + * + * @param otherSize the test value that gets compared with the size. + * @return A value `x` where + * {{{ + * x < 0 if this.size < otherSize + * x == 0 if this.size == otherSize + * x > 0 if this.size > otherSize + * }}} + * The method as implemented here does not call `size` directly; its running time + * is `O(size min _size)` instead of `O(size)`. The method should be overwritten + * if computing `size` is cheap. + */ + def sizeCompare(otherSize: Int): Int = { + if (otherSize < 0) 1 + else { + val known = knownSize + if (known >= 0) Integer.compare(known, otherSize) + else { + var i = 0 + val it = iterator + while (it.hasNext) { + if (i == otherSize) return if (it.hasNext) 1 else 0 + it.next() + i += 1 + } + i - otherSize + } + } + } + + /** Returns a value class containing operations for comparing the size of this $coll to a test value. + * + * These operations are implemented in terms of [[sizeCompare(Int) `sizeCompare(Int)`]], and + * allow the following more readable usages: + * + * {{{ + * this.sizeIs < size // this.sizeCompare(size) < 0 + * this.sizeIs <= size // this.sizeCompare(size) <= 0 + * this.sizeIs == size // this.sizeCompare(size) == 0 + * this.sizeIs != size // this.sizeCompare(size) != 0 + * this.sizeIs >= size // this.sizeCompare(size) >= 0 + * this.sizeIs > size // this.sizeCompare(size) > 0 + * }}} + */ + @inline final def sizeIs: IterableOps.SizeCompareOps = new IterableOps.SizeCompareOps(this) + + /** Compares the size of this $coll to the size of another `Iterable`. + * + * @param that the `Iterable` whose size is compared with this $coll's size. + * {{{ + * x < 0 if this.size < that.size + * x == 0 if this.size == that.size + * x > 0 if this.size > that.size + * }}} + * The method as implemented here does not call `size` directly; its running time + * is `O(this.size min that.size)` instead of `O(this.size + that.size)`. + * The method should be overwritten if computing `size` is cheap. + */ + def sizeCompare(that: Iterable[_]): Int = { + val thatKnownSize = that.knownSize + + if (thatKnownSize >= 0) this sizeCompare thatKnownSize + else { + val thisKnownSize = this.knownSize + + if (thisKnownSize >= 0) { + val res = that sizeCompare thisKnownSize + // can't just invert the result, because `-Int.MinValue == Int.MinValue` + if (res == Int.MinValue) 1 else -res + } else { + val thisIt = this.iterator + val thatIt = that.iterator + while (thisIt.hasNext && thatIt.hasNext) { + thisIt.next() + thatIt.next() + } + java.lang.Boolean.compare(thisIt.hasNext, thatIt.hasNext) + } + } + } + /** A view over a slice of the elements of this collection. */ @deprecated("Use .view.slice(from, until) instead of .view(from, until)", "2.13.0") @`inline` final def view(from: Int, until: Int): View[A] = view.slice(from, until) @@ -690,6 +772,26 @@ trait IterableOps[+A, +CC[_], +C] extends Any with IterableOnce[A] with Iterable object IterableOps { + /** Operations for comparing the size of a collection to a test value. + * + * These operations are implemented in terms of + * [[scala.collection.IterableOps.sizeCompare(Int) `sizeCompare(Int)`]]. + */ + final class SizeCompareOps private[collection](val it: IterableOps[_, AnyConstr, _]) extends AnyVal { + /** Tests if the size of the collection is less than some value. */ + @inline def <(size: Int): Boolean = it.sizeCompare(size) < 0 + /** Tests if the size of the collection is less than or equal to some value. */ + @inline def <=(size: Int): Boolean = it.sizeCompare(size) <= 0 + /** Tests if the size of the collection is equal to some value. */ + @inline def ==(size: Int): Boolean = it.sizeCompare(size) == 0 + /** Tests if the size of the collection is not equal to some value. */ + @inline def !=(size: Int): Boolean = it.sizeCompare(size) != 0 + /** Tests if the size of the collection is greater than or equal to some value. */ + @inline def >=(size: Int): Boolean = it.sizeCompare(size) >= 0 + /** Tests if the size of the collection is greater than some value. */ + @inline def >(size: Int): Boolean = it.sizeCompare(size) > 0 + } + /** A trait that contains just the `map`, `flatMap`, `foreach` and `withFilter` methods * of trait `Iterable`. * diff --git a/src/library/scala/collection/Seq.scala b/src/library/scala/collection/Seq.scala index 27b45acff67b..e56454a4a041 100644 --- a/src/library/scala/collection/Seq.scala +++ b/src/library/scala/collection/Seq.scala @@ -661,6 +661,8 @@ trait SeqOps[+A, +CC[_], +C] extends Any */ def indices: Range = Range(0, length) + override final def sizeCompare(_size: Int): Int = lengthCompare(_size) + /** Compares the length of this $coll to a test value. * * @param len the test value that gets compared with the length. @@ -674,23 +676,7 @@ trait SeqOps[+A, +CC[_], +C] extends Any * is `O(length min len)` instead of `O(length)`. The method should be overwritten * if computing `length` is cheap. */ - def lengthCompare(len: Int): Int = { - if (len < 0) 1 - else { - val known = knownSize - if (known >= 0) Integer.compare(known, len) - else { - var i = 0 - val it = iterator - while (it.hasNext) { - if (i == len) return if (it.hasNext) 1 else 0 - it.next() - i += 1 - } - i - len - } - } - } + def lengthCompare(len: Int): Int = super.sizeCompare(len) /** Returns a value class containing operations for comparing the length of this $coll to a test value. * @@ -706,7 +692,7 @@ trait SeqOps[+A, +CC[_], +C] extends Any * this.lengthIs > len // this.lengthCompare(len) > 0 * }}} */ - @inline final def lengthIs: SeqOps.LengthCompareOps = new SeqOps.LengthCompareOps(this) + @inline final def lengthIs: IterableOps.SizeCompareOps = new IterableOps.SizeCompareOps(this) override def isEmpty: Boolean = lengthCompare(0) == 0 diff --git a/test/benchmarks/src/main/scala/scala/collection/LengthCompareOpsBenchmark.scala b/test/benchmarks/src/main/scala/scala/collection/SizeCompareOpsBenchmark.scala similarity index 72% rename from test/benchmarks/src/main/scala/scala/collection/LengthCompareOpsBenchmark.scala rename to test/benchmarks/src/main/scala/scala/collection/SizeCompareOpsBenchmark.scala index 8d6c3435d83a..8736e3728402 100644 --- a/test/benchmarks/src/main/scala/scala/collection/LengthCompareOpsBenchmark.scala +++ b/test/benchmarks/src/main/scala/scala/collection/SizeCompareOpsBenchmark.scala @@ -13,12 +13,12 @@ import scala.util.Random @Measurement(iterations = 10) @OutputTimeUnit(TimeUnit.NANOSECONDS) @State(Scope.Benchmark) -class LengthCompareOpsBenchmark { +class SizeCompareOpsBenchmark { @Param(Array("0", "1", "10", "100", "1000")) var size: Int = _ @Param(Array("1", "100", "10000")) - var len: Int = _ + var cmpTo: Int = _ var values: List[Int] = _ @@ -27,11 +27,11 @@ class LengthCompareOpsBenchmark { values = List.fill(size)(Random.nextInt()) } - @Benchmark def lengthCompareUgly: Any = { - values.lengthCompare(len) == 0 + @Benchmark def sizeCompareUgly: Any = { + values.sizeCompare(cmpTo) == 0 } - @Benchmark def lengthComparePretty: Any = { - values.lengthIs == len + @Benchmark def sizeComparePretty: Any = { + values.sizeIs == cmpTo } } \ No newline at end of file diff --git a/test/junit/scala/collection/IterableTest.scala b/test/junit/scala/collection/IterableTest.scala index bc540f8821dc..5b2a154fa722 100644 --- a/test/junit/scala/collection/IterableTest.scala +++ b/test/junit/scala/collection/IterableTest.scala @@ -3,7 +3,9 @@ package scala.collection import org.junit.{Assert, Test} import org.junit.runner.RunWith import org.junit.runners.JUnit4 -import scala.collection.immutable.{ArraySeq, List, Range} + +import scala.collection.immutable.{ArraySeq, List, Range, Vector} +import scala.language.higherKinds import scala.tools.testing.AssertUtil._ @RunWith(classOf[JUnit4]) @@ -58,6 +60,34 @@ class IterableTest { Assert.assertEquals(expected, occurrences(xs)) } + @Test + def sizeCompareInt(): Unit = { + val seq = Seq(1, 2, 3) + assert(seq.sizeCompare(2) > 0) + assert(seq.sizeCompare(3) == 0) + assert(seq.sizeCompare(4) < 0) + } + + @Test + def sizeCompareIterable(): Unit = { + def check[I1[X] <: Iterable[X], I2[X] <: Iterable[X]] + (f1: IterableFactory[I1], f2: IterableFactory[I2]): Unit = { + val it = f1(1, 2, 3) + assert(it.sizeCompare(f2(1, 2)) > 0) + assert(it.sizeCompare(f2(1, 2, 3)) == 0) + assert(it.sizeCompare(f2(1, 2, 3, 4)) < 0) + } + + // factories for `Seq`s with known and unknown size + val known: IterableFactory[IndexedSeq] = Vector + val unknown: IterableFactory[LinearSeq] = List + + check(known, known) + check(known, unknown) + check(unknown, known) + check(unknown, unknown) + } + @Test def copyToArray(): Unit = { def check(a: Array[Int], start: Int, end: Int) = { var i = 0 From ed8a6e36916b10575e30c8befa9f1437f9e815b4 Mon Sep 17 00:00:00 2001 From: Isaac Levy Date: Mon, 23 Jul 2018 22:49:27 -0400 Subject: [PATCH 075/143] Move StringBuilder to its own file --- .../scala/collection/mutable/Builder.scala | 457 ----------------- .../collection/mutable/StringBuilder.scala | 458 ++++++++++++++++++ 2 files changed, 458 insertions(+), 457 deletions(-) create mode 100644 src/library/scala/collection/mutable/StringBuilder.scala diff --git a/src/library/scala/collection/mutable/Builder.scala b/src/library/scala/collection/mutable/Builder.scala index 77022c528d07..403324dd55bd 100644 --- a/src/library/scala/collection/mutable/Builder.scala +++ b/src/library/scala/collection/mutable/Builder.scala @@ -1,19 +1,5 @@ package scala.collection.mutable -import java.lang.String - -import scala.collection.IterableOnce -import scala.collection.immutable.WrappedString - -import scala.Predef.{ // unimport char-related implicit conversions to avoid triggering them accidentally - genericArrayOps => _, - charArrayOps => _, - genericWrapArray => _, - wrapCharArray => _, - wrapString => _, - _ -} - /** Base trait for collection builders */ trait Builder[-A, +To] extends Growable[A] { self => @@ -79,446 +65,3 @@ trait Builder[-A, +To] extends Growable[A] { self => } } - -/** A builder for mutable sequence of characters. This class provides an API - * mostly compatible with `java.lang.StringBuilder`, except where there are - * conflicts with the Scala collections API (such as the `reverse` method.) - * - * @author Stephane Micheloud - * @author Martin Odersky - * @since 2.7 - * @define Coll `mutable.IndexedSeq` - * @define coll string builder - * @see [[http://docs.scala-lang.org/overviews/collections/concrete-mutable-collection-classes.html#stringbuilders "Scala's Collection Library overview"]] - * section on `StringBuilders` for more information. - */ -@SerialVersionUID(3L) -final class StringBuilder(val underlying: java.lang.StringBuilder) extends AbstractSeq[Char] - with Builder[Char, String] - with IndexedSeq[Char] - with IndexedSeqOps[Char, IndexedSeq, StringBuilder] - with java.lang.CharSequence { - - def this() = this(new java.lang.StringBuilder) - - /** Constructs a string builder with no characters in it and an - * initial capacity specified by the `capacity` argument. - * - * @param capacity the initial capacity. - * @throws NegativeArraySizeException if capacity < 0. - */ - def this(capacity: Int) = this(new java.lang.StringBuilder(capacity)) - - /** Constructs a string builder with initial characters - * equal to characters of `str`. - */ - def this(str: String) = this(new java.lang.StringBuilder(str)) - - /** Constructs a string builder initialized with string value `initValue` - * and with additional character capacity `initCapacity`. - */ - def this(initCapacity: Int, initValue: String) = - this(new java.lang.StringBuilder(initValue.length + initCapacity) append initValue) - - // Methods required to make this an IndexedSeq: - def apply(i: Int): Char = underlying.charAt(i) - - override protected def fromSpecificIterable(coll: scala.collection.Iterable[Char]): StringBuilder = - new StringBuilder() appendAll coll - - override protected def newSpecificBuilder: Builder[Char, StringBuilder] = - new GrowableBuilder(new StringBuilder()) - - @inline def length: Int = underlying.length - - def length_=(n: Int): Unit = underlying.setLength(n) - - def addOne(x: Char) = { underlying.append(x); this } - - def clear() = underlying.setLength(0) - - /** Overloaded version of `addAll` that takes a string */ - def addAll(s: String): this.type = { underlying.append(s); this } - - /** Alias for `addAll` */ - def ++= (s: String): this.type = addAll(s) - - def result() = underlying.toString - - override def toString = result() - - override def toArray[B >: Char](implicit ct: scala.reflect.ClassTag[B]) = - ct.runtimeClass match { - case java.lang.Character.TYPE => toCharArray.asInstanceOf[Array[B]] - case _ => super.toArray - } - - /** Returns the contents of this StringBuilder as an `Array[Char]`. - * - * @return An array with the characters from this builder. - */ - def toCharArray: Array[Char] = { - val len = underlying.length - val arr = new Array[Char](len) - underlying.getChars(0, len, arr, 0) - arr - } - // append* methods delegate to the underlying java.lang.StringBuilder: - - def appendAll(xs: String): StringBuilder = { - underlying append xs - this - } - - /** Appends the string representation of the given argument, - * which is converted to a String with `String.valueOf`. - * - * @param x an `Any` object. - * @return this StringBuilder. - */ - def append(x: Any): StringBuilder = { - underlying append String.valueOf(x) - this - } - - /** Appends the given String to this sequence. - * - * @param s a String. - * @return this StringBuilder. - */ - def append(s: String): StringBuilder = { - underlying append s - this - } - - /** Appends the given CharSequence to this sequence. - * - * @param cs a CharSequence. - * @return this StringBuilder. - */ - def append(cs: java.lang.CharSequence): StringBuilder = { - underlying.append(cs match { - // Both cases call into append(), but java SB - // looks up type at runtime and has fast path for SB. - case s: StringBuilder => s.underlying - case _ => cs - }) - this - } - - /** Appends the specified string builder to this sequence. - * - * @param s - * @return - */ - def append(s: StringBuilder): StringBuilder = { - underlying append s.underlying - this - } - - /** Appends all the Chars in the given IterableOnce[Char] to this sequence. - * - * @param xs the characters to be appended. - * @return this StringBuilder. - */ - def appendAll(xs: IterableOnce[Char]): StringBuilder = { - val ks = xs.knownSize - val b = underlying - if (ks != 0) xs match { - case x: WrappedString => b append x.self - case x: ArraySeq.ofChar => b append x.array - case x: StringBuilder => b append x.underlying - case _ => - if (ks > 0) b.ensureCapacity(b.length + ks) - val it = xs.iterator - while (it.hasNext) { b append it.next() } - } - this - } - - /** Appends all the Chars in the given Array[Char] to this sequence. - * - * @param xs the characters to be appended. - * @return a reference to this object. - */ - def appendAll(xs: Array[Char]): StringBuilder = { - underlying append xs - this - } - - /** Appends a portion of the given Array[Char] to this sequence. - * - * @param xs the Array containing Chars to be appended. - * @param offset the index of the first Char to append. - * @param len the numbers of Chars to append. - * @return this StringBuilder. - */ - def appendAll(xs: Array[Char], offset: Int, len: Int): StringBuilder = { - underlying.append(xs, offset, len) - this - } - - /** Append the String representation of the given primitive type - * to this sequence. The argument is converted to a String with - * String.valueOf. - * - * @param x a primitive value - * @return This StringBuilder. - */ - def append(x: Boolean): StringBuilder = { underlying append x ; this } - def append(x: Byte): StringBuilder = append(x.toInt) - def append(x: Short): StringBuilder = append(x.toInt) - def append(x: Int): StringBuilder = { underlying append x ; this } - def append(x: Long): StringBuilder = { underlying append x ; this } - def append(x: Float): StringBuilder = { underlying append x ; this } - def append(x: Double): StringBuilder = { underlying append x ; this } - def append(x: Char): StringBuilder = { underlying append x ; this } - - /** Remove a subsequence of Chars from this sequence, starting at the - * given start index (inclusive) and extending to the end index (exclusive) - * or to the end of the String, whichever comes first. - * - * @param start The beginning index, inclusive. - * @param end The ending index, exclusive. - * @return This StringBuilder. - * @throws StringIndexOutOfBoundsException if start < 0 || start > end - */ - def delete(start: Int, end: Int): StringBuilder = { - underlying.delete(start, end) - this - } - - /** Replaces a subsequence of Chars with the given String. The semantics - * are as in delete, with the String argument then inserted at index 'start'. - * - * @param start The beginning index, inclusive. - * @param end The ending index, exclusive. - * @param str The String to be inserted at the start index. - * @return This StringBuilder. - * @throws StringIndexOutOfBoundsException if start < 0, start > length, or start > end - */ - def replace(start: Int, end: Int, str: String): StringBuilder = { - underlying.replace(start, end, str) - this - } - - /** Inserts a subarray of the given Array[Char] at the given index - * of this sequence. - * - * @param index index at which to insert the subarray. - * @param str the Array from which Chars will be taken. - * @param offset the index of the first Char to insert. - * @param len the number of Chars from 'str' to insert. - * @return This StringBuilder. - * - * @throws StringIndexOutOfBoundsException if index < 0, index > length, - * offset < 0, len < 0, or (offset + len) > str.length. - */ - def insertAll(index: Int, str: Array[Char], offset: Int, len: Int): StringBuilder = { - underlying.insert(index, str, offset, len) - this - } - - /** Inserts the String representation (via String.valueOf) of the given - * argument into this sequence at the given index. - * - * @param index the index at which to insert. - * @param x a value. - * @return this StringBuilder. - * @throws StringIndexOutOfBoundsException if the index is out of bounds. - */ - def insert(index: Int, x: Any): StringBuilder = insert(index, String.valueOf(x)) - - /** Inserts the String into this character sequence. - * - * @param index the index at which to insert. - * @param x a String. - * @return this StringBuilder. - * @throws StringIndexOutOfBoundsException if the index is out of bounds. - */ - def insert(index: Int, x: String): StringBuilder = { - underlying.insert(index, x) - this - } - - /** Inserts the given Seq[Char] into this sequence at the given index. - * - * @param index the index at which to insert. - * @param xs the Seq[Char]. - * @return this StringBuilder. - * @throws StringIndexOutOfBoundsException if the index is out of bounds. - */ - def insertAll(index: Int, xs: IterableOnce[Char]): StringBuilder = - insertAll(index, (ArrayBuilder.make[Char] ++= xs).result()) - - /** Inserts the given Array[Char] into this sequence at the given index. - * - * @param index the index at which to insert. - * @param xs the Array[Char]. - * @return this StringBuilder. - * @throws StringIndexOutOfBoundsException if the index is out of bounds. - */ - def insertAll(index: Int, xs: Array[Char]): StringBuilder = { - underlying.insert(index, xs) - this - } - - /** Calls String.valueOf on the given primitive value, and inserts the - * String at the given index. - * - * @param index the offset position. - * @param x a primitive value. - * @return this StringBuilder. - */ - def insert(index: Int, x: Boolean): StringBuilder = insert(index, String.valueOf(x)) - def insert(index: Int, x: Byte): StringBuilder = insert(index, x.toInt) - def insert(index: Int, x: Short): StringBuilder = insert(index, x.toInt) - def insert(index: Int, x: Int): StringBuilder = insert(index, String.valueOf(x)) - def insert(index: Int, x: Long): StringBuilder = insert(index, String.valueOf(x)) - def insert(index: Int, x: Float): StringBuilder = insert(index, String.valueOf(x)) - def insert(index: Int, x: Double): StringBuilder = insert(index, String.valueOf(x)) - def insert(index: Int, x: Char): StringBuilder = insert(index, String.valueOf(x)) - - /** Sets the length of the character sequence. If the current sequence - * is shorter than the given length, it is padded with nulls; if it is - * longer, it is truncated. - * - * @param len the new length - * @throws IndexOutOfBoundsException if the argument is negative. - */ - def setLength(len: Int): Unit = underlying.setLength(len) - - def update(idx: Int, elem: Char): Unit = underlying.setCharAt(idx, elem) - - - /** Like reverse, but destructively updates the target StringBuilder. - * - * @return the reversed StringBuilder (same as the target StringBuilder) - */ - @deprecated("Use reverseInPlace instead", "2.13.0") - final def reverseContents(): this.type = reverseInPlace() - - /** Like reverse, but destructively updates the target StringBuilder. - * - * @return the reversed StringBuilder (same as the target StringBuilder) - */ - def reverseInPlace(): this.type = { - underlying.reverse() - this - } - - - /** Returns the current capacity, which is the size of the underlying array. - * A new array will be allocated if the current capacity is exceeded. - * - * @return the capacity - */ - def capacity: Int = underlying.capacity() - - /** Ensure that the capacity is at least the given argument. - * If the argument is greater than the current capacity, new - * storage will be allocated with size equal to the given - * argument or to `(2 * capacity + 2)`, whichever is larger. - * - * @param newCapacity the minimum desired capacity. - */ - def ensureCapacity(newCapacity: Int): Unit = { underlying.ensureCapacity(newCapacity) } - - /** Returns the Char at the specified index, counting from 0 as in Arrays. - * - * @param index the index to look up - * @return the Char at the given index. - * @throws IndexOutOfBoundsException if the index is out of bounds. - */ - def charAt(index: Int): Char = underlying.charAt(index) - - /** Removes the Char at the specified index. The sequence is - * shortened by one. - * - * @param index The index to remove. - * @return This StringBuilder. - * @throws IndexOutOfBoundsException if the index is out of bounds. - */ - def deleteCharAt(index: Int): this.type = { - underlying.deleteCharAt(index) - this - } - - /** Update the sequence at the given index to hold the specified Char. - * - * @param index the index to modify. - * @param ch the new Char. - * @throws IndexOutOfBoundsException if the index is out of bounds. - */ - def setCharAt(index: Int, ch: Char): this.type = { - underlying.setCharAt(index, ch) - this - } - - /** Returns a new String made up of a subsequence of this sequence, - * beginning at the given index and extending to the end of the sequence. - * - * target.substring(start) is equivalent to target.drop(start) - * - * @param start The starting index, inclusive. - * @return The new String. - * @throws IndexOutOfBoundsException if the index is out of bounds. - */ - def substring(start: Int): String = underlying.substring(start, length) - - /** Returns a new String made up of a subsequence of this sequence, - * beginning at the start index (inclusive) and extending to the - * end index (exclusive). - * - * target.substring(start, end) is equivalent to target.slice(start, end).mkString - * - * @param start The beginning index, inclusive. - * @param end The ending index, exclusive. - * @return The new String. - * @throws StringIndexOutOfBoundsException If either index is out of bounds, - * or if start > end. - */ - def substring(start: Int, end: Int): String = underlying.substring(start, end) - - /** For implementing CharSequence. - */ - def subSequence(start: Int, end: Int): java.lang.CharSequence = - underlying.substring(start, end) - - /** Finds the index of the first occurrence of the specified substring. - * - * @param str the target string to search for - * @return the first applicable index where target occurs, or -1 if not found. - */ - def indexOf(str: String): Int = underlying.indexOf(str) - - /** Finds the index of the first occurrence of the specified substring. - * - * @param str the target string to search for - * @param fromIndex the smallest index in the source string to consider - * @return the first applicable index where target occurs, or -1 if not found. - */ - def indexOf(str: String, fromIndex: Int): Int = underlying.indexOf(str, fromIndex) - - /** Finds the index of the last occurrence of the specified substring. - * - * @param str the target string to search for - * @return the last applicable index where target occurs, or -1 if not found. - */ - def lastIndexOf(str: String): Int = underlying.lastIndexOf(str) - - /** Finds the index of the last occurrence of the specified substring. - * - * @param str the target string to search for - * @param fromIndex the smallest index in the source string to consider - * @return the last applicable index where target occurs, or -1 if not found. - */ - def lastIndexOf(str: String, fromIndex: Int): Int = underlying.lastIndexOf(str, fromIndex) - - override protected[this] def writeReplace(): AnyRef = this -} - -object StringBuilder { - @deprecated("Use `new StringBuilder()` instead of `StringBuilder.newBuilder`", "2.13.0") - def newBuilder = new StringBuilder -} diff --git a/src/library/scala/collection/mutable/StringBuilder.scala b/src/library/scala/collection/mutable/StringBuilder.scala new file mode 100644 index 000000000000..35baba856911 --- /dev/null +++ b/src/library/scala/collection/mutable/StringBuilder.scala @@ -0,0 +1,458 @@ +package scala.collection.mutable + +import java.lang.String + +import scala.collection.IterableOnce +import scala.collection.immutable.WrappedString + +import scala.Predef.{ // unimport char-related implicit conversions to avoid triggering them accidentally + genericArrayOps => _, + charArrayOps => _, + genericWrapArray => _, + wrapCharArray => _, + wrapString => _, + _ +} + +/** A builder for mutable sequence of characters. This class provides an API + * mostly compatible with `java.lang.StringBuilder`, except where there are + * conflicts with the Scala collections API (such as the `reverse` method.) + * + * @author Stephane Micheloud + * @author Martin Odersky + * @since 2.7 + * @define Coll `mutable.IndexedSeq` + * @define coll string builder + * @see [[http://docs.scala-lang.org/overviews/collections/concrete-mutable-collection-classes.html#stringbuilders "Scala's Collection Library overview"]] + * section on `StringBuilders` for more information. + */ +@SerialVersionUID(3L) +final class StringBuilder(val underlying: java.lang.StringBuilder) extends AbstractSeq[Char] + with Builder[Char, String] + with IndexedSeq[Char] + with IndexedSeqOps[Char, IndexedSeq, StringBuilder] + with java.lang.CharSequence { + + def this() = this(new java.lang.StringBuilder) + + /** Constructs a string builder with no characters in it and an + * initial capacity specified by the `capacity` argument. + * + * @param capacity the initial capacity. + * @throws NegativeArraySizeException if capacity < 0. + */ + def this(capacity: Int) = this(new java.lang.StringBuilder(capacity)) + + /** Constructs a string builder with initial characters + * equal to characters of `str`. + */ + def this(str: String) = this(new java.lang.StringBuilder(str)) + + /** Constructs a string builder initialized with string value `initValue` + * and with additional character capacity `initCapacity`. + */ + def this(initCapacity: Int, initValue: String) = + this(new java.lang.StringBuilder(initValue.length + initCapacity) append initValue) + + // Methods required to make this an IndexedSeq: + def apply(i: Int): Char = underlying.charAt(i) + + override protected def fromSpecificIterable(coll: scala.collection.Iterable[Char]): StringBuilder = + new StringBuilder() appendAll coll + + override protected def newSpecificBuilder: Builder[Char, StringBuilder] = + new GrowableBuilder(new StringBuilder()) + + @inline def length: Int = underlying.length + + def length_=(n: Int): Unit = underlying.setLength(n) + + def addOne(x: Char) = { underlying.append(x); this } + + def clear() = underlying.setLength(0) + + /** Overloaded version of `addAll` that takes a string */ + def addAll(s: String): this.type = { underlying.append(s); this } + + /** Alias for `addAll` */ + def ++= (s: String): this.type = addAll(s) + + def result() = underlying.toString + + override def toString = result() + + override def toArray[B >: Char](implicit ct: scala.reflect.ClassTag[B]) = + ct.runtimeClass match { + case java.lang.Character.TYPE => toCharArray.asInstanceOf[Array[B]] + case _ => super.toArray + } + + /** Returns the contents of this StringBuilder as an `Array[Char]`. + * + * @return An array with the characters from this builder. + */ + def toCharArray: Array[Char] = { + val len = underlying.length + val arr = new Array[Char](len) + underlying.getChars(0, len, arr, 0) + arr + } + // append* methods delegate to the underlying java.lang.StringBuilder: + + def appendAll(xs: String): StringBuilder = { + underlying append xs + this + } + + /** Appends the string representation of the given argument, + * which is converted to a String with `String.valueOf`. + * + * @param x an `Any` object. + * @return this StringBuilder. + */ + def append(x: Any): StringBuilder = { + underlying append String.valueOf(x) + this + } + + /** Appends the given String to this sequence. + * + * @param s a String. + * @return this StringBuilder. + */ + def append(s: String): StringBuilder = { + underlying append s + this + } + + /** Appends the given CharSequence to this sequence. + * + * @param cs a CharSequence. + * @return this StringBuilder. + */ + def append(cs: java.lang.CharSequence): StringBuilder = { + underlying.append(cs match { + // Both cases call into append(), but java SB + // looks up type at runtime and has fast path for SB. + case s: StringBuilder => s.underlying + case _ => cs + }) + this + } + + /** Appends the specified string builder to this sequence. + * + * @param s + * @return + */ + def append(s: StringBuilder): StringBuilder = { + underlying append s.underlying + this + } + + /** Appends all the Chars in the given IterableOnce[Char] to this sequence. + * + * @param xs the characters to be appended. + * @return this StringBuilder. + */ + def appendAll(xs: IterableOnce[Char]): StringBuilder = { + val ks = xs.knownSize + val b = underlying + if (ks != 0) xs match { + case x: WrappedString => b append x.self + case x: ArraySeq.ofChar => b append x.array + case x: StringBuilder => b append x.underlying + case _ => + if (ks > 0) b.ensureCapacity(b.length + ks) + val it = xs.iterator + while (it.hasNext) { b append it.next() } + } + this + } + + /** Appends all the Chars in the given Array[Char] to this sequence. + * + * @param xs the characters to be appended. + * @return a reference to this object. + */ + def appendAll(xs: Array[Char]): StringBuilder = { + underlying append xs + this + } + + /** Appends a portion of the given Array[Char] to this sequence. + * + * @param xs the Array containing Chars to be appended. + * @param offset the index of the first Char to append. + * @param len the numbers of Chars to append. + * @return this StringBuilder. + */ + def appendAll(xs: Array[Char], offset: Int, len: Int): StringBuilder = { + underlying.append(xs, offset, len) + this + } + + /** Append the String representation of the given primitive type + * to this sequence. The argument is converted to a String with + * String.valueOf. + * + * @param x a primitive value + * @return This StringBuilder. + */ + def append(x: Boolean): StringBuilder = { underlying append x ; this } + def append(x: Byte): StringBuilder = append(x.toInt) + def append(x: Short): StringBuilder = append(x.toInt) + def append(x: Int): StringBuilder = { underlying append x ; this } + def append(x: Long): StringBuilder = { underlying append x ; this } + def append(x: Float): StringBuilder = { underlying append x ; this } + def append(x: Double): StringBuilder = { underlying append x ; this } + def append(x: Char): StringBuilder = { underlying append x ; this } + + /** Remove a subsequence of Chars from this sequence, starting at the + * given start index (inclusive) and extending to the end index (exclusive) + * or to the end of the String, whichever comes first. + * + * @param start The beginning index, inclusive. + * @param end The ending index, exclusive. + * @return This StringBuilder. + * @throws StringIndexOutOfBoundsException if start < 0 || start > end + */ + def delete(start: Int, end: Int): StringBuilder = { + underlying.delete(start, end) + this + } + + /** Replaces a subsequence of Chars with the given String. The semantics + * are as in delete, with the String argument then inserted at index 'start'. + * + * @param start The beginning index, inclusive. + * @param end The ending index, exclusive. + * @param str The String to be inserted at the start index. + * @return This StringBuilder. + * @throws StringIndexOutOfBoundsException if start < 0, start > length, or start > end + */ + def replace(start: Int, end: Int, str: String): StringBuilder = { + underlying.replace(start, end, str) + this + } + + /** Inserts a subarray of the given Array[Char] at the given index + * of this sequence. + * + * @param index index at which to insert the subarray. + * @param str the Array from which Chars will be taken. + * @param offset the index of the first Char to insert. + * @param len the number of Chars from 'str' to insert. + * @return This StringBuilder. + * + * @throws StringIndexOutOfBoundsException if index < 0, index > length, + * offset < 0, len < 0, or (offset + len) > str.length. + */ + def insertAll(index: Int, str: Array[Char], offset: Int, len: Int): StringBuilder = { + underlying.insert(index, str, offset, len) + this + } + + /** Inserts the String representation (via String.valueOf) of the given + * argument into this sequence at the given index. + * + * @param index the index at which to insert. + * @param x a value. + * @return this StringBuilder. + * @throws StringIndexOutOfBoundsException if the index is out of bounds. + */ + def insert(index: Int, x: Any): StringBuilder = insert(index, String.valueOf(x)) + + /** Inserts the String into this character sequence. + * + * @param index the index at which to insert. + * @param x a String. + * @return this StringBuilder. + * @throws StringIndexOutOfBoundsException if the index is out of bounds. + */ + def insert(index: Int, x: String): StringBuilder = { + underlying.insert(index, x) + this + } + + /** Inserts the given Seq[Char] into this sequence at the given index. + * + * @param index the index at which to insert. + * @param xs the Seq[Char]. + * @return this StringBuilder. + * @throws StringIndexOutOfBoundsException if the index is out of bounds. + */ + def insertAll(index: Int, xs: IterableOnce[Char]): StringBuilder = + insertAll(index, (ArrayBuilder.make[Char] ++= xs).result()) + + /** Inserts the given Array[Char] into this sequence at the given index. + * + * @param index the index at which to insert. + * @param xs the Array[Char]. + * @return this StringBuilder. + * @throws StringIndexOutOfBoundsException if the index is out of bounds. + */ + def insertAll(index: Int, xs: Array[Char]): StringBuilder = { + underlying.insert(index, xs) + this + } + + /** Calls String.valueOf on the given primitive value, and inserts the + * String at the given index. + * + * @param index the offset position. + * @param x a primitive value. + * @return this StringBuilder. + */ + def insert(index: Int, x: Boolean): StringBuilder = insert(index, String.valueOf(x)) + def insert(index: Int, x: Byte): StringBuilder = insert(index, x.toInt) + def insert(index: Int, x: Short): StringBuilder = insert(index, x.toInt) + def insert(index: Int, x: Int): StringBuilder = insert(index, String.valueOf(x)) + def insert(index: Int, x: Long): StringBuilder = insert(index, String.valueOf(x)) + def insert(index: Int, x: Float): StringBuilder = insert(index, String.valueOf(x)) + def insert(index: Int, x: Double): StringBuilder = insert(index, String.valueOf(x)) + def insert(index: Int, x: Char): StringBuilder = insert(index, String.valueOf(x)) + + /** Sets the length of the character sequence. If the current sequence + * is shorter than the given length, it is padded with nulls; if it is + * longer, it is truncated. + * + * @param len the new length + * @throws IndexOutOfBoundsException if the argument is negative. + */ + def setLength(len: Int): Unit = underlying.setLength(len) + + def update(idx: Int, elem: Char): Unit = underlying.setCharAt(idx, elem) + + + /** Like reverse, but destructively updates the target StringBuilder. + * + * @return the reversed StringBuilder (same as the target StringBuilder) + */ + @deprecated("Use reverseInPlace instead", "2.13.0") + final def reverseContents(): this.type = reverseInPlace() + + /** Like reverse, but destructively updates the target StringBuilder. + * + * @return the reversed StringBuilder (same as the target StringBuilder) + */ + def reverseInPlace(): this.type = { + underlying.reverse() + this + } + + + /** Returns the current capacity, which is the size of the underlying array. + * A new array will be allocated if the current capacity is exceeded. + * + * @return the capacity + */ + def capacity: Int = underlying.capacity() + + /** Ensure that the capacity is at least the given argument. + * If the argument is greater than the current capacity, new + * storage will be allocated with size equal to the given + * argument or to `(2 * capacity + 2)`, whichever is larger. + * + * @param newCapacity the minimum desired capacity. + */ + def ensureCapacity(newCapacity: Int): Unit = { underlying.ensureCapacity(newCapacity) } + + /** Returns the Char at the specified index, counting from 0 as in Arrays. + * + * @param index the index to look up + * @return the Char at the given index. + * @throws IndexOutOfBoundsException if the index is out of bounds. + */ + def charAt(index: Int): Char = underlying.charAt(index) + + /** Removes the Char at the specified index. The sequence is + * shortened by one. + * + * @param index The index to remove. + * @return This StringBuilder. + * @throws IndexOutOfBoundsException if the index is out of bounds. + */ + def deleteCharAt(index: Int): this.type = { + underlying.deleteCharAt(index) + this + } + + /** Update the sequence at the given index to hold the specified Char. + * + * @param index the index to modify. + * @param ch the new Char. + * @throws IndexOutOfBoundsException if the index is out of bounds. + */ + def setCharAt(index: Int, ch: Char): this.type = { + underlying.setCharAt(index, ch) + this + } + + /** Returns a new String made up of a subsequence of this sequence, + * beginning at the given index and extending to the end of the sequence. + * + * target.substring(start) is equivalent to target.drop(start) + * + * @param start The starting index, inclusive. + * @return The new String. + * @throws IndexOutOfBoundsException if the index is out of bounds. + */ + def substring(start: Int): String = underlying.substring(start, length) + + /** Returns a new String made up of a subsequence of this sequence, + * beginning at the start index (inclusive) and extending to the + * end index (exclusive). + * + * target.substring(start, end) is equivalent to target.slice(start, end).mkString + * + * @param start The beginning index, inclusive. + * @param end The ending index, exclusive. + * @return The new String. + * @throws StringIndexOutOfBoundsException If either index is out of bounds, + * or if start > end. + */ + def substring(start: Int, end: Int): String = underlying.substring(start, end) + + /** For implementing CharSequence. + */ + def subSequence(start: Int, end: Int): java.lang.CharSequence = + underlying.substring(start, end) + + /** Finds the index of the first occurrence of the specified substring. + * + * @param str the target string to search for + * @return the first applicable index where target occurs, or -1 if not found. + */ + def indexOf(str: String): Int = underlying.indexOf(str) + + /** Finds the index of the first occurrence of the specified substring. + * + * @param str the target string to search for + * @param fromIndex the smallest index in the source string to consider + * @return the first applicable index where target occurs, or -1 if not found. + */ + def indexOf(str: String, fromIndex: Int): Int = underlying.indexOf(str, fromIndex) + + /** Finds the index of the last occurrence of the specified substring. + * + * @param str the target string to search for + * @return the last applicable index where target occurs, or -1 if not found. + */ + def lastIndexOf(str: String): Int = underlying.lastIndexOf(str) + + /** Finds the index of the last occurrence of the specified substring. + * + * @param str the target string to search for + * @param fromIndex the smallest index in the source string to consider + * @return the last applicable index where target occurs, or -1 if not found. + */ + def lastIndexOf(str: String, fromIndex: Int): Int = underlying.lastIndexOf(str, fromIndex) + + override protected[this] def writeReplace(): AnyRef = this +} + +object StringBuilder { + @deprecated("Use `new StringBuilder()` instead of `StringBuilder.newBuilder`", "2.13.0") + def newBuilder = new StringBuilder +} From c5eb6ed8a9c363544f4c6d55e56f0f45d480c6ad Mon Sep 17 00:00:00 2001 From: Isaac Levy Date: Tue, 24 Jul 2018 11:45:00 -0400 Subject: [PATCH 076/143] Minor cleanup of StringBuilder Adjust `appendAll()` to avoid knownSize check on wrapped arrays. --- .../collection/mutable/StringBuilder.scala | 27 ++++++++++--------- 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/src/library/scala/collection/mutable/StringBuilder.scala b/src/library/scala/collection/mutable/StringBuilder.scala index 35baba856911..299becd9d763 100644 --- a/src/library/scala/collection/mutable/StringBuilder.scala +++ b/src/library/scala/collection/mutable/StringBuilder.scala @@ -79,9 +79,9 @@ final class StringBuilder(val underlying: java.lang.StringBuilder) extends Abstr def result() = underlying.toString - override def toString = result() + override def toString = result - override def toArray[B >: Char](implicit ct: scala.reflect.ClassTag[B]) = + override def toArray[B >: Char](implicit ct: scala.reflect.ClassTag[B]) = ct.runtimeClass match { case java.lang.Character.TYPE => toCharArray.asInstanceOf[Array[B]] case _ => super.toArray @@ -97,6 +97,7 @@ final class StringBuilder(val underlying: java.lang.StringBuilder) extends Abstr underlying.getChars(0, len, arr, 0) arr } + // append* methods delegate to the underlying java.lang.StringBuilder: def appendAll(xs: String): StringBuilder = { @@ -156,16 +157,18 @@ final class StringBuilder(val underlying: java.lang.StringBuilder) extends Abstr * @return this StringBuilder. */ def appendAll(xs: IterableOnce[Char]): StringBuilder = { - val ks = xs.knownSize - val b = underlying - if (ks != 0) xs match { - case x: WrappedString => b append x.self - case x: ArraySeq.ofChar => b append x.array - case x: StringBuilder => b append x.underlying + xs match { + case x: WrappedString => underlying append x.self + case x: ArraySeq.ofChar => underlying append x.array + case x: StringBuilder => underlying append x.underlying case _ => - if (ks > 0) b.ensureCapacity(b.length + ks) - val it = xs.iterator - while (it.hasNext) { b append it.next() } + val ks = xs.knownSize + if (ks != 0) { + val b = underlying + if (ks > 0) b.ensureCapacity(b.length + ks) + val it = xs.iterator + while (it.hasNext) { b append it.next() } + } } this } @@ -347,7 +350,7 @@ final class StringBuilder(val underlying: java.lang.StringBuilder) extends Abstr * * @return the capacity */ - def capacity: Int = underlying.capacity() + def capacity: Int = underlying.capacity /** Ensure that the capacity is at least the given argument. * If the argument is greater than the current capacity, new From e37af440a4615c627a0c7fa9f4482e3cbf9f29ef Mon Sep 17 00:00:00 2001 From: Som Snytt Date: Mon, 23 Jul 2018 16:34:39 -0700 Subject: [PATCH 077/143] Enforce some linting People keep commiting unused imports, which are the easiest to check, so create some noise if they do that. --- build.sbt | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/build.sbt b/build.sbt index 1b9e729d34b7..b4389c356e84 100644 --- a/build.sbt +++ b/build.sbt @@ -158,7 +158,7 @@ lazy val commonSettings = instanceSettings ++ clearSourceAndResourceDirectories // END: Copy/pasted from SBT }, fork in run := true, - //scalacOptions += "-Xlint:-nullary-override,-inaccessible,_", + scalacOptions += "-Xlint:-nullary-override,-inaccessible,_", //scalacOptions ++= Seq("-Xmaxerrs", "5", "-Xmaxwarns", "5"), scalacOptions in Compile in doc ++= Seq( "-doc-footer", "epfl", @@ -577,6 +577,7 @@ lazy val junit = project.in(file("test") / "junit") .dependsOn(library, reflect, compiler, partest, scaladoc) .settings(clearSourceAndResourceDirectories) .settings(commonSettings) + .settings(scalacOptions += "-Xlint:-nullary-unit,-adapted-args") .settings(disableDocs) .settings(disablePublishing) .settings( @@ -684,6 +685,7 @@ lazy val test = project .disablePlugins(plugins.JUnitXmlReportPlugin) .configs(IntegrationTest) .settings(commonSettings) + .settings(scalacOptions -= "-Xlint:-nullary-override,-inaccessible,_") .settings(disableDocs) .settings(disablePublishing) .settings(Defaults.itSettings) From 34f91a23ccb8ae00422ace2d0247ec5edcc1ce84 Mon Sep 17 00:00:00 2001 From: Som Snytt Date: Mon, 23 Jul 2018 19:39:39 -0700 Subject: [PATCH 078/143] Some lintings --- .../scala/tools/nsc/backend/jvm/BCodeHelpers.scala | 3 +-- src/compiler/scala/tools/nsc/backend/jvm/BTypes.scala | 2 -- .../tools/nsc/backend/jvm/analysis/BackendUtils.scala | 2 +- .../scala/tools/nsc/backend/jvm/opt/BytecodeUtils.scala | 1 - src/compiler/scala/tools/nsc/typechecker/Contexts.scala | 7 +++---- src/library/scala/collection/mutable/Iterable.scala | 1 - src/library/scala/collection/mutable/Map.scala | 2 +- src/library/scala/collection/mutable/Set.scala | 2 +- test/junit/scala/PartialFunctionSerializationTest.scala | 1 - test/junit/scala/collection/BuildFromTest.scala | 2 +- test/junit/scala/collection/IndexedSeqTest.scala | 9 +++++---- test/junit/scala/collection/IterableViewLikeTest.scala | 1 - test/junit/scala/collection/SeqTests.scala | 4 ++-- 13 files changed, 15 insertions(+), 22 deletions(-) diff --git a/src/compiler/scala/tools/nsc/backend/jvm/BCodeHelpers.scala b/src/compiler/scala/tools/nsc/backend/jvm/BCodeHelpers.scala index a31cc12e2345..0b35b8978477 100644 --- a/src/compiler/scala/tools/nsc/backend/jvm/BCodeHelpers.scala +++ b/src/compiler/scala/tools/nsc/backend/jvm/BCodeHelpers.scala @@ -9,8 +9,7 @@ package backend.jvm import scala.tools.asm import BackendReporting._ -import scala.reflect.internal.Flags -import scala.tools.asm.{ByteVector, ClassWriter} +import scala.tools.asm.ClassWriter import scala.tools.nsc.backend.jvm.BCodeHelpers.ScalaSigBytes import scala.tools.nsc.reporters.NoReporter diff --git a/src/compiler/scala/tools/nsc/backend/jvm/BTypes.scala b/src/compiler/scala/tools/nsc/backend/jvm/BTypes.scala index 59a64a9b338c..564fed864ed4 100644 --- a/src/compiler/scala/tools/nsc/backend/jvm/BTypes.scala +++ b/src/compiler/scala/tools/nsc/backend/jvm/BTypes.scala @@ -6,8 +6,6 @@ package scala.tools.nsc package backend.jvm -import scala.collection.generic.Clearable -import scala.collection.concurrent import scala.tools.asm import scala.tools.asm.Opcodes import scala.tools.nsc.backend.jvm.BTypes.{InlineInfo, InternalName} diff --git a/src/compiler/scala/tools/nsc/backend/jvm/analysis/BackendUtils.scala b/src/compiler/scala/tools/nsc/backend/jvm/analysis/BackendUtils.scala index 0f684b1e3dfb..00309ade46b0 100644 --- a/src/compiler/scala/tools/nsc/backend/jvm/analysis/BackendUtils.scala +++ b/src/compiler/scala/tools/nsc/backend/jvm/analysis/BackendUtils.scala @@ -13,7 +13,7 @@ import scala.tools.asm import scala.tools.asm.Opcodes._ import scala.tools.asm.tree._ import scala.tools.asm.tree.analysis._ -import scala.tools.asm.{Handle, Label, Type} +import scala.tools.asm.{Handle, Type} import scala.tools.nsc.backend.jvm.BTypes._ import scala.tools.nsc.backend.jvm.GenBCode._ import scala.tools.nsc.backend.jvm.analysis.BackendUtils._ diff --git a/src/compiler/scala/tools/nsc/backend/jvm/opt/BytecodeUtils.scala b/src/compiler/scala/tools/nsc/backend/jvm/opt/BytecodeUtils.scala index c1e6b5775e3f..57846847d2ed 100644 --- a/src/compiler/scala/tools/nsc/backend/jvm/opt/BytecodeUtils.scala +++ b/src/compiler/scala/tools/nsc/backend/jvm/opt/BytecodeUtils.scala @@ -9,7 +9,6 @@ package opt import scala.annotation.{tailrec, switch} -import scala.PartialFunction.cond import scala.reflect.internal.util.Collections._ import scala.tools.asm.commons.CodeSizeEvaluator import scala.tools.asm.tree.analysis._ diff --git a/src/compiler/scala/tools/nsc/typechecker/Contexts.scala b/src/compiler/scala/tools/nsc/typechecker/Contexts.scala index 7ec4c54a7703..3833d7962b13 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Contexts.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Contexts.scala @@ -6,7 +6,7 @@ package scala.tools.nsc package typechecker -import scala.collection.{ immutable, mutable } +import scala.collection.{immutable, mutable} import scala.annotation.tailrec import scala.reflect.internal.util.shortClassOfInstance import scala.reflect.internal.Reporter @@ -17,7 +17,7 @@ import scala.reflect.internal.Reporter */ trait Contexts { self: Analyzer => import global._ - import definitions.{ AnyRefClass, JavaLangPackage, ScalaPackage, PredefModule, ScalaXmlTopScope, ScalaXmlPackage } + import definitions.{JavaLangPackage, ScalaPackage, PredefModule, ScalaXmlTopScope, ScalaXmlPackage} import ContextMode._ import scala.reflect.internal.Flags._ @@ -265,7 +265,7 @@ trait Contexts { self: Analyzer => val fresh = freshNameCreatorFor(this) val vname = newTermName(fresh.newName("rec$")) val vsym = owner.newValue(vname, newFlags = FINAL | SYNTHETIC) setInfo tpe - implicitDictionary +:= (tpe -> (vsym, EmptyTree)) + implicitDictionary +:= (tpe, (vsym, EmptyTree)) vsym } gen.mkAttributedRef(sym) setType tpe @@ -323,7 +323,6 @@ trait Contexts { self: Analyzer => (vsym, ValDef(Modifiers(FINAL | SYNTHETIC), vsym.name.toTermName, TypeTree(rhs.tpe), rhs.changeOwner(owner -> vsym))) }.unzip - val ctor = DefDef(NoMods, nme.CONSTRUCTOR, Nil, ListOfNil, TypeTree(), Block(List(pendingSuperCall), Literal(Constant(())))) val mname = newTermName(typer.fresh.newName("LazyDefns$")) val mdef = ModuleDef(Modifiers(SYNTHETIC), mname, diff --git a/src/library/scala/collection/mutable/Iterable.scala b/src/library/scala/collection/mutable/Iterable.scala index 427d88e39228..82f1b4c0bcf1 100644 --- a/src/library/scala/collection/mutable/Iterable.scala +++ b/src/library/scala/collection/mutable/Iterable.scala @@ -1,7 +1,6 @@ package scala.collection.mutable import scala.collection.IterableFactory -import scala.language.higherKinds trait Iterable[A] extends collection.Iterable[A] diff --git a/src/library/scala/collection/mutable/Map.scala b/src/library/scala/collection/mutable/Map.scala index b6d28c1e4b94..db1544cfed31 100644 --- a/src/library/scala/collection/mutable/Map.scala +++ b/src/library/scala/collection/mutable/Map.scala @@ -2,7 +2,7 @@ package scala package collection package mutable -import scala.collection.{IterableOnce, MapFactory} +import scala.collection.MapFactory import scala.language.higherKinds /** Base type of mutable Maps */ diff --git a/src/library/scala/collection/mutable/Set.scala b/src/library/scala/collection/mutable/Set.scala index fffa5c2e21a9..bf42703e0406 100644 --- a/src/library/scala/collection/mutable/Set.scala +++ b/src/library/scala/collection/mutable/Set.scala @@ -1,6 +1,6 @@ package scala.collection.mutable -import scala.collection.{IterableFactory, IterableOnce} +import scala.collection.IterableFactory import scala.language.higherKinds /** Base trait for mutable sets */ diff --git a/test/junit/scala/PartialFunctionSerializationTest.scala b/test/junit/scala/PartialFunctionSerializationTest.scala index 2019e3a4259c..6618012ad5de 100644 --- a/test/junit/scala/PartialFunctionSerializationTest.scala +++ b/test/junit/scala/PartialFunctionSerializationTest.scala @@ -1,7 +1,6 @@ package scala import org.junit.Test -import org.junit.Assert._ import org.junit.runner.RunWith import org.junit.runners.JUnit4 diff --git a/test/junit/scala/collection/BuildFromTest.scala b/test/junit/scala/collection/BuildFromTest.scala index 66a9492c692b..1a3bc60f0488 100644 --- a/test/junit/scala/collection/BuildFromTest.scala +++ b/test/junit/scala/collection/BuildFromTest.scala @@ -2,7 +2,7 @@ package scala.collection import org.junit.Test -import scala.collection.mutable.{ArrayBuffer, Builder, Growable} +import scala.collection.mutable.Builder import scala.math.Ordering class BuildFromTest { diff --git a/test/junit/scala/collection/IndexedSeqTest.scala b/test/junit/scala/collection/IndexedSeqTest.scala index 4f1927bf8f48..d69350688a89 100644 --- a/test/junit/scala/collection/IndexedSeqTest.scala +++ b/test/junit/scala/collection/IndexedSeqTest.scala @@ -172,6 +172,7 @@ abstract class IndexedTest[T, E] { @Test def checkTakeTooBig: Unit = { val orig = underTest(size) val e = take(orig, 0) + assertNotNull(e) for (len <- List(size + 1, size + 10, Int.MaxValue)) { val all = take(orig, len) assertEquals(s"len $len", size, length(all)) @@ -547,7 +548,7 @@ package IndexedTestImpl { override def createEmpty(size: Int): StringBuilder = new StringBuilder(size) override protected def underTest(size: Int): StringBuilder = { - var res = createEmpty(size) + val res = createEmpty(size) for (i <- 0 until size) res += expectedValueAtIndex(i) res @@ -556,7 +557,7 @@ package IndexedTestImpl { class StringOpsTest extends StringOpsBaseTest with CharTestData { override protected def underTest(size: Int): StringOps = { - var res = new StringBuilder(size) + val res = new StringBuilder(size) for (i <- 0 until size) res += expectedValueAtIndex(i) res.toString @@ -567,7 +568,7 @@ package IndexedTestImpl { override def isTakeAllSame: Boolean = false override protected def underTest(size: Int): WrappedString = { - var res = new StringBuilder(size) + val res = new StringBuilder(size) for (i <- 0 until size) res += expectedValueAtIndex(i) new WrappedString(res.toString) @@ -576,7 +577,7 @@ package IndexedTestImpl { class VectorTest extends ImmutableIndexedSeqTest[Vector[String], String] with StringTestData { override protected def underTest(size: Int): Vector[String] = { - var res = Vector.newBuilder[String] + val res = Vector.newBuilder[String] for (i <- 0 until size) res += expectedValueAtIndex(i) res.result() diff --git a/test/junit/scala/collection/IterableViewLikeTest.scala b/test/junit/scala/collection/IterableViewLikeTest.scala index 6784dfd28c53..df7754be6e49 100644 --- a/test/junit/scala/collection/IterableViewLikeTest.scala +++ b/test/junit/scala/collection/IterableViewLikeTest.scala @@ -4,7 +4,6 @@ import org.junit.Assert._ import org.junit.Test import org.junit.runner.RunWith import org.junit.runners.JUnit4 -import language.postfixOps @RunWith(classOf[JUnit4]) class IterableViewLikeTest { diff --git a/test/junit/scala/collection/SeqTests.scala b/test/junit/scala/collection/SeqTests.scala index b4f04ac34a7d..6c826620662f 100644 --- a/test/junit/scala/collection/SeqTests.scala +++ b/test/junit/scala/collection/SeqTests.scala @@ -1,6 +1,6 @@ package scala.collection.immutable -import org.junit.{Assert, Test} +import org.junit.Assert object SeqTests { def checkSearch[A](seq: Seq[A], needle: A, ord: Ordering[A]): Unit = { @@ -28,4 +28,4 @@ object SeqTests { } } } -} \ No newline at end of file +} From 3f35e94f6dab56f09036eb353bece6eb968feb35 Mon Sep 17 00:00:00 2001 From: xuwei-k <6b656e6a69@gmail.com> Date: Tue, 24 Jul 2018 22:58:27 +0900 Subject: [PATCH 079/143] fix indent --- src/compiler/scala/tools/nsc/typechecker/StdAttachments.scala | 2 +- src/library/scala/collection/Seq.scala | 2 +- src/library/scala/collection/mutable/StringBuilder.scala | 2 +- src/library/scala/concurrent/duration/Duration.scala | 2 +- src/library/scala/math/BigDecimal.scala | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/compiler/scala/tools/nsc/typechecker/StdAttachments.scala b/src/compiler/scala/tools/nsc/typechecker/StdAttachments.scala index 7bba269951ba..53d242673d50 100644 --- a/src/compiler/scala/tools/nsc/typechecker/StdAttachments.scala +++ b/src/compiler/scala/tools/nsc/typechecker/StdAttachments.scala @@ -20,7 +20,7 @@ trait StdAttachments { /** Loads underlying MacroExpanderAttachment from a macro expandee or returns a default value for that attachment. */ - def macroExpanderAttachment(tree: Tree): MacroExpanderAttachment = + def macroExpanderAttachment(tree: Tree): MacroExpanderAttachment = tree.attachments.get[MacroExpanderAttachment] getOrElse { tree match { case Apply(fn, _) if tree.isInstanceOf[ApplyToImplicitArgs] => macroExpanderAttachment(fn) diff --git a/src/library/scala/collection/Seq.scala b/src/library/scala/collection/Seq.scala index 27b45acff67b..ad7d8061b8b4 100644 --- a/src/library/scala/collection/Seq.scala +++ b/src/library/scala/collection/Seq.scala @@ -1035,7 +1035,7 @@ object SeqOps { * @param wlen Just in case we're only IndexedSeq and not IndexedSeqOptimized * @return KMP jump table for target sequence */ - private def kmpJumpTable[B](Wopt: IndexedSeqView[B], wlen: Int) = { + private def kmpJumpTable[B](Wopt: IndexedSeqView[B], wlen: Int) = { val arr = new Array[Int](wlen) var pos = 2 var cnd = 0 diff --git a/src/library/scala/collection/mutable/StringBuilder.scala b/src/library/scala/collection/mutable/StringBuilder.scala index 299becd9d763..72bd1d47462b 100644 --- a/src/library/scala/collection/mutable/StringBuilder.scala +++ b/src/library/scala/collection/mutable/StringBuilder.scala @@ -57,7 +57,7 @@ final class StringBuilder(val underlying: java.lang.StringBuilder) extends Abstr // Methods required to make this an IndexedSeq: def apply(i: Int): Char = underlying.charAt(i) - override protected def fromSpecificIterable(coll: scala.collection.Iterable[Char]): StringBuilder = + override protected def fromSpecificIterable(coll: scala.collection.Iterable[Char]): StringBuilder = new StringBuilder() appendAll coll override protected def newSpecificBuilder: Builder[Char, StringBuilder] = diff --git a/src/library/scala/concurrent/duration/Duration.scala b/src/library/scala/concurrent/duration/Duration.scala index d39af28be34c..6b221940d91a 100644 --- a/src/library/scala/concurrent/duration/Duration.scala +++ b/src/library/scala/concurrent/duration/Duration.scala @@ -693,7 +693,7 @@ final class FiniteDuration(val length: Long, val unit: TimeUnit) extends Duratio * * @throws ArithmeticException if the factor is 0 */ - def div(divisor: Long) = this / divisor + def div(divisor: Long) = this / divisor /** * Return the product of this duration and the given integer factor. diff --git a/src/library/scala/math/BigDecimal.scala b/src/library/scala/math/BigDecimal.scala index 309ab51e3d8a..a04e72850831 100644 --- a/src/library/scala/math/BigDecimal.scala +++ b/src/library/scala/math/BigDecimal.scala @@ -125,7 +125,7 @@ object BigDecimal { /** Constructs a `BigDecimal` that exactly represents the number * specified in base 10 in a character array. */ - def exact(cs: Array[Char]): BigDecimal = exact(new BigDec(cs)) + def exact(cs: Array[Char]): BigDecimal = exact(new BigDec(cs)) /** Constructs a `BigDecimal` using the java BigDecimal static From cc66be63be36a87b22edb46189e68ba9f75bc0a0 Mon Sep 17 00:00:00 2001 From: Miles Sabin Date: Wed, 25 Jul 2018 08:13:04 +0100 Subject: [PATCH 080/143] Add a default to ImplicitSearch ctor arg to unbreak shapeless The introduction of the isByNamePt constructor argument of ImplicitSearch breaks the use of this constructor by shapeless. This commit fixes that by adding a default argument. I'd be happy to also reorder the arguments so that isByNamePt comes last, or alternatively reinstate the previous constructor signature via a secondary constructor. --- src/compiler/scala/tools/nsc/typechecker/Implicits.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/compiler/scala/tools/nsc/typechecker/Implicits.scala b/src/compiler/scala/tools/nsc/typechecker/Implicits.scala index 6583d99ad16a..b7f96840118f 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Implicits.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Implicits.scala @@ -389,7 +389,7 @@ trait Implicits { * (useful when we infer synthetic stuff and pass EmptyTree in the `tree` argument) * If it's set to NoPosition, then position-based services will use `tree.pos` */ - class ImplicitSearch(val tree: Tree, val pt: Type, val isView: Boolean, val isByNamePt: Boolean, val context0: Context, val pos0: Position = NoPosition) extends Typer(context0) with ImplicitsContextErrors { + class ImplicitSearch(val tree: Tree, val pt: Type, val isView: Boolean, val isByNamePt: Boolean = false, val context0: Context, val pos0: Position = NoPosition) extends Typer(context0) with ImplicitsContextErrors { val searchId = implicitSearchId() private def typingLog(what: String, msg: => String) = { if (printingOk(tree)) From 2fb1703c19a5bf85028d5cc843f359fd6bc091fd Mon Sep 17 00:00:00 2001 From: Miles Sabin Date: Wed, 25 Jul 2018 10:03:35 +0100 Subject: [PATCH 081/143] Make isByNamePt last ctor arg. --- src/compiler/scala/tools/nsc/typechecker/Implicits.scala | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/compiler/scala/tools/nsc/typechecker/Implicits.scala b/src/compiler/scala/tools/nsc/typechecker/Implicits.scala index b7f96840118f..82195166b143 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Implicits.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Implicits.scala @@ -92,7 +92,7 @@ trait Implicits { val implicitSearchContext = context.makeImplicit(reportAmbiguous) val dpt = if (isView) pt else dropByName(pt) val isByName = dpt ne pt - val search = new ImplicitSearch(tree, dpt, isView, isByName, implicitSearchContext, pos) + val search = new ImplicitSearch(tree, dpt, isView, implicitSearchContext, pos, isByName) pluginsNotifyImplicitSearch(search) val result = search.bestImplicit pluginsNotifyImplicitSearchResult(result) @@ -154,7 +154,7 @@ trait Implicits { val tvars = tpars map (TypeVar untouchable _) val tpSubsted = tp.subst(tpars, tvars) - val search = new ImplicitSearch(EmptyTree, functionType(List(tpSubsted), AnyTpe), true, false, context.makeImplicit(reportAmbiguousErrors = false)) + val search = new ImplicitSearch(EmptyTree, functionType(List(tpSubsted), AnyTpe), true, context.makeImplicit(reportAmbiguousErrors = false), isByNamePt = false) search.allImplicitsPoly(tvars) } @@ -389,7 +389,7 @@ trait Implicits { * (useful when we infer synthetic stuff and pass EmptyTree in the `tree` argument) * If it's set to NoPosition, then position-based services will use `tree.pos` */ - class ImplicitSearch(val tree: Tree, val pt: Type, val isView: Boolean, val isByNamePt: Boolean = false, val context0: Context, val pos0: Position = NoPosition) extends Typer(context0) with ImplicitsContextErrors { + class ImplicitSearch(val tree: Tree, val pt: Type, val isView: Boolean, val context0: Context, val pos0: Position = NoPosition, val isByNamePt: Boolean = false) extends Typer(context0) with ImplicitsContextErrors { val searchId = implicitSearchId() private def typingLog(what: String, msg: => String) = { if (printingOk(tree)) From 665df73dddf5498dd805f7bec987766be4a1d95c Mon Sep 17 00:00:00 2001 From: Allan Renucci Date: Thu, 26 Jul 2018 11:33:20 +0200 Subject: [PATCH 082/143] Rename `enum` to `enumeration` `enum` is now a keyword in Dotty --- src/library/scala/Enumeration.scala | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/library/scala/Enumeration.scala b/src/library/scala/Enumeration.scala index 26e3fa6c066a..9ebb316fd8e3 100644 --- a/src/library/scala/Enumeration.scala +++ b/src/library/scala/Enumeration.scala @@ -249,9 +249,9 @@ abstract class Enumeration (initial: Int) extends Serializable { catch { case _: NoSuchElementException => "" } protected def readResolve(): AnyRef = { - val enum = thisenum.readResolve().asInstanceOf[Enumeration] - if (enum.vmap == null) this - else enum.vmap(i) + val enumeration = thisenum.readResolve().asInstanceOf[Enumeration] + if (enumeration.vmap == null) this + else enumeration.vmap(i) } } From d4aef3584a07927dd844d9b54f6a149242e1fa1e Mon Sep 17 00:00:00 2001 From: Allan Renucci Date: Thu, 26 Jul 2018 11:48:25 +0200 Subject: [PATCH 083/143] Dotty only considers methods as implicit conversions See http://dotty.epfl.ch/docs/reference/changed/implicit-conversions.html --- src/library/scala/math/Ordering.scala | 4 ++-- src/library/scala/runtime/Tuple2Zipped.scala | 2 +- src/library/scala/runtime/Tuple3Zipped.scala | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/library/scala/math/Ordering.scala b/src/library/scala/math/Ordering.scala index a3b8cff9f19d..2ca181449d60 100644 --- a/src/library/scala/math/Ordering.scala +++ b/src/library/scala/math/Ordering.scala @@ -199,8 +199,8 @@ trait LowPriorityOrderingImplicits { * turn up if nothing else works. Since `Ordered[A]` extends * `Comparable[A]` anyway, we can throw in some Java interop too. */ - implicit def ordered[A: AsComparable]: Ordering[A] = new Ordering[A] { - def compare(x: A, y: A): Int = x compareTo y + implicit def ordered[A](implicit asComparable: AsComparable[A]): Ordering[A] = new Ordering[A] { + def compare(x: A, y: A): Int = asComparable(x).compareTo(y) } implicit def comparatorToOrdering[A](implicit cmp: Comparator[A]): Ordering[A] = new Ordering[A] { diff --git a/src/library/scala/runtime/Tuple2Zipped.scala b/src/library/scala/runtime/Tuple2Zipped.scala index b9370ed0fb3e..fcfc309a26cf 100644 --- a/src/library/scala/runtime/Tuple2Zipped.scala +++ b/src/library/scala/runtime/Tuple2Zipped.scala @@ -135,6 +135,6 @@ object Tuple2Zipped { def zipped[El1, It1 <: Iterable[El1], El2, It2 <: Iterable[El2]] (implicit w1: T1 => IterableOps[El1, Iterable, It1] with It1, w2: T2 => IterableOps[El2, Iterable, It2] with It2 - ): Tuple2Zipped[El1, It1, El2, It2] = new Tuple2Zipped((x._1, x._2)) + ): Tuple2Zipped[El1, It1, El2, It2] = new Tuple2Zipped((w1(x._1), w2(x._2))) } } diff --git a/src/library/scala/runtime/Tuple3Zipped.scala b/src/library/scala/runtime/Tuple3Zipped.scala index 01ab2f3d5ae2..96b9eba92423 100644 --- a/src/library/scala/runtime/Tuple3Zipped.scala +++ b/src/library/scala/runtime/Tuple3Zipped.scala @@ -149,6 +149,6 @@ object Tuple3Zipped { (implicit w1: T1 => IterableOps[El1, Iterable, It1] with It1, w2: T2 => IterableOps[El2, Iterable, It2] with It2, w3: T3 => IterableOps[El3, Iterable, It3] with It3 - ): Tuple3Zipped[El1, It1, El2, It2, El3, It3] = new Tuple3Zipped((x._1, x._2, x._3)) + ): Tuple3Zipped[El1, It1, El2, It2, El3, It3] = new Tuple3Zipped((w1(x._1), w2(x._2), w3(x._3))) } } From fec6ae6e59155b22cae196e54f28bb0f05c5548d Mon Sep 17 00:00:00 2001 From: Allan Renucci Date: Thu, 26 Jul 2018 11:40:09 +0200 Subject: [PATCH 084/143] Add explicit result types to implicit definitions --- src/library/scala/Predef.scala | 20 +++++++++---------- .../scala/util/control/Exception.scala | 2 +- src/library/scala/util/hashing/Hashing.scala | 2 +- 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/library/scala/Predef.scala b/src/library/scala/Predef.scala index e287b6be0eae..a309f8aa14ef 100644 --- a/src/library/scala/Predef.scala +++ b/src/library/scala/Predef.scala @@ -429,8 +429,8 @@ object Predef extends LowPriorityImplicits { // views -------------------------------------------------------------- - implicit def tuple2ToZippedOps[T1, T2](x: (T1, T2)) = new runtime.Tuple2Zipped.Ops(x) - implicit def tuple3ToZippedOps[T1, T2, T3](x: (T1, T2, T3)) = new runtime.Tuple3Zipped.Ops(x) + implicit def tuple2ToZippedOps[T1, T2](x: (T1, T2)): runtime.Tuple2Zipped.Ops[T1, T2] = new runtime.Tuple2Zipped.Ops(x) + implicit def tuple3ToZippedOps[T1, T2, T3](x: (T1, T2, T3)): runtime.Tuple3Zipped.Ops[T1, T2, T3] = new runtime.Tuple3Zipped.Ops(x) // Not specialized anymore since 2.13 but we still need separate methods // to avoid https://github.com/scala/bug/issues/10746 @@ -756,14 +756,14 @@ private[scala] abstract class LowPriorityImplicits extends LowPriorityImplicits2 * Even inlined, every call site does a no-op retrieval of Predef's MODULE$ * because maybe loading Predef has side effects! */ - @inline implicit def byteWrapper(x: Byte) = new runtime.RichByte(x) - @inline implicit def shortWrapper(x: Short) = new runtime.RichShort(x) - @inline implicit def intWrapper(x: Int) = new runtime.RichInt(x) - @inline implicit def charWrapper(c: Char) = new runtime.RichChar(c) - @inline implicit def longWrapper(x: Long) = new runtime.RichLong(x) - @inline implicit def floatWrapper(x: Float) = new runtime.RichFloat(x) - @inline implicit def doubleWrapper(x: Double) = new runtime.RichDouble(x) - @inline implicit def booleanWrapper(x: Boolean) = new runtime.RichBoolean(x) + @inline implicit def byteWrapper(x: Byte): runtime.RichByte = new runtime.RichByte(x) + @inline implicit def shortWrapper(x: Short): runtime.RichShort = new runtime.RichShort(x) + @inline implicit def intWrapper(x: Int): runtime.RichInt = new runtime.RichInt(x) + @inline implicit def charWrapper(c: Char): runtime.RichChar = new runtime.RichChar(c) + @inline implicit def longWrapper(x: Long): runtime.RichLong = new runtime.RichLong(x) + @inline implicit def floatWrapper(x: Float): runtime.RichFloat = new runtime.RichFloat(x) + @inline implicit def doubleWrapper(x: Double): runtime.RichDouble = new runtime.RichDouble(x) + @inline implicit def booleanWrapper(x: Boolean): runtime.RichBoolean = new runtime.RichBoolean(x) /** @group conversions-array-to-wrapped-array */ implicit def genericWrapArray[T](xs: Array[T]): ArraySeq[T] = diff --git a/src/library/scala/util/control/Exception.scala b/src/library/scala/util/control/Exception.scala index 07574e871be2..d93b38042dca 100644 --- a/src/library/scala/util/control/Exception.scala +++ b/src/library/scala/util/control/Exception.scala @@ -161,7 +161,7 @@ object Exception { def mkThrowableCatcher[T](isDef: Throwable => Boolean, f: Throwable => T) = mkCatcher(isDef, f) - implicit def throwableSubtypeToCatcher[Ex <: Throwable: ClassTag, T](pf: PartialFunction[Ex, T]) = + implicit def throwableSubtypeToCatcher[Ex <: Throwable: ClassTag, T](pf: PartialFunction[Ex, T]): Catcher[T] = mkCatcher(pf.isDefinedAt _, pf.apply _) /** !!! Not at all sure of every factor which goes into this, diff --git a/src/library/scala/util/hashing/Hashing.scala b/src/library/scala/util/hashing/Hashing.scala index 2b72c1dbe3de..884a0e23a7c8 100644 --- a/src/library/scala/util/hashing/Hashing.scala +++ b/src/library/scala/util/hashing/Hashing.scala @@ -32,7 +32,7 @@ object Hashing { def hash(x: T) = x.## } - implicit def default[T] = new Default[T] + implicit def default[T]: Default[T] = new Default[T] def fromFunction[T](f: T => Int) = new Hashing[T] { def hash(x: T) = f(x) From edb45b7cfc571468fe3dbb803a8499dac0ac9721 Mon Sep 17 00:00:00 2001 From: Allan Renucci Date: Thu, 26 Jul 2018 11:55:36 +0200 Subject: [PATCH 085/143] Workaround lampepfl/dotty#4739 --- src/library/scala/runtime/StructuralCallSite.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/library/scala/runtime/StructuralCallSite.java b/src/library/scala/runtime/StructuralCallSite.java index f73b4f08e622..76e165409096 100644 --- a/src/library/scala/runtime/StructuralCallSite.java +++ b/src/library/scala/runtime/StructuralCallSite.java @@ -7,11 +7,11 @@ public final class StructuralCallSite { - private Class[] parameterTypes; + private Class[] _parameterTypes; private SoftReference cache = new SoftReference<>(new EmptyMethodCache()); private StructuralCallSite(MethodType callType) { - parameterTypes = callType.parameterArray(); + _parameterTypes = callType.parameterArray(); } public MethodCache get() { @@ -32,7 +32,7 @@ public Method add(Class receiver, Method m) { return m; } public Class[] parameterTypes() { - return parameterTypes; + return _parameterTypes; } public static CallSite bootstrap(MethodHandles.Lookup lookup, String invokedName, From e5cf68d2ca0ca4ffca9ab1f4d72ee3df64187664 Mon Sep 17 00:00:00 2001 From: Allan Renucci Date: Thu, 26 Jul 2018 16:54:29 +0200 Subject: [PATCH 086/143] Fix TreeMap class hierarchy Inherit `StrictOptimizedMapOps` to refine return type of map, flatmap, concat and collect. See lampepfl/dotty#4839 --- src/library/scala/collection/immutable/TreeMap.scala | 7 ++++--- src/library/scala/collection/mutable/TreeMap.scala | 8 ++++---- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/src/library/scala/collection/immutable/TreeMap.scala b/src/library/scala/collection/immutable/TreeMap.scala index f7ec43cfe6bd..7b7f5966c4e9 100644 --- a/src/library/scala/collection/immutable/TreeMap.scala +++ b/src/library/scala/collection/immutable/TreeMap.scala @@ -30,15 +30,16 @@ final class TreeMap[K, +V] private (tree: RB.Tree[K, V])(implicit val ordering: with SortedMap[K, V] with SortedMapOps[K, V, TreeMap, TreeMap[K, V]] with StrictOptimizedIterableOps[(K, V), Iterable, TreeMap[K, V]] + with StrictOptimizedMapOps[K, V, Map, TreeMap[K, V]] with StrictOptimizedSortedMapOps[K, V, TreeMap, TreeMap[K, V]] { def this()(implicit ordering: Ordering[K]) = this(null)(ordering) override def sortedMapFactory = TreeMap - def iterator: collection.Iterator[(K, V)] = RB.iterator(tree) + def iterator: Iterator[(K, V)] = RB.iterator(tree) - def keysIteratorFrom(start: K): collection.Iterator[K] = RB.keysIterator(tree, Some(start)) + def keysIteratorFrom(start: K): Iterator[K] = RB.keysIterator(tree, Some(start)) def iteratorFrom(start: K): Iterator[(K, V)] = RB.iterator(tree, Some(start)) @@ -152,7 +153,7 @@ object TreeMap extends SortedMapFactory[TreeMap] { def empty[K : Ordering, V]: TreeMap[K, V] = new TreeMap() - def from[K : Ordering, V](it: collection.IterableOnce[(K, V)]): TreeMap[K, V] = + def from[K : Ordering, V](it: IterableOnce[(K, V)]): TreeMap[K, V] = it match { case tm: TreeMap[K, V] => tm case _ => (newBuilder[K, V] ++= it).result() diff --git a/src/library/scala/collection/mutable/TreeMap.scala b/src/library/scala/collection/mutable/TreeMap.scala index 2b3a1479f6ff..8f3e48a2211d 100644 --- a/src/library/scala/collection/mutable/TreeMap.scala +++ b/src/library/scala/collection/mutable/TreeMap.scala @@ -1,9 +1,8 @@ package scala -package collection.mutable +package collection +package mutable -import collection.{Iterator, SortedMapFactory, StrictOptimizedIterableOps, StrictOptimizedSortedMapOps} import collection.mutable.{RedBlackTree => RB} -import java.lang.String /** * A mutable sorted map implemented using a mutable red-black tree as underlying data structure. @@ -23,6 +22,7 @@ sealed class TreeMap[K, V] private (tree: RB.Tree[K, V])(implicit val ordering: with SortedMap[K, V] with SortedMapOps[K, V, TreeMap, TreeMap[K, V]] with StrictOptimizedIterableOps[(K, V), Iterable, TreeMap[K, V]] + with StrictOptimizedMapOps[K, V, Map, TreeMap[K, V]] with StrictOptimizedSortedMapOps[K, V, TreeMap, TreeMap[K, V]] { override def sortedMapFactory = TreeMap @@ -178,7 +178,7 @@ sealed class TreeMap[K, V] private (tree: RB.Tree[K, V])(implicit val ordering: @SerialVersionUID(3L) object TreeMap extends SortedMapFactory[TreeMap] { - def from[K : Ordering, V](it: collection.IterableOnce[(K, V)]): TreeMap[K, V] = + def from[K : Ordering, V](it: IterableOnce[(K, V)]): TreeMap[K, V] = Growable.from(empty[K, V], it) def empty[K : Ordering, V]: TreeMap[K, V] = new TreeMap[K, V]() From 38c213e11a7b0c26c16c9751f313ce915d261300 Mon Sep 17 00:00:00 2001 From: Allan Renucci Date: Thu, 26 Jul 2018 17:36:31 +0200 Subject: [PATCH 087/143] Workaround lampepfl/dotty#4742 --- src/library/scala/util/control/Exception.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/library/scala/util/control/Exception.scala b/src/library/scala/util/control/Exception.scala index 07574e871be2..8beb1a6979c6 100644 --- a/src/library/scala/util/control/Exception.scala +++ b/src/library/scala/util/control/Exception.scala @@ -159,7 +159,7 @@ object Exception { def apply(x: Throwable): T = f(downcast(x).get) } - def mkThrowableCatcher[T](isDef: Throwable => Boolean, f: Throwable => T) = mkCatcher(isDef, f) + def mkThrowableCatcher[T](isDef: Throwable => Boolean, f: Throwable => T) = mkCatcher[Throwable, T](isDef, f) implicit def throwableSubtypeToCatcher[Ex <: Throwable: ClassTag, T](pf: PartialFunction[Ex, T]) = mkCatcher(pf.isDefinedAt _, pf.apply _) From d33fdaec3ee41b0256494c77a5b8d0ffe13503d7 Mon Sep 17 00:00:00 2001 From: Allan Renucci Date: Thu, 26 Jul 2018 19:20:49 +0200 Subject: [PATCH 088/143] Lazy values may not override a non-lazy value in Dotty --- src/library/scala/io/BufferedSource.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/library/scala/io/BufferedSource.scala b/src/library/scala/io/BufferedSource.scala index e4686176b230..deed6930b6b6 100644 --- a/src/library/scala/io/BufferedSource.scala +++ b/src/library/scala/io/BufferedSource.scala @@ -34,7 +34,7 @@ class BufferedSource(inputStream: InputStream, bufferSize: Int)(implicit val cod bufferedReader() } - override lazy val iter = ( + override val iter = ( Iterator continually (codec wrap charReader.read()) takeWhile (_ != -1) From f5c102e72fbd835bf66377879bdb8be20d882da1 Mon Sep 17 00:00:00 2001 From: Allan Renucci Date: Thu, 26 Jul 2018 18:18:15 +0200 Subject: [PATCH 089/143] Normalise API for Auto-Application removal Dotty does not support Auto-Application (an empty argument list `()` was implicitly inserted when calling a nullary method without arguments). See http://dotty.epfl.ch/docs/reference/dropped/auto-apply.html --- src/library/scala/StringContext.scala | 2 +- .../scala/collection/IterableOnce.scala | 6 ++-- src/library/scala/collection/StringOps.scala | 4 +-- .../collection/generic/IsIterableLike.scala | 4 +-- .../scala/collection/generic/IsSeqLike.scala | 4 +-- src/library/scala/io/Source.scala | 2 +- src/library/scala/math/BigDecimal.scala | 20 +++++------ src/library/scala/math/BigInt.scala | 2 +- .../scala/math/ScalaNumericConversions.scala | 34 +++++++++---------- src/library/scala/ref/Reference.scala | 2 +- src/library/scala/ref/ReferenceWrapper.scala | 2 +- src/library/scala/runtime/RichByte.scala | 12 +++---- src/library/scala/runtime/RichChar.scala | 12 +++---- src/library/scala/runtime/RichDouble.scala | 12 +++---- src/library/scala/runtime/RichFloat.scala | 12 +++---- src/library/scala/runtime/RichInt.scala | 12 +++---- src/library/scala/runtime/RichLong.scala | 12 +++---- src/library/scala/runtime/RichShort.scala | 12 +++---- .../scala/runtime/ScalaNumberProxy.scala | 18 +++++----- src/library/scala/sys/BooleanProp.scala | 6 +++- .../scala/sys/ShutdownHookThread.scala | 2 +- src/library/scala/util/matching/Regex.scala | 6 ++-- test/files/pos/t6600.scala | 12 +++---- .../files/presentation/infix-completion.check | 6 ++-- .../presentation/infix-completion2.check | 6 ++-- 25 files changed, 113 insertions(+), 109 deletions(-) diff --git a/src/library/scala/StringContext.scala b/src/library/scala/StringContext.scala index d71048576e16..9606fdf58584 100644 --- a/src/library/scala/StringContext.scala +++ b/src/library/scala/StringContext.scala @@ -232,7 +232,7 @@ object StringContext { val ai = args.iterator val bldr = new JLSBuilder(process(pi.next())) while (ai.hasNext) { - bldr append ai.next + bldr append ai.next() bldr append process(pi.next()) } bldr.toString diff --git a/src/library/scala/collection/IterableOnce.scala b/src/library/scala/collection/IterableOnce.scala index b76cc9630dcf..36d981070b6d 100644 --- a/src/library/scala/collection/IterableOnce.scala +++ b/src/library/scala/collection/IterableOnce.scala @@ -1061,7 +1061,7 @@ trait IterableOnceOps[+A, +CC[_], +C] extends Any { this: IterableOnce[A] => */ final def mkString(start: String, sep: String, end: String): String = if (isEmpty) start + end - else addString(new StringBuilder(), start, sep, end).result + else addString(new StringBuilder(), start, sep, end).result() /** Displays all elements of this $coll in a string using a separator string. * @@ -1116,10 +1116,10 @@ trait IterableOnceOps[+A, +CC[_], +C] extends Any { this: IterableOnce[A] => if (start.length != 0) jsb.append(start) val it = iterator if (it.hasNext) { - jsb.append(it.next) + jsb.append(it.next()) while (it.hasNext) { jsb.append(sep) - jsb.append(it.next) + jsb.append(it.next()) } } if (end.length != 0) jsb.append(end) diff --git a/src/library/scala/collection/StringOps.scala b/src/library/scala/collection/StringOps.scala index 7f65d32863eb..fa87465e22b0 100644 --- a/src/library/scala/collection/StringOps.scala +++ b/src/library/scala/collection/StringOps.scala @@ -1051,7 +1051,7 @@ final class StringOps(private val s: String) extends AnyVal { def indices: Range = Range(0, s.length) /** Iterator can be used only once */ - def iterator(): Iterator[Char] = new StringIterator(s) + def iterator: Iterator[Char] = new StringIterator(s) /** Tests whether the string is not empty. */ @`inline` def nonEmpty: Boolean = !s.isEmpty @@ -1065,7 +1065,7 @@ final class StringOps(private val s: String) extends AnyVal { * * @return an iterator yielding the chars of this string in reversed order */ - def reverseIterator(): Iterator[Char] = new ReverseIterator(s) + def reverseIterator: Iterator[Char] = new ReverseIterator(s) /** Creates a non-strict filter of this string. * diff --git a/src/library/scala/collection/generic/IsIterableLike.scala b/src/library/scala/collection/generic/IsIterableLike.scala index 72efffac69c3..68ebb92e0281 100644 --- a/src/library/scala/collection/generic/IsIterableLike.scala +++ b/src/library/scala/collection/generic/IsIterableLike.scala @@ -115,8 +115,8 @@ object IsIterableLike { protected[this] def coll: String = s protected[this] def fromSpecificIterable(coll: Iterable[Char]): String = coll.mkString def iterableFactory: IterableFactory[Iterable] = Iterable - protected[this] def newSpecificBuilder(): mutable.Builder[Char, String] = new StringBuilder - def iterator(): Iterator[Char] = s.iterator() + protected[this] def newSpecificBuilder: mutable.Builder[Char, String] = new StringBuilder + def iterator: Iterator[Char] = s.iterator } } diff --git a/src/library/scala/collection/generic/IsSeqLike.scala b/src/library/scala/collection/generic/IsSeqLike.scala index f45590cce7b9..faed438d148a 100644 --- a/src/library/scala/collection/generic/IsSeqLike.scala +++ b/src/library/scala/collection/generic/IsSeqLike.scala @@ -31,8 +31,8 @@ object IsSeqLike { protected[this] def coll: String = s protected[this] def fromSpecificIterable(coll: Iterable[Char]): String = coll.mkString def iterableFactory: IterableFactory[Seq] = Seq - protected[this] def newSpecificBuilder(): mutable.Builder[Char, String] = new StringBuilder - def iterator(): Iterator[Char] = s.iterator() + protected[this] def newSpecificBuilder: mutable.Builder[Char, String] = new StringBuilder + def iterator: Iterator[Char] = s.iterator } } diff --git a/src/library/scala/io/Source.scala b/src/library/scala/io/Source.scala index 8bb07194b1cf..eddfd9b0db78 100644 --- a/src/library/scala/io/Source.scala +++ b/src/library/scala/io/Source.scala @@ -227,7 +227,7 @@ abstract class Source extends Iterator[Char] with Closeable { } } def hasNext = iter.hasNext - def next = { + def next() = { sb.clear() while (getc()) { } sb.toString diff --git a/src/library/scala/math/BigDecimal.scala b/src/library/scala/math/BigDecimal.scala index a04e72850831..076b779a9892 100644 --- a/src/library/scala/math/BigDecimal.scala +++ b/src/library/scala/math/BigDecimal.scala @@ -394,7 +394,7 @@ extends ScalaNumber with ScalaNumericConversions with Serializable with Ordered[ * with large exponents. */ override def hashCode(): Int = { - if (computedHashCode == BigDecimal.hashCodeNotComputed) computeHashCode + if (computedHashCode == BigDecimal.hashCodeNotComputed) computeHashCode() computedHashCode } @@ -466,7 +466,7 @@ extends ScalaNumber with ScalaNumericConversions with Serializable with Ordered[ catch { case _: ArithmeticException => false } } - def isWhole() = scale <= 0 || bigDecimal.stripTrailingZeros.scale <= 0 + def isWhole = scale <= 0 || bigDecimal.stripTrailingZeros.scale <= 0 def underlying = bigDecimal @@ -547,11 +547,11 @@ extends ScalaNumber with ScalaNumericConversions with Serializable with Ordered[ * +1 if it is greater than 0, * 0 if it is equal to 0. */ - def signum: Int = this.bigDecimal.signum() + def signum: Int = this.bigDecimal.signum /** Returns the precision of this `BigDecimal`. */ - def precision: Int = this.bigDecimal.precision() + def precision: Int = this.bigDecimal.precision /** Returns a BigDecimal rounded according to the supplied MathContext settings, but * preserving its own MathContext for future operations. @@ -569,7 +569,7 @@ extends ScalaNumber with ScalaNumericConversions with Serializable with Ordered[ /** Returns the scale of this `BigDecimal`. */ - def scale: Int = this.bigDecimal.scale() + def scale: Int = this.bigDecimal.scale /** Returns the size of an ulp, a unit in the last place, of this BigDecimal. */ @@ -697,20 +697,20 @@ extends ScalaNumber with ScalaNumericConversions with Serializable with Ordered[ /** Converts this `BigDecimal` to a scala.BigInt. */ - def toBigInt(): BigInt = new BigInt(this.bigDecimal.toBigInteger()) + def toBigInt: BigInt = new BigInt(this.bigDecimal.toBigInteger) /** Converts this `BigDecimal` to a scala.BigInt if it * can be done losslessly, returning Some(BigInt) or None. */ - def toBigIntExact(): Option[BigInt] = - if (isWhole()) { - try Some(new BigInt(this.bigDecimal.toBigIntegerExact())) + def toBigIntExact: Option[BigInt] = + if (isWhole) { + try Some(new BigInt(this.bigDecimal.toBigIntegerExact)) catch { case _: ArithmeticException => None } } else None /** Returns the decimal String representation of this BigDecimal. */ - override def toString(): String = this.bigDecimal.toString() + override def toString: String = this.bigDecimal.toString } diff --git a/src/library/scala/math/BigInt.scala b/src/library/scala/math/BigInt.scala index f23db59ccc79..478670305658 100644 --- a/src/library/scala/math/BigInt.scala +++ b/src/library/scala/math/BigInt.scala @@ -115,7 +115,7 @@ final class BigInt(val bigInteger: BigInteger) { /** Returns the hash code for this BigInt. */ override def hashCode(): Int = - if (isValidLong) unifiedPrimitiveHashcode() + if (isValidLong) unifiedPrimitiveHashcode else bigInteger.## /** Compares this BigInt with the specified value for equality. diff --git a/src/library/scala/math/ScalaNumericConversions.scala b/src/library/scala/math/ScalaNumericConversions.scala index 0006133b13a8..ce99a6ace516 100644 --- a/src/library/scala/math/ScalaNumericConversions.scala +++ b/src/library/scala/math/ScalaNumericConversions.scala @@ -13,7 +13,7 @@ package math * extend ScalaNumber (which excludes value classes.) */ trait ScalaNumericConversions extends ScalaNumber with ScalaNumericAnyConversions { - def underlying(): Object + def underlying: Object } /** Conversions which present a consistent conversion interface @@ -21,50 +21,50 @@ trait ScalaNumericConversions extends ScalaNumber with ScalaNumericAnyConversion */ trait ScalaNumericAnyConversions extends Any { /** @return `'''true'''` if this number has no decimal component, `'''false'''` otherwise. */ - def isWhole(): Boolean - def underlying(): Any + def isWhole: Boolean + def underlying: Any - def byteValue(): Byte - def shortValue(): Short - def intValue(): Int - def longValue(): Long - def floatValue(): Float - def doubleValue(): Double + def byteValue: Byte + def shortValue: Short + def intValue: Int + def longValue: Long + def floatValue: Float + def doubleValue: Double /** Returns the value of this as a [[scala.Char]]. This may involve * rounding or truncation. */ - def toChar = intValue().toChar + def toChar = intValue.toChar /** Returns the value of this as a [[scala.Byte]]. This may involve * rounding or truncation. */ - def toByte = byteValue() + def toByte = byteValue /** Returns the value of this as a [[scala.Short]]. This may involve * rounding or truncation. */ - def toShort = shortValue() + def toShort = shortValue /** Returns the value of this as an [[scala.Int]]. This may involve * rounding or truncation. */ - def toInt = intValue() + def toInt = intValue /** Returns the value of this as a [[scala.Long]]. This may involve * rounding or truncation. */ - def toLong = longValue() + def toLong = longValue /** Returns the value of this as a [[scala.Float]]. This may involve * rounding or truncation. */ - def toFloat = floatValue() + def toFloat = floatValue /** Returns the value of this as a [[scala.Double]]. This may involve * rounding or truncation. */ - def toDouble = doubleValue() + def toDouble = doubleValue /** Returns `true` iff this has a zero fractional part, and is within the * range of [[scala.Byte]] MinValue and MaxValue; otherwise returns `false`. @@ -86,7 +86,7 @@ trait ScalaNumericAnyConversions extends Any { */ def isValidChar = isWhole && (toInt >= Char.MinValue && toInt <= Char.MaxValue) - protected def unifiedPrimitiveHashcode() = { + protected def unifiedPrimitiveHashcode = { val lv = toLong if (lv >= Int.MinValue && lv <= Int.MaxValue) lv.toInt else lv.## diff --git a/src/library/scala/ref/Reference.scala b/src/library/scala/ref/Reference.scala index 6377dddcd3ca..30b0018a6c57 100644 --- a/src/library/scala/ref/Reference.scala +++ b/src/library/scala/ref/Reference.scala @@ -20,5 +20,5 @@ trait Reference[+T <: AnyRef] extends Function0[T] { override def toString = get.map(_.toString).getOrElse("") def clear(): Unit def enqueue(): Boolean - def isEnqueued(): Boolean + def isEnqueued: Boolean } diff --git a/src/library/scala/ref/ReferenceWrapper.scala b/src/library/scala/ref/ReferenceWrapper.scala index 3da1f2ea7c9c..330adcc4b6d5 100644 --- a/src/library/scala/ref/ReferenceWrapper.scala +++ b/src/library/scala/ref/ReferenceWrapper.scala @@ -21,7 +21,7 @@ trait ReferenceWrapper[+T <: AnyRef] extends Reference[T] with Proxy { ret } def clear() = underlying.clear() - def enqueue = underlying.enqueue + def enqueue() = underlying.enqueue() def isEnqueued = underlying.isEnqueued def self = underlying } diff --git a/src/library/scala/runtime/RichByte.scala b/src/library/scala/runtime/RichByte.scala index ce658d2277ee..9ab2eeb33162 100644 --- a/src/library/scala/runtime/RichByte.scala +++ b/src/library/scala/runtime/RichByte.scala @@ -14,12 +14,12 @@ final class RichByte(val self: Byte) extends AnyVal with ScalaWholeNumberProxy[B protected def num = scala.math.Numeric.ByteIsIntegral protected def ord = scala.math.Ordering.Byte - override def doubleValue() = self.toDouble - override def floatValue() = self.toFloat - override def longValue() = self.toLong - override def intValue() = self.toInt - override def byteValue() = self - override def shortValue() = self.toShort + override def doubleValue = self.toDouble + override def floatValue = self.toFloat + override def longValue = self.toLong + override def intValue = self.toInt + override def byteValue = self + override def shortValue = self.toShort override def isValidByte = true diff --git a/src/library/scala/runtime/RichChar.scala b/src/library/scala/runtime/RichChar.scala index 71ea3a21e1a7..df0465ef1492 100644 --- a/src/library/scala/runtime/RichChar.scala +++ b/src/library/scala/runtime/RichChar.scala @@ -16,12 +16,12 @@ final class RichChar(val self: Char) extends AnyVal with IntegralProxy[Char] { protected def num = scala.math.Numeric.CharIsIntegral protected def ord = scala.math.Ordering.Char - override def doubleValue() = self.toDouble - override def floatValue() = self.toFloat - override def longValue() = self.toLong - override def intValue() = self.toInt - override def byteValue() = self.toByte - override def shortValue() = self.toShort + override def doubleValue = self.toDouble + override def floatValue = self.toFloat + override def longValue = self.toLong + override def intValue = self.toInt + override def byteValue = self.toByte + override def shortValue = self.toShort override def isValidChar = true diff --git a/src/library/scala/runtime/RichDouble.scala b/src/library/scala/runtime/RichDouble.scala index 3bfd7648b214..9736f4085578 100644 --- a/src/library/scala/runtime/RichDouble.scala +++ b/src/library/scala/runtime/RichDouble.scala @@ -13,12 +13,12 @@ final class RichDouble(val self: Double) extends AnyVal with FractionalProxy[Dou protected def num: Fractional[Double] = scala.math.Numeric.DoubleIsFractional protected def ord: Ordering[Double] = scala.math.Ordering.Double.TotalOrdering - override def doubleValue() = self - override def floatValue() = self.toFloat - override def longValue() = self.toLong - override def intValue() = self.toInt - override def byteValue() = self.toByte - override def shortValue() = self.toShort + override def doubleValue = self + override def floatValue = self.toFloat + override def longValue = self.toLong + override def intValue = self.toInt + override def byteValue = self.toByte + override def shortValue = self.toShort override def isWhole = { val l = self.toLong diff --git a/src/library/scala/runtime/RichFloat.scala b/src/library/scala/runtime/RichFloat.scala index 5640c64c7ad3..e3a595fb282e 100644 --- a/src/library/scala/runtime/RichFloat.scala +++ b/src/library/scala/runtime/RichFloat.scala @@ -13,12 +13,12 @@ final class RichFloat(val self: Float) extends AnyVal with FractionalProxy[Float protected def num: Fractional[Float] = scala.math.Numeric.FloatIsFractional protected def ord: Ordering[Float] = scala.math.Ordering.Float.TotalOrdering - override def doubleValue() = self.toDouble - override def floatValue() = self - override def longValue() = self.toLong - override def intValue() = self.toInt - override def byteValue() = self.toByte - override def shortValue() = self.toShort + override def doubleValue = self.toDouble + override def floatValue = self + override def longValue = self.toLong + override def intValue = self.toInt + override def byteValue = self.toByte + override def shortValue = self.toShort override def isWhole = { val l = self.toLong diff --git a/src/library/scala/runtime/RichInt.scala b/src/library/scala/runtime/RichInt.scala index 37d236dfe90a..327017f2d01a 100644 --- a/src/library/scala/runtime/RichInt.scala +++ b/src/library/scala/runtime/RichInt.scala @@ -17,12 +17,12 @@ final class RichInt(val self: Int) extends AnyVal with ScalaNumberProxy[Int] wit protected def num = scala.math.Numeric.IntIsIntegral protected def ord = scala.math.Ordering.Int - override def doubleValue() = self.toDouble - override def floatValue() = self.toFloat - override def longValue() = self.toLong - override def intValue() = self - override def byteValue() = self.toByte - override def shortValue() = self.toShort + override def doubleValue = self.toDouble + override def floatValue = self.toFloat + override def longValue = self.toLong + override def intValue = self + override def byteValue = self.toByte + override def shortValue = self.toShort /** Returns `'''true'''` if this number has no decimal component. * Always `'''true'''` for `RichInt`. diff --git a/src/library/scala/runtime/RichLong.scala b/src/library/scala/runtime/RichLong.scala index 233ce231b4c8..c06a34b9ee23 100644 --- a/src/library/scala/runtime/RichLong.scala +++ b/src/library/scala/runtime/RichLong.scala @@ -13,12 +13,12 @@ final class RichLong(val self: Long) extends AnyVal with IntegralProxy[Long] { protected def num = scala.math.Numeric.LongIsIntegral protected def ord = scala.math.Ordering.Long - override def doubleValue() = self.toDouble - override def floatValue() = self.toFloat - override def longValue() = self - override def intValue() = self.toInt - override def byteValue() = self.toByte - override def shortValue() = self.toShort + override def doubleValue = self.toDouble + override def floatValue = self.toFloat + override def longValue = self + override def intValue = self.toInt + override def byteValue = self.toByte + override def shortValue = self.toShort override def isValidByte = self.toByte.toLong == self override def isValidShort = self.toShort.toLong == self diff --git a/src/library/scala/runtime/RichShort.scala b/src/library/scala/runtime/RichShort.scala index b35beff7eb4c..bc41b134066b 100644 --- a/src/library/scala/runtime/RichShort.scala +++ b/src/library/scala/runtime/RichShort.scala @@ -14,12 +14,12 @@ final class RichShort(val self: Short) extends AnyVal with ScalaWholeNumberProxy protected def num = scala.math.Numeric.ShortIsIntegral protected def ord = scala.math.Ordering.Short - override def doubleValue() = self.toDouble - override def floatValue() = self.toFloat - override def longValue() = self.toLong - override def intValue() = self.toInt - override def byteValue() = self.toByte - override def shortValue() = self + override def doubleValue = self.toDouble + override def floatValue = self.toFloat + override def longValue = self.toLong + override def intValue = self.toInt + override def byteValue = self.toByte + override def shortValue = self override def isValidShort = true diff --git a/src/library/scala/runtime/ScalaNumberProxy.scala b/src/library/scala/runtime/ScalaNumberProxy.scala index 4823a3271d06..ef19d871d512 100644 --- a/src/library/scala/runtime/ScalaNumberProxy.scala +++ b/src/library/scala/runtime/ScalaNumberProxy.scala @@ -23,13 +23,13 @@ import Proxy.Typed trait ScalaNumberProxy[T] extends Any with ScalaNumericAnyConversions with Typed[T] with OrderedProxy[T] { protected implicit def num: Numeric[T] - def underlying() = self.asInstanceOf[AnyRef] - def doubleValue() = num.toDouble(self) - def floatValue() = num.toFloat(self) - def longValue() = num.toLong(self) - def intValue() = num.toInt(self) - def byteValue() = intValue().toByte - def shortValue() = intValue().toShort + def underlying = self.asInstanceOf[AnyRef] + def doubleValue = num.toDouble(self) + def floatValue = num.toFloat(self) + def longValue = num.toLong(self) + def intValue = num.toInt(self) + def byteValue = intValue.toByte + def shortValue = intValue.toShort /** Returns `'''this'''` if `'''this''' < that` or `that` otherwise. */ def min(that: T): T = num.min(self, that) @@ -41,7 +41,7 @@ trait ScalaNumberProxy[T] extends Any with ScalaNumericAnyConversions with Typed def signum = num.signum(self) } trait ScalaWholeNumberProxy[T] extends Any with ScalaNumberProxy[T] { - def isWhole() = true + def isWhole = true } trait IntegralProxy[T] extends Any with ScalaWholeNumberProxy[T] with RangedProxy[T] { protected implicit def num: Integral[T] @@ -55,7 +55,7 @@ trait IntegralProxy[T] extends Any with ScalaWholeNumberProxy[T] with RangedProx trait FractionalProxy[T] extends Any with ScalaNumberProxy[T] { protected implicit def num: Fractional[T] - def isWhole() = false + def isWhole = false } trait OrderedProxy[T] extends Any with Ordered[T] with Typed[T] { diff --git a/src/library/scala/sys/BooleanProp.scala b/src/library/scala/sys/BooleanProp.scala index b0008b41fd41..3a8cabb6199d 100644 --- a/src/library/scala/sys/BooleanProp.scala +++ b/src/library/scala/sys/BooleanProp.scala @@ -48,10 +48,14 @@ object BooleanProp { def set(newValue: String) = "" + value def setValue[T1 >: Boolean](newValue: T1): Boolean = value def get: String = "" + value - val clear, enable, disable, toggle = () def option = if (isSet) Some(value) else None //def or[T1 >: Boolean](alt: => T1): T1 = if (value) true else alt + def clear() = () + def enable() = () + def disable() = () + def toggle() = () + protected def zero = false } diff --git a/src/library/scala/sys/ShutdownHookThread.scala b/src/library/scala/sys/ShutdownHookThread.scala index ff19e3c1651c..73a75a410073 100644 --- a/src/library/scala/sys/ShutdownHookThread.scala +++ b/src/library/scala/sys/ShutdownHookThread.scala @@ -29,7 +29,7 @@ object ShutdownHookThread { * given code. */ def apply(body: => Unit): ShutdownHookThread = { - val t = new ShutdownHookThread(() => body, hookName) + val t = new ShutdownHookThread(() => body, hookName()) Runtime.getRuntime addShutdownHook t t } diff --git a/src/library/scala/util/matching/Regex.scala b/src/library/scala/util/matching/Regex.scala index d8fdfe5fedef..767d2441d5e1 100644 --- a/src/library/scala/util/matching/Regex.scala +++ b/src/library/scala/util/matching/Regex.scala @@ -393,7 +393,7 @@ class Regex private[matching](val pattern: Pattern, groupNames: String*) extends val matchIterator = findAllIn(source) new AbstractIterator[Match] { def hasNext = matchIterator.hasNext - def next: Match = { + def next(): Match = { matchIterator.next() new Match(matchIterator.source, matchIterator.matcher, matchIterator.groupNames).force } @@ -854,14 +854,14 @@ object Regex { /** Convert to an iterator that yields MatchData elements instead of Strings. */ def matchData: Iterator[Match] = new AbstractIterator[Match] { def hasNext = self.hasNext - def next = { self.next(); new Match(source, matcher, groupNames).force } + def next() = { self.next(); new Match(source, matcher, groupNames).force } } /** Convert to an iterator that yields MatchData elements instead of Strings and has replacement support. */ private[matching] def replacementData = new AbstractIterator[Match] with Replacement { def matcher = self.matcher def hasNext = self.hasNext - def next = { self.next(); new Match(source, matcher, groupNames).force } + def next() = { self.next(); new Match(source, matcher, groupNames).force } } } diff --git a/test/files/pos/t6600.scala b/test/files/pos/t6600.scala index 1e8137894cd6..c0cc6677d3db 100644 --- a/test/files/pos/t6600.scala +++ b/test/files/pos/t6600.scala @@ -1,8 +1,8 @@ final class Natural extends scala.math.ScalaNumber with scala.math.ScalaNumericConversions { - def intValue(): Int = 0 - def longValue(): Long = 0L - def floatValue(): Float = 0.0F - def doubleValue(): Double = 0.0D - def isWhole(): Boolean = false - def underlying() = this + def intValue: Int = 0 + def longValue: Long = 0L + def floatValue: Float = 0.0F + def doubleValue: Double = 0.0D + def isWhole: Boolean = false + def underlying = this } diff --git a/test/files/presentation/infix-completion.check b/test/files/presentation/infix-completion.check index d88a6606f2cd..76c711d5512e 100644 --- a/test/files/presentation/infix-completion.check +++ b/test/files/presentation/infix-completion.check @@ -7,7 +7,7 @@ retrieved 202 members [inaccessible] protected def num: Fractional[Double] [inaccessible] protected def ord: Ordering[Double] [inaccessible] protected def unifiedPrimitiveEquals(x: Any): Boolean -[inaccessible] protected def unifiedPrimitiveHashcode(): Int +[inaccessible] protected def unifiedPrimitiveHashcode: Int [inaccessible] protected[package lang] def clone(): Object [inaccessible] protected[package lang] def finalize(): Unit def !=(x: Byte): Boolean @@ -159,7 +159,7 @@ def toString(): String def unary_+: Int def unary_-: Int def unary_~: Int -def underlying(): AnyRef +def underlying: AnyRef def until(end: Int): scala.collection.immutable.Range def until(end: Int, step: Int): scala.collection.immutable.Range def until(end: Long): scala.collection.immutable.NumericRange.Exclusive[Long] @@ -188,7 +188,7 @@ override def isValidByte: Boolean override def isValidChar: Boolean override def isValidInt: Boolean override def isValidShort: Boolean -override def isWhole(): Boolean +override def isWhole: Boolean override def max(that: Double): Double override def max(that: Float): Float override def max(that: Int): Int diff --git a/test/files/presentation/infix-completion2.check b/test/files/presentation/infix-completion2.check index d88a6606f2cd..76c711d5512e 100644 --- a/test/files/presentation/infix-completion2.check +++ b/test/files/presentation/infix-completion2.check @@ -7,7 +7,7 @@ retrieved 202 members [inaccessible] protected def num: Fractional[Double] [inaccessible] protected def ord: Ordering[Double] [inaccessible] protected def unifiedPrimitiveEquals(x: Any): Boolean -[inaccessible] protected def unifiedPrimitiveHashcode(): Int +[inaccessible] protected def unifiedPrimitiveHashcode: Int [inaccessible] protected[package lang] def clone(): Object [inaccessible] protected[package lang] def finalize(): Unit def !=(x: Byte): Boolean @@ -159,7 +159,7 @@ def toString(): String def unary_+: Int def unary_-: Int def unary_~: Int -def underlying(): AnyRef +def underlying: AnyRef def until(end: Int): scala.collection.immutable.Range def until(end: Int, step: Int): scala.collection.immutable.Range def until(end: Long): scala.collection.immutable.NumericRange.Exclusive[Long] @@ -188,7 +188,7 @@ override def isValidByte: Boolean override def isValidChar: Boolean override def isValidInt: Boolean override def isValidShort: Boolean -override def isWhole(): Boolean +override def isWhole: Boolean override def max(that: Double): Double override def max(that: Float): Float override def max(that: Int): Int From cfeed4be44c46f259d03b976967988e131594160 Mon Sep 17 00:00:00 2001 From: Allan Renucci Date: Thu, 26 Jul 2018 17:30:07 +0200 Subject: [PATCH 090/143] Rename Numeric.Ops and Ordering.Ops to OrderingOps and NumericOps Class shadowing is forbidden in Dotty --- src/library/scala/math/Fractional.scala | 2 +- src/library/scala/math/Integral.scala | 2 +- src/library/scala/math/Numeric.scala | 6 +++--- src/library/scala/math/Ordering.scala | 6 +++--- test/files/pos/t4273.scala | 2 +- .../junit/scala/SerializationStabilityTest.scala | 16 ++++++++-------- 6 files changed, 17 insertions(+), 17 deletions(-) diff --git a/src/library/scala/math/Fractional.scala b/src/library/scala/math/Fractional.scala index ace5a6c48834..d7d8370a91ca 100644 --- a/src/library/scala/math/Fractional.scala +++ b/src/library/scala/math/Fractional.scala @@ -17,7 +17,7 @@ import scala.language.implicitConversions trait Fractional[T] extends Numeric[T] { def div(x: T, y: T): T - class FractionalOps(lhs: T) extends Ops(lhs) { + class FractionalOps(lhs: T) extends NumericOps(lhs) { def /(rhs: T) = div(lhs, rhs) } override implicit def mkNumericOps(lhs: T): FractionalOps = diff --git a/src/library/scala/math/Integral.scala b/src/library/scala/math/Integral.scala index ca94290249ac..a03d653d682b 100644 --- a/src/library/scala/math/Integral.scala +++ b/src/library/scala/math/Integral.scala @@ -18,7 +18,7 @@ trait Integral[T] extends Numeric[T] { def quot(x: T, y: T): T def rem(x: T, y: T): T - class IntegralOps(lhs: T) extends Ops(lhs) { + class IntegralOps(lhs: T) extends NumericOps(lhs) { def /(rhs: T) = quot(lhs, rhs) def %(rhs: T) = rem(lhs, rhs) def /%(rhs: T) = (quot(lhs, rhs), rem(lhs, rhs)) diff --git a/src/library/scala/math/Numeric.scala b/src/library/scala/math/Numeric.scala index 2c8e4cc3955b..fc4f6043b314 100644 --- a/src/library/scala/math/Numeric.scala +++ b/src/library/scala/math/Numeric.scala @@ -26,7 +26,7 @@ object Numeric { * def plus[T: Numeric](x: T, y: T) = x + y * }}} */ - implicit def infixNumericOps[T](x: T)(implicit num: Numeric[T]): Numeric[T]#Ops = new num.Ops(x) + implicit def infixNumericOps[T](x: T)(implicit num: Numeric[T]): Numeric[T]#NumericOps = new num.NumericOps(x) } object Implicits extends ExtraImplicits { } @@ -208,7 +208,7 @@ trait Numeric[T] extends Ordering[T] { else if (gt(x, zero)) 1 else 0 - class Ops(lhs: T) { + class NumericOps(lhs: T) { def +(rhs: T) = plus(lhs, rhs) def -(rhs: T) = minus(lhs, rhs) def *(rhs: T) = times(lhs, rhs) @@ -220,5 +220,5 @@ trait Numeric[T] extends Ordering[T] { def toFloat(): Float = Numeric.this.toFloat(lhs) def toDouble(): Double = Numeric.this.toDouble(lhs) } - implicit def mkNumericOps(lhs: T): Ops = new Ops(lhs) + implicit def mkNumericOps(lhs: T): NumericOps = new NumericOps(lhs) } diff --git a/src/library/scala/math/Ordering.scala b/src/library/scala/math/Ordering.scala index a3b8cff9f19d..ec43a9ef2e7b 100644 --- a/src/library/scala/math/Ordering.scala +++ b/src/library/scala/math/Ordering.scala @@ -173,7 +173,7 @@ trait Ordering[T] extends Comparator[T] with PartialOrdering[T] with Serializabl } /** This inner class defines comparison operators available for `T`. */ - class Ops(lhs: T) { + class OrderingOps(lhs: T) { def <(rhs: T) = lt(lhs, rhs) def <=(rhs: T) = lteq(lhs, rhs) def >(rhs: T) = gt(lhs, rhs) @@ -186,7 +186,7 @@ trait Ordering[T] extends Comparator[T] with PartialOrdering[T] with Serializabl /** This implicit method augments `T` with the comparison operators defined * in `scala.math.Ordering.Ops`. */ - implicit def mkOrderingOps(lhs: T): Ops = new Ops(lhs) + implicit def mkOrderingOps(lhs: T): OrderingOps = new OrderingOps(lhs) } trait LowPriorityOrderingImplicits { @@ -243,7 +243,7 @@ object Ordering extends LowPriorityOrderingImplicits { * def lessThan[T: Ordering](x: T, y: T) = x < y * }}} */ - implicit def infixOrderingOps[T](x: T)(implicit ord: Ordering[T]): Ordering[T]#Ops = new ord.Ops(x) + implicit def infixOrderingOps[T](x: T)(implicit ord: Ordering[T]): Ordering[T]#OrderingOps = new ord.OrderingOps(x) } /** An object containing implicits which are not in the default scope. */ diff --git a/test/files/pos/t4273.scala b/test/files/pos/t4273.scala index a4d37174ad0d..a8a2a9e2f099 100644 --- a/test/files/pos/t4273.scala +++ b/test/files/pos/t4273.scala @@ -1,5 +1,5 @@ class A { - implicit def compareComparables[T](x: T)(implicit ord: Ordering[T]) = new ord.Ops(x) + implicit def compareComparables[T](x: T)(implicit ord: Ordering[T]) = new ord.OrderingOps(x) class Bippy implicit val bippyOrdering = new Ordering[Bippy] { def compare(x: Bippy, y: Bippy) = util.Random.nextInt } diff --git a/test/junit/scala/SerializationStabilityTest.scala b/test/junit/scala/SerializationStabilityTest.scala index 16064cc5e26a..45eaf9f46bdc 100644 --- a/test/junit/scala/SerializationStabilityTest.scala +++ b/test/junit/scala/SerializationStabilityTest.scala @@ -86,7 +86,7 @@ object SerializationStability { } } - // Generated on 20180709-21:06:19 with Scala version 2.13.0-20180710-010238-d0a74ab) + // Generated on 20180727-09:45:07 with Scala version 2.13.0-20180726-161815-2cea3cb) def main(args: Array[String]): Unit = { overwrite.foreach(updateComment) def g = Thread.currentThread.getStackTrace @@ -183,7 +183,7 @@ object SerializationStability { // TODO scala/bug#8576 Uninitialized field: IndexedSeqLike.scala: 56 // check(g)(immutable.Stream(1, 2, 3))( "rO0ABXNyACZzY2FsYS5jb2xsZWN0aW9uLmltbXV0YWJsZS5TdHJlYW0kQ29uc/ekjBXM3TlFAgADTAACaGR0ABJMamF2YS9sYW5nL09iamVjdDtMAAV0bEdlbnQAEUxzY2FsYS9GdW5jdGlvbjA7TAAFdGxWYWx0ACNMc2NhbGEvY29sbGVjdGlvbi9pbW11dGFibGUvU3RyZWFtO3hyACFzY2FsYS5jb2xsZWN0aW9uLmltbXV0YWJsZS5TdHJlYW0552RDntM42gIAAHhwc3IAEWphdmEubGFuZy5JbnRlZ2VyEuKgpPeBhzgCAAFJAAV2YWx1ZXhyABBqYXZhLmxhbmcuTnVtYmVyhqyVHQuU4IsCAAB4cAAAAAFzcgAtc2NhbGEuY29sbGVjdGlvbi5JdGVyYXRvciQkYW5vbmZ1biR0b1N0cmVhbSQxRWR4We0SX0UCAAFMAAYkb3V0ZXJ0ABtMc2NhbGEvY29sbGVjdGlvbi9JdGVyYXRvcjt4cHNyAChzY2FsYS5jb2xsZWN0aW9uLkluZGV4ZWRTZXFMaWtlJEVsZW1lbnRzGF+1cBwmcx0CAANJAANlbmRJAAVpbmRleEwABiRvdXRlcnQAIUxzY2FsYS9jb2xsZWN0aW9uL0luZGV4ZWRTZXFMaWtlO3hwAAAAAwAAAAFzcgArc2NhbGEuY29sbGVjdGlvbi5tdXRhYmxlLldyYXBwZWRBcnJheSRvZkludMmRLBcI15VjAgABWwAFYXJyYXl0AAJbSXhwdXIAAltJTbpgJnbqsqUCAAB4cAAAAAMAAAABAAAAAgAAAANw") - check(g)(immutable.TreeSet[Int]())( "rO0ABXNyADJzY2FsYS5jb2xsZWN0aW9uLmdlbmVyaWMuRGVmYXVsdFNlcmlhbGl6YXRpb25Qcm94eQAAAAAAAAADAwABTAAHZmFjdG9yeXQAGkxzY2FsYS9jb2xsZWN0aW9uL0ZhY3Rvcnk7eHBzcgAyc2NhbGEuY29sbGVjdGlvbi5FdmlkZW5jZUl0ZXJhYmxlRmFjdG9yeSRUb0ZhY3RvcnkAAAAAAAAAAwIAAkwAC2V2aWRlbmNlJDE1dAASTGphdmEvbGFuZy9PYmplY3Q7TAAHZmFjdG9yeXQAKkxzY2FsYS9jb2xsZWN0aW9uL0V2aWRlbmNlSXRlcmFibGVGYWN0b3J5O3hwc3IAGHNjYWxhLm1hdGguT3JkZXJpbmckSW50JLM5TfdXrEG2AgAAeHBzcgAjc2NhbGEuY29sbGVjdGlvbi5pbW11dGFibGUuVHJlZVNldCQAAAAAAAAAAwIAAHhwdwT/////c3IAJnNjYWxhLmNvbGxlY3Rpb24uZ2VuZXJpYy5TZXJpYWxpemVFbmQkAAAAAAAAAAMCAAB4cHg=") + check(g)(immutable.TreeSet[Int]())( "rO0ABXNyADJzY2FsYS5jb2xsZWN0aW9uLmdlbmVyaWMuRGVmYXVsdFNlcmlhbGl6YXRpb25Qcm94eQAAAAAAAAADAwABTAAHZmFjdG9yeXQAGkxzY2FsYS9jb2xsZWN0aW9uL0ZhY3Rvcnk7eHBzcgAyc2NhbGEuY29sbGVjdGlvbi5FdmlkZW5jZUl0ZXJhYmxlRmFjdG9yeSRUb0ZhY3RvcnkAAAAAAAAAAwIAAkwAC2V2aWRlbmNlJDE1dAASTGphdmEvbGFuZy9PYmplY3Q7TAAHZmFjdG9yeXQAKkxzY2FsYS9jb2xsZWN0aW9uL0V2aWRlbmNlSXRlcmFibGVGYWN0b3J5O3hwc3IAGHNjYWxhLm1hdGguT3JkZXJpbmckSW50JFKsUqd1equjAgAAeHBzcgAjc2NhbGEuY29sbGVjdGlvbi5pbW11dGFibGUuVHJlZVNldCQAAAAAAAAAAwIAAHhwdwT/////c3IAJnNjYWxhLmNvbGxlY3Rpb24uZ2VuZXJpYy5TZXJpYWxpemVFbmQkAAAAAAAAAAMCAAB4cHg=") // TODO scala/bug#8576 unstable under -Xcheckinit // check(g)(immutable.TreeSet(1, 2, 3))( "rO0ABXNyACJzY2FsYS5jb2xsZWN0aW9uLmltbXV0YWJsZS5UcmVlU2V0sRdVIDjbWAsCAAJMAAhvcmRlcmluZ3QAFUxzY2FsYS9tYXRoL09yZGVyaW5nO0wABHRyZWV0AC5Mc2NhbGEvY29sbGVjdGlvbi9pbW11dGFibGUvUmVkQmxhY2tUcmVlJFRyZWU7eHBzcgAYc2NhbGEubWF0aC5PcmRlcmluZyRJbnQkC4BMdr1Z51wCAAB4cHNyADFzY2FsYS5jb2xsZWN0aW9uLmltbXV0YWJsZS5SZWRCbGFja1RyZWUkQmxhY2tUcmVlzRxnCKenVAECAAB4cgAsc2NhbGEuY29sbGVjdGlvbi5pbW11dGFibGUuUmVkQmxhY2tUcmVlJFRyZWVrqCSyHJbsMgIABUkABWNvdW50TAADa2V5dAASTGphdmEvbGFuZy9PYmplY3Q7TAAEbGVmdHEAfgACTAAFcmlnaHRxAH4AAkwABXZhbHVlcQB+AAh4cAAAAANzcgARamF2YS5sYW5nLkludGVnZXIS4qCk94GHOAIAAUkABXZhbHVleHIAEGphdmEubGFuZy5OdW1iZXKGrJUdC5TgiwIAAHhwAAAAAnNxAH4ABgAAAAFzcQB+AAoAAAABcHBzcgAXc2NhbGEucnVudGltZS5Cb3hlZFVuaXR0pn1HHezLmgIAAHhwc3EAfgAGAAAAAXNxAH4ACgAAAANwcHEAfgAQcQB+ABA=") @@ -199,12 +199,12 @@ object SerializationStability { check(g)(mutable.HashMap())( "rO0ABXNyADJzY2FsYS5jb2xsZWN0aW9uLmdlbmVyaWMuRGVmYXVsdFNlcmlhbGl6YXRpb25Qcm94eQAAAAAAAAADAwABTAAHZmFjdG9yeXQAGkxzY2FsYS9jb2xsZWN0aW9uL0ZhY3Rvcnk7eHBzcgAlc2NhbGEuY29sbGVjdGlvbi5NYXBGYWN0b3J5JFRvRmFjdG9yeQAAAAAAAAADAgABTAAHZmFjdG9yeXQAHUxzY2FsYS9jb2xsZWN0aW9uL01hcEZhY3Rvcnk7eHBzcgAhc2NhbGEuY29sbGVjdGlvbi5tdXRhYmxlLkhhc2hNYXAkAAAAAAAAAAMCAAB4cHcE/////3NyACZzY2FsYS5jb2xsZWN0aW9uLmdlbmVyaWMuU2VyaWFsaXplRW5kJAAAAAAAAAADAgAAeHB4") check(g)(mutable.HashMap(1 -> 1))( "rO0ABXNyADJzY2FsYS5jb2xsZWN0aW9uLmdlbmVyaWMuRGVmYXVsdFNlcmlhbGl6YXRpb25Qcm94eQAAAAAAAAADAwABTAAHZmFjdG9yeXQAGkxzY2FsYS9jb2xsZWN0aW9uL0ZhY3Rvcnk7eHBzcgAlc2NhbGEuY29sbGVjdGlvbi5NYXBGYWN0b3J5JFRvRmFjdG9yeQAAAAAAAAADAgABTAAHZmFjdG9yeXQAHUxzY2FsYS9jb2xsZWN0aW9uL01hcEZhY3Rvcnk7eHBzcgAhc2NhbGEuY29sbGVjdGlvbi5tdXRhYmxlLkhhc2hNYXAkAAAAAAAAAAMCAAB4cHcE/////3NyAAxzY2FsYS5UdXBsZTIulGZ9W5L59QIAAkwAAl8xdAASTGphdmEvbGFuZy9PYmplY3Q7TAACXzJxAH4ACXhwc3IAEWphdmEubGFuZy5JbnRlZ2VyEuKgpPeBhzgCAAFJAAV2YWx1ZXhyABBqYXZhLmxhbmcuTnVtYmVyhqyVHQuU4IsCAAB4cAAAAAFxAH4ADXNyACZzY2FsYS5jb2xsZWN0aW9uLmdlbmVyaWMuU2VyaWFsaXplRW5kJAAAAAAAAAADAgAAeHB4") check(g)(mutable.HashSet(1, 2, 3))( "rO0ABXNyADJzY2FsYS5jb2xsZWN0aW9uLmdlbmVyaWMuRGVmYXVsdFNlcmlhbGl6YXRpb25Qcm94eQAAAAAAAAADAwABTAAHZmFjdG9yeXQAGkxzY2FsYS9jb2xsZWN0aW9uL0ZhY3Rvcnk7eHBzcgAqc2NhbGEuY29sbGVjdGlvbi5JdGVyYWJsZUZhY3RvcnkkVG9GYWN0b3J5AAAAAAAAAAMCAAFMAAdmYWN0b3J5dAAiTHNjYWxhL2NvbGxlY3Rpb24vSXRlcmFibGVGYWN0b3J5O3hwc3IAIXNjYWxhLmNvbGxlY3Rpb24ubXV0YWJsZS5IYXNoU2V0JAAAAAAAAAADAgAAeHB3BAAAAANzcgARamF2YS5sYW5nLkludGVnZXIS4qCk94GHOAIAAUkABXZhbHVleHIAEGphdmEubGFuZy5OdW1iZXKGrJUdC5TgiwIAAHhwAAAAAXNxAH4ACAAAAAJzcQB+AAgAAAADeA==") - check(g)(mutable.TreeMap[Int, Int]())( "rO0ABXNyADJzY2FsYS5jb2xsZWN0aW9uLmdlbmVyaWMuRGVmYXVsdFNlcmlhbGl6YXRpb25Qcm94eQAAAAAAAAADAwABTAAHZmFjdG9yeXQAGkxzY2FsYS9jb2xsZWN0aW9uL0ZhY3Rvcnk7eHBzcgArc2NhbGEuY29sbGVjdGlvbi5Tb3J0ZWRNYXBGYWN0b3J5JFRvRmFjdG9yeQAAAAAAAAADAgACTAALZXZpZGVuY2UkNDF0ABVMc2NhbGEvbWF0aC9PcmRlcmluZztMAAdmYWN0b3J5dAAjTHNjYWxhL2NvbGxlY3Rpb24vU29ydGVkTWFwRmFjdG9yeTt4cHNyABhzY2FsYS5tYXRoLk9yZGVyaW5nJEludCSzOU33V6xBtgIAAHhwc3IAIXNjYWxhLmNvbGxlY3Rpb24ubXV0YWJsZS5UcmVlTWFwJAAAAAAAAAADAgAAeHB3BP////9zcgAmc2NhbGEuY29sbGVjdGlvbi5nZW5lcmljLlNlcmlhbGl6ZUVuZCQAAAAAAAAAAwIAAHhweA==") - check(g)(mutable.TreeMap(1 -> 1, 3 -> 6))( "rO0ABXNyADJzY2FsYS5jb2xsZWN0aW9uLmdlbmVyaWMuRGVmYXVsdFNlcmlhbGl6YXRpb25Qcm94eQAAAAAAAAADAwABTAAHZmFjdG9yeXQAGkxzY2FsYS9jb2xsZWN0aW9uL0ZhY3Rvcnk7eHBzcgArc2NhbGEuY29sbGVjdGlvbi5Tb3J0ZWRNYXBGYWN0b3J5JFRvRmFjdG9yeQAAAAAAAAADAgACTAALZXZpZGVuY2UkNDF0ABVMc2NhbGEvbWF0aC9PcmRlcmluZztMAAdmYWN0b3J5dAAjTHNjYWxhL2NvbGxlY3Rpb24vU29ydGVkTWFwRmFjdG9yeTt4cHNyABhzY2FsYS5tYXRoLk9yZGVyaW5nJEludCSzOU33V6xBtgIAAHhwc3IAIXNjYWxhLmNvbGxlY3Rpb24ubXV0YWJsZS5UcmVlTWFwJAAAAAAAAAADAgAAeHB3BP////9zcgAMc2NhbGEuVHVwbGUyLpRmfVuS+fUCAAJMAAJfMXQAEkxqYXZhL2xhbmcvT2JqZWN0O0wAAl8ycQB+AAx4cHNyABFqYXZhLmxhbmcuSW50ZWdlchLioKT3gYc4AgABSQAFdmFsdWV4cgAQamF2YS5sYW5nLk51bWJlcoaslR0LlOCLAgAAeHAAAAABcQB+ABBzcQB+AAtzcQB+AA4AAAADc3EAfgAOAAAABnNyACZzY2FsYS5jb2xsZWN0aW9uLmdlbmVyaWMuU2VyaWFsaXplRW5kJAAAAAAAAAADAgAAeHB4") - check(g)(mutable.TreeMap(1 -> 1, 3 -> 6).range(1, 2))( "rO0ABXNyADJzY2FsYS5jb2xsZWN0aW9uLmdlbmVyaWMuRGVmYXVsdFNlcmlhbGl6YXRpb25Qcm94eQAAAAAAAAADAwABTAAHZmFjdG9yeXQAGkxzY2FsYS9jb2xsZWN0aW9uL0ZhY3Rvcnk7eHBzcgArc2NhbGEuY29sbGVjdGlvbi5Tb3J0ZWRNYXBGYWN0b3J5JFRvRmFjdG9yeQAAAAAAAAADAgACTAALZXZpZGVuY2UkNDF0ABVMc2NhbGEvbWF0aC9PcmRlcmluZztMAAdmYWN0b3J5dAAjTHNjYWxhL2NvbGxlY3Rpb24vU29ydGVkTWFwRmFjdG9yeTt4cHNyABhzY2FsYS5tYXRoLk9yZGVyaW5nJEludCSzOU33V6xBtgIAAHhwc3IAIXNjYWxhLmNvbGxlY3Rpb24ubXV0YWJsZS5UcmVlTWFwJAAAAAAAAAADAgAAeHB3BP////9zcgAMc2NhbGEuVHVwbGUyLpRmfVuS+fUCAAJMAAJfMXQAEkxqYXZhL2xhbmcvT2JqZWN0O0wAAl8ycQB+AAx4cHNyABFqYXZhLmxhbmcuSW50ZWdlchLioKT3gYc4AgABSQAFdmFsdWV4cgAQamF2YS5sYW5nLk51bWJlcoaslR0LlOCLAgAAeHAAAAABcQB+ABBzcgAmc2NhbGEuY29sbGVjdGlvbi5nZW5lcmljLlNlcmlhbGl6ZUVuZCQAAAAAAAAAAwIAAHhweA==") - check(g)(mutable.TreeSet[Int]())( "rO0ABXNyADJzY2FsYS5jb2xsZWN0aW9uLmdlbmVyaWMuRGVmYXVsdFNlcmlhbGl6YXRpb25Qcm94eQAAAAAAAAADAwABTAAHZmFjdG9yeXQAGkxzY2FsYS9jb2xsZWN0aW9uL0ZhY3Rvcnk7eHBzcgAyc2NhbGEuY29sbGVjdGlvbi5FdmlkZW5jZUl0ZXJhYmxlRmFjdG9yeSRUb0ZhY3RvcnkAAAAAAAAAAwIAAkwAC2V2aWRlbmNlJDE1dAASTGphdmEvbGFuZy9PYmplY3Q7TAAHZmFjdG9yeXQAKkxzY2FsYS9jb2xsZWN0aW9uL0V2aWRlbmNlSXRlcmFibGVGYWN0b3J5O3hwc3IAGHNjYWxhLm1hdGguT3JkZXJpbmckSW50JLM5TfdXrEG2AgAAeHBzcgAhc2NhbGEuY29sbGVjdGlvbi5tdXRhYmxlLlRyZWVTZXQkAAAAAAAAAAMCAAB4cHcE/////3NyACZzY2FsYS5jb2xsZWN0aW9uLmdlbmVyaWMuU2VyaWFsaXplRW5kJAAAAAAAAAADAgAAeHB4") - check(g)(mutable.TreeSet(1, 3))( "rO0ABXNyADJzY2FsYS5jb2xsZWN0aW9uLmdlbmVyaWMuRGVmYXVsdFNlcmlhbGl6YXRpb25Qcm94eQAAAAAAAAADAwABTAAHZmFjdG9yeXQAGkxzY2FsYS9jb2xsZWN0aW9uL0ZhY3Rvcnk7eHBzcgAyc2NhbGEuY29sbGVjdGlvbi5FdmlkZW5jZUl0ZXJhYmxlRmFjdG9yeSRUb0ZhY3RvcnkAAAAAAAAAAwIAAkwAC2V2aWRlbmNlJDE1dAASTGphdmEvbGFuZy9PYmplY3Q7TAAHZmFjdG9yeXQAKkxzY2FsYS9jb2xsZWN0aW9uL0V2aWRlbmNlSXRlcmFibGVGYWN0b3J5O3hwc3IAGHNjYWxhLm1hdGguT3JkZXJpbmckSW50JLM5TfdXrEG2AgAAeHBzcgAhc2NhbGEuY29sbGVjdGlvbi5tdXRhYmxlLlRyZWVTZXQkAAAAAAAAAAMCAAB4cHcE/////3NyABFqYXZhLmxhbmcuSW50ZWdlchLioKT3gYc4AgABSQAFdmFsdWV4cgAQamF2YS5sYW5nLk51bWJlcoaslR0LlOCLAgAAeHAAAAABc3EAfgALAAAAA3NyACZzY2FsYS5jb2xsZWN0aW9uLmdlbmVyaWMuU2VyaWFsaXplRW5kJAAAAAAAAAADAgAAeHB4") - check(g)(mutable.TreeSet(1, 3).range(1, 2))( "rO0ABXNyADJzY2FsYS5jb2xsZWN0aW9uLmdlbmVyaWMuRGVmYXVsdFNlcmlhbGl6YXRpb25Qcm94eQAAAAAAAAADAwABTAAHZmFjdG9yeXQAGkxzY2FsYS9jb2xsZWN0aW9uL0ZhY3Rvcnk7eHBzcgAyc2NhbGEuY29sbGVjdGlvbi5FdmlkZW5jZUl0ZXJhYmxlRmFjdG9yeSRUb0ZhY3RvcnkAAAAAAAAAAwIAAkwAC2V2aWRlbmNlJDE1dAASTGphdmEvbGFuZy9PYmplY3Q7TAAHZmFjdG9yeXQAKkxzY2FsYS9jb2xsZWN0aW9uL0V2aWRlbmNlSXRlcmFibGVGYWN0b3J5O3hwc3IAGHNjYWxhLm1hdGguT3JkZXJpbmckSW50JLM5TfdXrEG2AgAAeHBzcgAhc2NhbGEuY29sbGVjdGlvbi5tdXRhYmxlLlRyZWVTZXQkAAAAAAAAAAMCAAB4cHcE/////3NyABFqYXZhLmxhbmcuSW50ZWdlchLioKT3gYc4AgABSQAFdmFsdWV4cgAQamF2YS5sYW5nLk51bWJlcoaslR0LlOCLAgAAeHAAAAABc3IAJnNjYWxhLmNvbGxlY3Rpb24uZ2VuZXJpYy5TZXJpYWxpemVFbmQkAAAAAAAAAAMCAAB4cHg=") + check(g)(mutable.TreeMap[Int, Int]())( "rO0ABXNyADJzY2FsYS5jb2xsZWN0aW9uLmdlbmVyaWMuRGVmYXVsdFNlcmlhbGl6YXRpb25Qcm94eQAAAAAAAAADAwABTAAHZmFjdG9yeXQAGkxzY2FsYS9jb2xsZWN0aW9uL0ZhY3Rvcnk7eHBzcgArc2NhbGEuY29sbGVjdGlvbi5Tb3J0ZWRNYXBGYWN0b3J5JFRvRmFjdG9yeQAAAAAAAAADAgACTAALZXZpZGVuY2UkNDF0ABVMc2NhbGEvbWF0aC9PcmRlcmluZztMAAdmYWN0b3J5dAAjTHNjYWxhL2NvbGxlY3Rpb24vU29ydGVkTWFwRmFjdG9yeTt4cHNyABhzY2FsYS5tYXRoLk9yZGVyaW5nJEludCRSrFKndXqrowIAAHhwc3IAIXNjYWxhLmNvbGxlY3Rpb24ubXV0YWJsZS5UcmVlTWFwJAAAAAAAAAADAgAAeHB3BP////9zcgAmc2NhbGEuY29sbGVjdGlvbi5nZW5lcmljLlNlcmlhbGl6ZUVuZCQAAAAAAAAAAwIAAHhweA==") + check(g)(mutable.TreeMap(1 -> 1, 3 -> 6))( "rO0ABXNyADJzY2FsYS5jb2xsZWN0aW9uLmdlbmVyaWMuRGVmYXVsdFNlcmlhbGl6YXRpb25Qcm94eQAAAAAAAAADAwABTAAHZmFjdG9yeXQAGkxzY2FsYS9jb2xsZWN0aW9uL0ZhY3Rvcnk7eHBzcgArc2NhbGEuY29sbGVjdGlvbi5Tb3J0ZWRNYXBGYWN0b3J5JFRvRmFjdG9yeQAAAAAAAAADAgACTAALZXZpZGVuY2UkNDF0ABVMc2NhbGEvbWF0aC9PcmRlcmluZztMAAdmYWN0b3J5dAAjTHNjYWxhL2NvbGxlY3Rpb24vU29ydGVkTWFwRmFjdG9yeTt4cHNyABhzY2FsYS5tYXRoLk9yZGVyaW5nJEludCRSrFKndXqrowIAAHhwc3IAIXNjYWxhLmNvbGxlY3Rpb24ubXV0YWJsZS5UcmVlTWFwJAAAAAAAAAADAgAAeHB3BP////9zcgAMc2NhbGEuVHVwbGUyLpRmfVuS+fUCAAJMAAJfMXQAEkxqYXZhL2xhbmcvT2JqZWN0O0wAAl8ycQB+AAx4cHNyABFqYXZhLmxhbmcuSW50ZWdlchLioKT3gYc4AgABSQAFdmFsdWV4cgAQamF2YS5sYW5nLk51bWJlcoaslR0LlOCLAgAAeHAAAAABcQB+ABBzcQB+AAtzcQB+AA4AAAADc3EAfgAOAAAABnNyACZzY2FsYS5jb2xsZWN0aW9uLmdlbmVyaWMuU2VyaWFsaXplRW5kJAAAAAAAAAADAgAAeHB4") + check(g)(mutable.TreeMap(1 -> 1, 3 -> 6).range(1, 2))( "rO0ABXNyADJzY2FsYS5jb2xsZWN0aW9uLmdlbmVyaWMuRGVmYXVsdFNlcmlhbGl6YXRpb25Qcm94eQAAAAAAAAADAwABTAAHZmFjdG9yeXQAGkxzY2FsYS9jb2xsZWN0aW9uL0ZhY3Rvcnk7eHBzcgArc2NhbGEuY29sbGVjdGlvbi5Tb3J0ZWRNYXBGYWN0b3J5JFRvRmFjdG9yeQAAAAAAAAADAgACTAALZXZpZGVuY2UkNDF0ABVMc2NhbGEvbWF0aC9PcmRlcmluZztMAAdmYWN0b3J5dAAjTHNjYWxhL2NvbGxlY3Rpb24vU29ydGVkTWFwRmFjdG9yeTt4cHNyABhzY2FsYS5tYXRoLk9yZGVyaW5nJEludCRSrFKndXqrowIAAHhwc3IAIXNjYWxhLmNvbGxlY3Rpb24ubXV0YWJsZS5UcmVlTWFwJAAAAAAAAAADAgAAeHB3BP////9zcgAMc2NhbGEuVHVwbGUyLpRmfVuS+fUCAAJMAAJfMXQAEkxqYXZhL2xhbmcvT2JqZWN0O0wAAl8ycQB+AAx4cHNyABFqYXZhLmxhbmcuSW50ZWdlchLioKT3gYc4AgABSQAFdmFsdWV4cgAQamF2YS5sYW5nLk51bWJlcoaslR0LlOCLAgAAeHAAAAABcQB+ABBzcgAmc2NhbGEuY29sbGVjdGlvbi5nZW5lcmljLlNlcmlhbGl6ZUVuZCQAAAAAAAAAAwIAAHhweA==") + check(g)(mutable.TreeSet[Int]())( "rO0ABXNyADJzY2FsYS5jb2xsZWN0aW9uLmdlbmVyaWMuRGVmYXVsdFNlcmlhbGl6YXRpb25Qcm94eQAAAAAAAAADAwABTAAHZmFjdG9yeXQAGkxzY2FsYS9jb2xsZWN0aW9uL0ZhY3Rvcnk7eHBzcgAyc2NhbGEuY29sbGVjdGlvbi5FdmlkZW5jZUl0ZXJhYmxlRmFjdG9yeSRUb0ZhY3RvcnkAAAAAAAAAAwIAAkwAC2V2aWRlbmNlJDE1dAASTGphdmEvbGFuZy9PYmplY3Q7TAAHZmFjdG9yeXQAKkxzY2FsYS9jb2xsZWN0aW9uL0V2aWRlbmNlSXRlcmFibGVGYWN0b3J5O3hwc3IAGHNjYWxhLm1hdGguT3JkZXJpbmckSW50JFKsUqd1equjAgAAeHBzcgAhc2NhbGEuY29sbGVjdGlvbi5tdXRhYmxlLlRyZWVTZXQkAAAAAAAAAAMCAAB4cHcE/////3NyACZzY2FsYS5jb2xsZWN0aW9uLmdlbmVyaWMuU2VyaWFsaXplRW5kJAAAAAAAAAADAgAAeHB4") + check(g)(mutable.TreeSet(1, 3))( "rO0ABXNyADJzY2FsYS5jb2xsZWN0aW9uLmdlbmVyaWMuRGVmYXVsdFNlcmlhbGl6YXRpb25Qcm94eQAAAAAAAAADAwABTAAHZmFjdG9yeXQAGkxzY2FsYS9jb2xsZWN0aW9uL0ZhY3Rvcnk7eHBzcgAyc2NhbGEuY29sbGVjdGlvbi5FdmlkZW5jZUl0ZXJhYmxlRmFjdG9yeSRUb0ZhY3RvcnkAAAAAAAAAAwIAAkwAC2V2aWRlbmNlJDE1dAASTGphdmEvbGFuZy9PYmplY3Q7TAAHZmFjdG9yeXQAKkxzY2FsYS9jb2xsZWN0aW9uL0V2aWRlbmNlSXRlcmFibGVGYWN0b3J5O3hwc3IAGHNjYWxhLm1hdGguT3JkZXJpbmckSW50JFKsUqd1equjAgAAeHBzcgAhc2NhbGEuY29sbGVjdGlvbi5tdXRhYmxlLlRyZWVTZXQkAAAAAAAAAAMCAAB4cHcE/////3NyABFqYXZhLmxhbmcuSW50ZWdlchLioKT3gYc4AgABSQAFdmFsdWV4cgAQamF2YS5sYW5nLk51bWJlcoaslR0LlOCLAgAAeHAAAAABc3EAfgALAAAAA3NyACZzY2FsYS5jb2xsZWN0aW9uLmdlbmVyaWMuU2VyaWFsaXplRW5kJAAAAAAAAAADAgAAeHB4") + check(g)(mutable.TreeSet(1, 3).range(1, 2))( "rO0ABXNyADJzY2FsYS5jb2xsZWN0aW9uLmdlbmVyaWMuRGVmYXVsdFNlcmlhbGl6YXRpb25Qcm94eQAAAAAAAAADAwABTAAHZmFjdG9yeXQAGkxzY2FsYS9jb2xsZWN0aW9uL0ZhY3Rvcnk7eHBzcgAyc2NhbGEuY29sbGVjdGlvbi5FdmlkZW5jZUl0ZXJhYmxlRmFjdG9yeSRUb0ZhY3RvcnkAAAAAAAAAAwIAAkwAC2V2aWRlbmNlJDE1dAASTGphdmEvbGFuZy9PYmplY3Q7TAAHZmFjdG9yeXQAKkxzY2FsYS9jb2xsZWN0aW9uL0V2aWRlbmNlSXRlcmFibGVGYWN0b3J5O3hwc3IAGHNjYWxhLm1hdGguT3JkZXJpbmckSW50JFKsUqd1equjAgAAeHBzcgAhc2NhbGEuY29sbGVjdGlvbi5tdXRhYmxlLlRyZWVTZXQkAAAAAAAAAAMCAAB4cHcE/////3NyABFqYXZhLmxhbmcuSW50ZWdlchLioKT3gYc4AgABSQAFdmFsdWV4cgAQamF2YS5sYW5nLk51bWJlcoaslR0LlOCLAgAAeHAAAAABc3IAJnNjYWxhLmNvbGxlY3Rpb24uZ2VuZXJpYy5TZXJpYWxpemVFbmQkAAAAAAAAAAMCAAB4cHg=") // TODO scala/bug#8576 Uninitialized field under -Xcheckinit // check(g)(new mutable.History())( "rO0ABXNyACBzY2FsYS5jb2xsZWN0aW9uLm11dGFibGUuSGlzdG9yeUhuXxDIFJrsAgACSQAKbWF4SGlzdG9yeUwAA2xvZ3QAIExzY2FsYS9jb2xsZWN0aW9uL211dGFibGUvUXVldWU7eHAAAAPoc3IAHnNjYWxhLmNvbGxlY3Rpb24ubXV0YWJsZS5RdWV1ZbjMURVfOuHHAgAAeHIAJHNjYWxhLmNvbGxlY3Rpb24ubXV0YWJsZS5NdXRhYmxlTGlzdFJpnjJ+gFbAAgADSQADbGVuTAAGZmlyc3QwdAAlTHNjYWxhL2NvbGxlY3Rpb24vbXV0YWJsZS9MaW5rZWRMaXN0O0wABWxhc3QwcQB+AAV4cAAAAABzcgAjc2NhbGEuY29sbGVjdGlvbi5tdXRhYmxlLkxpbmtlZExpc3Sak+nGCZHaUQIAAkwABGVsZW10ABJMamF2YS9sYW5nL09iamVjdDtMAARuZXh0dAAeTHNjYWxhL2NvbGxlY3Rpb24vbXV0YWJsZS9TZXE7eHBwcQB+AApxAH4ACg==") check(g)(mutable.LinkedHashMap(1 -> 2))( "rO0ABXNyADJzY2FsYS5jb2xsZWN0aW9uLmdlbmVyaWMuRGVmYXVsdFNlcmlhbGl6YXRpb25Qcm94eQAAAAAAAAADAwABTAAHZmFjdG9yeXQAGkxzY2FsYS9jb2xsZWN0aW9uL0ZhY3Rvcnk7eHBzcgAlc2NhbGEuY29sbGVjdGlvbi5NYXBGYWN0b3J5JFRvRmFjdG9yeQAAAAAAAAADAgABTAAHZmFjdG9yeXQAHUxzY2FsYS9jb2xsZWN0aW9uL01hcEZhY3Rvcnk7eHBzcgAnc2NhbGEuY29sbGVjdGlvbi5tdXRhYmxlLkxpbmtlZEhhc2hNYXAkAAAAAAAAAAMCAAB4cHcE/////3NyAAxzY2FsYS5UdXBsZTIulGZ9W5L59QIAAkwAAl8xdAASTGphdmEvbGFuZy9PYmplY3Q7TAACXzJxAH4ACXhwc3IAEWphdmEubGFuZy5JbnRlZ2VyEuKgpPeBhzgCAAFJAAV2YWx1ZXhyABBqYXZhLmxhbmcuTnVtYmVyhqyVHQuU4IsCAAB4cAAAAAFzcQB+AAsAAAACc3IAJnNjYWxhLmNvbGxlY3Rpb24uZ2VuZXJpYy5TZXJpYWxpemVFbmQkAAAAAAAAAAMCAAB4cHg=") From d7b132b94acaefef6bfe927527e17977a72f1b1b Mon Sep 17 00:00:00 2001 From: Allan Renucci Date: Fri, 27 Jul 2018 14:48:24 +0200 Subject: [PATCH 091/143] Compute knownSize only once This prevent possible exponential computations of knownSize --- src/library/scala/collection/View.scala | 45 ++++++++++++++++++------- 1 file changed, 33 insertions(+), 12 deletions(-) diff --git a/src/library/scala/collection/View.scala b/src/library/scala/collection/View.scala index d7d18b71efde..eea19bd64361 100644 --- a/src/library/scala/collection/View.scala +++ b/src/library/scala/collection/View.scala @@ -129,7 +129,7 @@ object View extends IterableFactory[View] { /** An `IterableOps` whose collection type and collection type constructor are unknown */ type SomeIterableOps[A] = IterableOps[A, AnyConstr, _] - + /** A view that filters an underlying collection. */ @SerialVersionUID(3L) class Filter[A](val underlying: SomeIterableOps[A], val p: A => Boolean, val isFlipped: Boolean) extends AbstractView[A] { @@ -176,8 +176,10 @@ object View extends IterableFactory[View] { class Drop[A](underlying: SomeIterableOps[A], n: Int) extends AbstractView[A] { def iterator = underlying.iterator.drop(n) protected val normN = n max 0 - override def knownSize = - if (underlying.knownSize >= 0) (underlying.knownSize - normN) max 0 else -1 + override def knownSize = { + val size = underlying.knownSize + if (size >= 0) (size - normN) max 0 else -1 + } } @SerialVersionUID(3L) @@ -190,8 +192,10 @@ object View extends IterableFactory[View] { class Take[+A](underlying: SomeIterableOps[A], n: Int) extends AbstractView[A] { def iterator = underlying.iterator.take(n) protected val normN = n max 0 - override def knownSize = - if (underlying.knownSize >= 0) underlying.knownSize min normN else -1 + override def knownSize = { + val size = underlying.knownSize + if (size >= 0) size min normN else -1 + } } @SerialVersionUID(3L) @@ -202,8 +206,10 @@ object View extends IterableFactory[View] { @SerialVersionUID(3L) class ScanLeft[+A, +B](underlying: SomeIterableOps[A], z: B, op: (B, A) => B) extends AbstractView[B] { def iterator: Iterator[B] = underlying.iterator.scanLeft(z)(op) - override def knownSize: Int = - if (underlying.knownSize >= 0) underlying.knownSize + 1 else -1 + override def knownSize: Int = { + val size = underlying.knownSize + if (size >= 0) size + 1 else -1 + } } /** A view that maps elements of the underlying collection. */ @@ -225,9 +231,15 @@ object View extends IterableFactory[View] { @SerialVersionUID(3L) class Concat[A](prefix: SomeIterableOps[A], suffix: SomeIterableOps[A]) extends AbstractView[A] { def iterator = prefix.iterator ++ suffix.iterator - override def knownSize = - if (prefix.knownSize >= 0 && suffix.knownSize >= 0) prefix.knownSize + suffix.knownSize + override def knownSize = { + val prefixSize = prefix.knownSize + if (prefixSize >= 0) { + val suffixSize = suffix.knownSize + if (suffixSize >= 0) prefixSize + suffixSize + else -1 + } else -1 + } } /** A view that zips elements of the underlying collection with the elements @@ -259,14 +271,20 @@ object View extends IterableFactory[View] { @SerialVersionUID(3L) class Appended[A](underlying: SomeIterableOps[A], elem: A) extends AbstractView[A] { def iterator: Iterator[A] = new Concat(underlying, new View.Single(elem)).iterator - override def knownSize: Int = if (underlying.knownSize >= 0) underlying.knownSize + 1 else -1 + override def knownSize: Int = { + val size = underlying.knownSize + if (size >= 0) size + 1 else -1 + } } /** A view that prepends an element to its elements */ @SerialVersionUID(3L) class Prepended[+A](elem: A, underlying: SomeIterableOps[A]) extends AbstractView[A] { def iterator: Iterator[A] = new Concat(new View.Single(elem), underlying).iterator - override def knownSize: Int = if (underlying.knownSize >= 0) underlying.knownSize + 1 else -1 + override def knownSize: Int = { + val size = underlying.knownSize + if (size >= 0) size + 1 else -1 + } } @SerialVersionUID(3L) @@ -312,7 +330,10 @@ object View extends IterableFactory[View] { class PadTo[A](underlying: SomeIterableOps[A], len: Int, elem: A) extends AbstractView[A] { def iterator: Iterator[A] = underlying.iterator.padTo(len, elem) - override def knownSize: Int = if (underlying.knownSize >= 0) underlying.knownSize max len else -1 + override def knownSize: Int = { + val size = underlying.knownSize + if (size >= 0) size max len else -1 + } } // scalac generates a `readReplace` method to discard the deserialized state (see https://github.com/scala/bug/issues/10412). From 91baba70cc1427a3853a8da2157846505f590319 Mon Sep 17 00:00:00 2001 From: Allan Renucci Date: Thu, 26 Jul 2018 12:07:47 +0200 Subject: [PATCH 092/143] Use a dummy parameter to distinguish overload and override in AnyRefMap This used to rely on a scalac bug. See scala/bug#11035 --- src/library/scala/collection/mutable/AnyRefMap.scala | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/library/scala/collection/mutable/AnyRefMap.scala b/src/library/scala/collection/mutable/AnyRefMap.scala index 9c260ac34f22..163f3532a511 100644 --- a/src/library/scala/collection/mutable/AnyRefMap.scala +++ b/src/library/scala/collection/mutable/AnyRefMap.scala @@ -426,12 +426,12 @@ class AnyRefMap[K <: AnyRef, V] private[collection] (defaultEntry: K => V, initi this } - // The `K with AnyRef` parameter type is necessary to distinguish these methods from the base methods they overload (not override) - def map[K2 <: AnyRef, V2](f: ((K with AnyRef, V)) => (K2, V2)): AnyRefMap[K2, V2] = + // The implicit dummy parameter is necessary to distinguish these methods from the base methods they overload (not override) + def map[K2 <: AnyRef, V2](f: ((K, V)) => (K2, V2))(implicit dummy: DummyImplicit): AnyRefMap[K2, V2] = AnyRefMap.from(new View.Map(toIterable, f)) - def flatMap[K2 <: AnyRef, V2](f: ((K with AnyRef, V)) => IterableOnce[(K2, V2)]): AnyRefMap[K2, V2] = + def flatMap[K2 <: AnyRef, V2](f: ((K, V)) => IterableOnce[(K2, V2)])(implicit dummy: DummyImplicit): AnyRefMap[K2, V2] = AnyRefMap.from(new View.FlatMap(toIterable, f)) - def collect[K2 <: AnyRef, V2](pf: PartialFunction[(K with AnyRef, V), (K2, V2)]): AnyRefMap[K2, V2] = + def collect[K2 <: AnyRef, V2](pf: PartialFunction[(K, V), (K2, V2)])(implicit dummy: DummyImplicit): AnyRefMap[K2, V2] = strictOptimizedCollect(AnyRefMap.newBuilder[K2, V2], pf) override protected[this] def writeReplace(): AnyRef = new DefaultSerializationProxy(AnyRefMap.toFactory[K, V](AnyRefMap), this) From 18317f41be2e9c11d2b6298b8bc85ffc9c1ddda8 Mon Sep 17 00:00:00 2001 From: Som Snytt Date: Fri, 8 Jun 2018 14:24:41 -0700 Subject: [PATCH 093/143] Support -Yimports for implicit preamble imports Take `-Yimports:x,y,z` to mean `x,y,z` are root imports of the form: ``` import x._ { import y._ { import z._ { code } } } ``` and where the import from a module (non-package) can be disabled with usual idiom, an import at the package level. The disabling import is registered when the import is completed, so it must precede all usages. --- .../tools/nsc/settings/ScalaSettings.scala | 3 + .../tools/nsc/typechecker/Contexts.scala | 68 ++++++++++++++----- .../scala/tools/nsc/typechecker/Namers.scala | 1 + .../scala/reflect/internal/TreeInfo.scala | 21 +----- .../scala/reflect/internal/Trees.scala | 1 + test/files/neg/yimports-custom-b.check | 7 ++ test/files/neg/yimports-custom-b/C_2.flags | 1 + test/files/neg/yimports-custom-b/C_2.scala | 9 +++ .../neg/yimports-custom-b/minidef_1.flags | 1 + .../neg/yimports-custom-b/minidef_1.scala | 7 ++ test/files/neg/yimports-custom.check | 4 ++ test/files/neg/yimports-custom/C_2.flags | 1 + test/files/neg/yimports-custom/C_2.scala | 5 ++ .../files/neg/yimports-custom/minidef_1.scala | 7 ++ test/files/neg/yimports-masked.check | 7 ++ test/files/neg/yimports-masked/C_2.flags | 1 + test/files/neg/yimports-masked/C_2.scala | 13 ++++ .../files/neg/yimports-masked/minidef_1.scala | 7 ++ test/files/neg/yimports-nojava.check | 7 ++ test/files/neg/yimports-nojava.flags | 1 + test/files/neg/yimports-nojava.scala | 6 ++ test/files/neg/yimports-nosuch.check | 3 + test/files/neg/yimports-nosuch.flags | 1 + test/files/neg/yimports-nosuch.scala | 2 + test/files/neg/yimports-predef.check | 4 ++ test/files/neg/yimports-predef.flags | 1 + test/files/neg/yimports-predef.scala | 6 ++ test/files/neg/yimports-stable.check | 2 + test/files/neg/yimports-stable/C_2.flags | 1 + test/files/neg/yimports-stable/C_2.scala | 5 ++ .../files/neg/yimports-stable/minidef_1.scala | 11 +++ test/files/pos/yimports-deep.scala | 12 ++++ test/files/pos/yimports-pkgobj/C_2.flags | 1 + test/files/pos/yimports-pkgobj/C_2.scala | 7 ++ .../files/pos/yimports-pkgobj/minidef_1.flags | 1 + .../files/pos/yimports-pkgobj/minidef_1.scala | 6 ++ 36 files changed, 205 insertions(+), 36 deletions(-) create mode 100644 test/files/neg/yimports-custom-b.check create mode 100644 test/files/neg/yimports-custom-b/C_2.flags create mode 100644 test/files/neg/yimports-custom-b/C_2.scala create mode 100644 test/files/neg/yimports-custom-b/minidef_1.flags create mode 100644 test/files/neg/yimports-custom-b/minidef_1.scala create mode 100644 test/files/neg/yimports-custom.check create mode 100644 test/files/neg/yimports-custom/C_2.flags create mode 100644 test/files/neg/yimports-custom/C_2.scala create mode 100644 test/files/neg/yimports-custom/minidef_1.scala create mode 100644 test/files/neg/yimports-masked.check create mode 100644 test/files/neg/yimports-masked/C_2.flags create mode 100644 test/files/neg/yimports-masked/C_2.scala create mode 100644 test/files/neg/yimports-masked/minidef_1.scala create mode 100644 test/files/neg/yimports-nojava.check create mode 100644 test/files/neg/yimports-nojava.flags create mode 100644 test/files/neg/yimports-nojava.scala create mode 100644 test/files/neg/yimports-nosuch.check create mode 100644 test/files/neg/yimports-nosuch.flags create mode 100644 test/files/neg/yimports-nosuch.scala create mode 100644 test/files/neg/yimports-predef.check create mode 100644 test/files/neg/yimports-predef.flags create mode 100644 test/files/neg/yimports-predef.scala create mode 100644 test/files/neg/yimports-stable.check create mode 100644 test/files/neg/yimports-stable/C_2.flags create mode 100644 test/files/neg/yimports-stable/C_2.scala create mode 100644 test/files/neg/yimports-stable/minidef_1.scala create mode 100644 test/files/pos/yimports-deep.scala create mode 100644 test/files/pos/yimports-pkgobj/C_2.flags create mode 100644 test/files/pos/yimports-pkgobj/C_2.scala create mode 100644 test/files/pos/yimports-pkgobj/minidef_1.flags create mode 100644 test/files/pos/yimports-pkgobj/minidef_1.scala diff --git a/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala b/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala index 12adcd62b76e..7146aa4ec909 100644 --- a/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala +++ b/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala @@ -198,7 +198,10 @@ trait ScalaSettings extends AbsScalaSettings val Ylogcp = BooleanSetting ("-Ylog-classpath", "Output information about what classpath is being applied.") val Ynogenericsig = BooleanSetting ("-Yno-generic-signatures", "Suppress generation of generic signatures for Java.") val noimports = BooleanSetting ("-Yno-imports", "Compile without importing scala.*, java.lang.*, or Predef.") + .withPostSetHook(bs => if (bs) imports.value = Nil) val nopredef = BooleanSetting ("-Yno-predef", "Compile without importing Predef.") + .withPostSetHook(bs => if (bs && !noimports) imports.value = "java.lang" :: "scala" :: Nil) + val imports = MultiStringSetting("-Yimports", "import", "Custom preamble imports, default is java.lang, scala, scala.Predef.") val Yrecursion = IntSetting ("-Yrecursion", "Set recursion depth used when locking symbols.", 0, Some((0, Int.MaxValue)), (_: String) => None) val Xshowtrees = BooleanSetting ("-Yshow-trees", "(Requires -Xprint:) Print detailed ASTs in formatted form.") val XshowtreesCompact diff --git a/src/compiler/scala/tools/nsc/typechecker/Contexts.scala b/src/compiler/scala/tools/nsc/typechecker/Contexts.scala index 7ec4c54a7703..500079430201 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Contexts.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Contexts.scala @@ -79,31 +79,63 @@ trait Contexts { self: Analyzer => var lastAccessCheckDetails: String = "" - /** List of symbols to import from in a root context. Typically that - * is `java.lang`, `scala`, and [[scala.Predef]], in that order. Exceptions: + val rootImportsCached = perRunCaches.newMap[CompilationUnit, List[Symbol]] + + val excludedRootImportsCached = perRunCaches.newMap[CompilationUnit, List[Symbol]] + + // register an import for the narrow purpose of excluding root imports of predef modules + def registerImport(ctx: Context, imp: Import): Unit = { + val sym = imp.expr.symbol + if (!sym.isPackage && ctx.enclosingNonImportContext.owner.isPackage && rootImports(ctx.unit).contains(sym)) { + var current = excludedRootImportsCached.get(ctx.unit).getOrElse(Nil) + current = sym :: current + excludedRootImportsCached += ctx.unit -> current + } + } + + /** List of symbols to import from in a root context. By default, that + * is `java.lang`, `scala`, and [[scala.Predef]], in that order. * - * - if option `-Yno-imports` is given, nothing is imported - * - if the unit is java defined, only `java.lang` is imported - * - if option `-Yno-predef` is given, if the unit body has an import of Predef + * - if option `-Yimports` is supplied, then that specifies the preamble imports + * - if the unit body has an import of Predef * among its leading imports, or if the tree is [[scala.Predef]], `Predef` is not imported. + * Similarly for any module among the preamble imports. + * - if the unit is java defined, only `java.lang` is imported + * + * The root imports for a unit are cached. */ protected def rootImports(unit: CompilationUnit): List[Symbol] = { assert(definitions.isDefinitionsInitialized, "definitions uninitialized") - if (settings.noimports) Nil - else if (unit.isJava) RootImports.javaList - else if (settings.nopredef || treeInfo.noPredefImportForUnit(unit.body)) { - // scala/bug#8258 Needed for the presentation compiler using -sourcepath, otherwise cycles can occur. See the commit - // message for this ticket for an example. - debuglog("Omitted import of Predef._ for " + unit) - RootImports.javaAndScalaList + if (unit.isJava) RootImports.javaList + else rootImportsCached.get(unit).getOrElse { + val calculated = defaultRootImports + rootImportsCached += unit -> calculated + calculated } - else RootImports.completeList } + private def defaultRootImports: List[Symbol] = { + import rootMirror.{getModuleIfDefined, getPackageObjectIfDefined, getPackageIfDefined} + + if (settings.imports.isSetByUser) + settings.imports.value.map { + case "java.lang" => JavaLangPackage + case "scala" => ScalaPackage + case "scala.Predef" => PredefModule + case s => + getModuleIfDefined(s) orElse + getPackageObjectIfDefined(s) orElse + getPackageIfDefined(s) orElse { + error(s"bad preamble import $s") + NoSymbol + } + } + else RootImports.completeList + } def rootContext(unit: CompilationUnit, tree: Tree = EmptyTree, throwing: Boolean = false, checking: Boolean = false): Context = { - val rootImportsContext = rootImports(unit).foldLeft(startContext)((c, sym) => c.make(gen.mkWildcardImport(sym))) + val rootImportsContext = rootImports(unit).foldLeft(startContext)((c, sym) => c.make(gen.mkWildcardImport(sym), unit = unit)) // there must be a scala.xml package when xml literals were parsed in this unit if (unit.hasXml && ScalaXmlPackage == NoSymbol) @@ -974,7 +1006,7 @@ trait Contexts { self: Analyzer => for (sym <- syms.toList if isQualifyingImplicit(sym.name, sym, pre, imported)) yield new ImplicitInfo(sym.name, pre, sym) - private def collectImplicitImports(imp: ImportInfo): List[ImplicitInfo] = { + private def collectImplicitImports(imp: ImportInfo): List[ImplicitInfo] = if (isExcludedRootImport(imp)) List() else { val qual = imp.qual val pre = qual.tpe @@ -1137,7 +1169,11 @@ trait Contexts { self: Analyzer => * if any such symbol is accessible from this context. */ private def importedAccessibleSymbol(imp: ImportInfo, name: Name, requireExplicit: Boolean, record: Boolean): Symbol = - imp.importedSymbol(name, requireExplicit, record) filter (s => isAccessible(s, imp.qual.tpe, superAccess = false)) + if (isExcludedRootImport(imp)) NoSymbol + else imp.importedSymbol(name, requireExplicit, record) filter (s => isAccessible(s, imp.qual.tpe, superAccess = false)) + + private def isExcludedRootImport(imp: ImportInfo): Boolean = + imp.isRootImport && excludedRootImportsCached.get(unit).map(_.contains(imp.qual.symbol)).getOrElse(false) private def requiresQualifier(s: Symbol): Boolean = ( s.owner.isClass diff --git a/src/compiler/scala/tools/nsc/typechecker/Namers.scala b/src/compiler/scala/tools/nsc/typechecker/Namers.scala index 0064647a3f9a..a8c26b32c346 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Namers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Namers.scala @@ -1780,6 +1780,7 @@ trait Namers extends MethodSynthesis { val newImport = treeCopy.Import(imp, expr1, selectors).asInstanceOf[Import] checkSelectors(newImport) context.unit.transformed(imp) = newImport + registerImport(context, newImport) // copy symbol and type attributes back into old expression // so that the structure builder will find it. expr setSymbol expr1.symbol setType expr1.tpe diff --git a/src/reflect/scala/reflect/internal/TreeInfo.scala b/src/reflect/scala/reflect/internal/TreeInfo.scala index 975dd4565618..b3573c423d78 100644 --- a/src/reflect/scala/reflect/internal/TreeInfo.scala +++ b/src/reflect/scala/reflect/internal/TreeInfo.scala @@ -835,7 +835,7 @@ abstract class TreeInfo { } /** Does list of trees start with a definition of - * a class of module with given name (ignoring imports) + * a class or module with given name (ignoring imports) */ def firstDefinesClassOrObject(trees: List[Tree], name: Name): Boolean = trees match { case Import(_, _) :: xs => firstDefinesClassOrObject(xs, name) @@ -859,25 +859,6 @@ abstract class TreeInfo { } } - /** Is this file the body of a compilation unit which should not - * have Predef imported? - */ - def noPredefImportForUnit(body: Tree) = { - // Top-level definition whose leading imports include Predef. - def isLeadingPredefImport(defn: Tree): Boolean = defn match { - case PackageDef(_, defs1) => defs1 exists isLeadingPredefImport - case Import(expr, _) => isReferenceToPredef(expr) - case _ => false - } - // Compilation unit is class or object 'name' in package 'scala' - def isUnitInScala(tree: Tree, name: Name) = tree match { - case PackageDef(Ident(nme.scala_), defs) => firstDefinesClassOrObject(defs, name) - case _ => false - } - - isUnitInScala(body, nme.Predef) || isLeadingPredefImport(body) - } - def isAbsTypeDef(tree: Tree) = tree match { case TypeDef(_, _, _, TypeBoundsTree(_, _)) => true case TypeDef(_, _, _, rhs) => rhs.tpe.isInstanceOf[TypeBounds] diff --git a/src/reflect/scala/reflect/internal/Trees.scala b/src/reflect/scala/reflect/internal/Trees.scala index 41a4e0be8c30..4858cbb50391 100644 --- a/src/reflect/scala/reflect/internal/Trees.scala +++ b/src/reflect/scala/reflect/internal/Trees.scala @@ -1309,6 +1309,7 @@ trait Trees extends api.Trees { case Select(Select(Ident(nme.ROOTPKG), nme.scala_), Id) => true case _ => false } + /** Is the tree Predef, scala.Predef, or _root_.scala.Predef? */ def isReferenceToPredef(t: Tree) = isReferenceToScalaMember(t, nme.Predef) diff --git a/test/files/neg/yimports-custom-b.check b/test/files/neg/yimports-custom-b.check new file mode 100644 index 000000000000..96166b660c83 --- /dev/null +++ b/test/files/neg/yimports-custom-b.check @@ -0,0 +1,7 @@ +C_2.scala:7: error: not found: type Numb + val v: Numb = Answer + ^ +C_2.scala:8: error: not found: value println + def greet() = println("hello, world!") + ^ +two errors found diff --git a/test/files/neg/yimports-custom-b/C_2.flags b/test/files/neg/yimports-custom-b/C_2.flags new file mode 100644 index 000000000000..f5031ea530c5 --- /dev/null +++ b/test/files/neg/yimports-custom-b/C_2.flags @@ -0,0 +1 @@ +-Yimports:hello.world.minidef diff --git a/test/files/neg/yimports-custom-b/C_2.scala b/test/files/neg/yimports-custom-b/C_2.scala new file mode 100644 index 000000000000..a028f82f44aa --- /dev/null +++ b/test/files/neg/yimports-custom-b/C_2.scala @@ -0,0 +1,9 @@ + +import hello.{world => hw} +import hw.minidef.{Magic => Answer} + +// Finds the answer, but dumb to forget Numb +class C { + val v: Numb = Answer + def greet() = println("hello, world!") +} diff --git a/test/files/neg/yimports-custom-b/minidef_1.flags b/test/files/neg/yimports-custom-b/minidef_1.flags new file mode 100644 index 000000000000..d130bcbc973f --- /dev/null +++ b/test/files/neg/yimports-custom-b/minidef_1.flags @@ -0,0 +1 @@ +-Yimports:scala diff --git a/test/files/neg/yimports-custom-b/minidef_1.scala b/test/files/neg/yimports-custom-b/minidef_1.scala new file mode 100644 index 000000000000..5d18d0a39584 --- /dev/null +++ b/test/files/neg/yimports-custom-b/minidef_1.scala @@ -0,0 +1,7 @@ + +package hello.world + +object minidef { + type Numb = Int + final val Magic = 42 +} diff --git a/test/files/neg/yimports-custom.check b/test/files/neg/yimports-custom.check new file mode 100644 index 000000000000..7a5bc3ab88a7 --- /dev/null +++ b/test/files/neg/yimports-custom.check @@ -0,0 +1,4 @@ +C_2.scala:4: error: not found: value println + def greet() = println("hello, world!") + ^ +one error found diff --git a/test/files/neg/yimports-custom/C_2.flags b/test/files/neg/yimports-custom/C_2.flags new file mode 100644 index 000000000000..f5031ea530c5 --- /dev/null +++ b/test/files/neg/yimports-custom/C_2.flags @@ -0,0 +1 @@ +-Yimports:hello.world.minidef diff --git a/test/files/neg/yimports-custom/C_2.scala b/test/files/neg/yimports-custom/C_2.scala new file mode 100644 index 000000000000..cc31c1938337 --- /dev/null +++ b/test/files/neg/yimports-custom/C_2.scala @@ -0,0 +1,5 @@ + +class C { + val v: Numb = Magic + def greet() = println("hello, world!") +} diff --git a/test/files/neg/yimports-custom/minidef_1.scala b/test/files/neg/yimports-custom/minidef_1.scala new file mode 100644 index 000000000000..5d18d0a39584 --- /dev/null +++ b/test/files/neg/yimports-custom/minidef_1.scala @@ -0,0 +1,7 @@ + +package hello.world + +object minidef { + type Numb = Int + final val Magic = 42 +} diff --git a/test/files/neg/yimports-masked.check b/test/files/neg/yimports-masked.check new file mode 100644 index 000000000000..cf2507d6dc22 --- /dev/null +++ b/test/files/neg/yimports-masked.check @@ -0,0 +1,7 @@ +C_2.scala:10: error: not found: type Numb + val v: Numb = Answer + ^ +C_2.scala:11: error: not found: value println + def greet() = println("hello, world!") + ^ +two errors found diff --git a/test/files/neg/yimports-masked/C_2.flags b/test/files/neg/yimports-masked/C_2.flags new file mode 100644 index 000000000000..f578fa979117 --- /dev/null +++ b/test/files/neg/yimports-masked/C_2.flags @@ -0,0 +1 @@ +-Yimports:scala,hello.world.minidef diff --git a/test/files/neg/yimports-masked/C_2.scala b/test/files/neg/yimports-masked/C_2.scala new file mode 100644 index 000000000000..ae97a17ecf38 --- /dev/null +++ b/test/files/neg/yimports-masked/C_2.scala @@ -0,0 +1,13 @@ + +// import at top level or top of package disables implicit import. +// the import can appear at any statement position, here, end of package. +// Update: with new trick, the import has to be completed before usages. + +import hello.world.minidef.{Magic => Answer} + +package p { + class C { + val v: Numb = Answer + def greet() = println("hello, world!") + } +} diff --git a/test/files/neg/yimports-masked/minidef_1.scala b/test/files/neg/yimports-masked/minidef_1.scala new file mode 100644 index 000000000000..5d18d0a39584 --- /dev/null +++ b/test/files/neg/yimports-masked/minidef_1.scala @@ -0,0 +1,7 @@ + +package hello.world + +object minidef { + type Numb = Int + final val Magic = 42 +} diff --git a/test/files/neg/yimports-nojava.check b/test/files/neg/yimports-nojava.check new file mode 100644 index 000000000000..1c874f2fa410 --- /dev/null +++ b/test/files/neg/yimports-nojava.check @@ -0,0 +1,7 @@ +yimports-nojava.scala:4: error: not found: type Integer + def g() = new Integer(42) + ^ +yimports-nojava.scala:5: error: not found: value Thread + def sleep() = Thread.sleep(42000L) + ^ +two errors found diff --git a/test/files/neg/yimports-nojava.flags b/test/files/neg/yimports-nojava.flags new file mode 100644 index 000000000000..9704adbb454e --- /dev/null +++ b/test/files/neg/yimports-nojava.flags @@ -0,0 +1 @@ +-Yimports:scala,scala.Predef diff --git a/test/files/neg/yimports-nojava.scala b/test/files/neg/yimports-nojava.scala new file mode 100644 index 000000000000..dc8c2c0f5947 --- /dev/null +++ b/test/files/neg/yimports-nojava.scala @@ -0,0 +1,6 @@ + +trait T { + def f() = println("hello, world!") + def g() = new Integer(42) + def sleep() = Thread.sleep(42000L) +} diff --git a/test/files/neg/yimports-nosuch.check b/test/files/neg/yimports-nosuch.check new file mode 100644 index 000000000000..041a37866512 --- /dev/null +++ b/test/files/neg/yimports-nosuch.check @@ -0,0 +1,3 @@ +error: bad preamble import skala +error: bad preamble import scala.Predeff +two errors found diff --git a/test/files/neg/yimports-nosuch.flags b/test/files/neg/yimports-nosuch.flags new file mode 100644 index 000000000000..46d0d3e36192 --- /dev/null +++ b/test/files/neg/yimports-nosuch.flags @@ -0,0 +1 @@ +-Yimports:skala,scala.Predeff diff --git a/test/files/neg/yimports-nosuch.scala b/test/files/neg/yimports-nosuch.scala new file mode 100644 index 000000000000..311da69beba0 --- /dev/null +++ b/test/files/neg/yimports-nosuch.scala @@ -0,0 +1,2 @@ + +class C diff --git a/test/files/neg/yimports-predef.check b/test/files/neg/yimports-predef.check new file mode 100644 index 000000000000..438bdfd74a02 --- /dev/null +++ b/test/files/neg/yimports-predef.check @@ -0,0 +1,4 @@ +yimports-predef.scala:5: error: value + is not a member of type parameter A + def f[A](x: A) = x + 42 + ^ +one error found diff --git a/test/files/neg/yimports-predef.flags b/test/files/neg/yimports-predef.flags new file mode 100644 index 000000000000..9704adbb454e --- /dev/null +++ b/test/files/neg/yimports-predef.flags @@ -0,0 +1 @@ +-Yimports:scala,scala.Predef diff --git a/test/files/neg/yimports-predef.scala b/test/files/neg/yimports-predef.scala new file mode 100644 index 000000000000..87a086f3855a --- /dev/null +++ b/test/files/neg/yimports-predef.scala @@ -0,0 +1,6 @@ + +import Predef.{any2stringadd => _, _} + +class classic { + def f[A](x: A) = x + 42 +} diff --git a/test/files/neg/yimports-stable.check b/test/files/neg/yimports-stable.check new file mode 100644 index 000000000000..36febddeaa6d --- /dev/null +++ b/test/files/neg/yimports-stable.check @@ -0,0 +1,2 @@ +error: bad preamble import hello.world.potions +one error found diff --git a/test/files/neg/yimports-stable/C_2.flags b/test/files/neg/yimports-stable/C_2.flags new file mode 100644 index 000000000000..02c413fc905c --- /dev/null +++ b/test/files/neg/yimports-stable/C_2.flags @@ -0,0 +1 @@ +-Yimports:scala,scala.Predef,hello.world.potions diff --git a/test/files/neg/yimports-stable/C_2.scala b/test/files/neg/yimports-stable/C_2.scala new file mode 100644 index 000000000000..ea28e0b6b663 --- /dev/null +++ b/test/files/neg/yimports-stable/C_2.scala @@ -0,0 +1,5 @@ + +class C { + val v: Numb = magic + def greet() = println("hello, world!") +} diff --git a/test/files/neg/yimports-stable/minidef_1.scala b/test/files/neg/yimports-stable/minidef_1.scala new file mode 100644 index 000000000000..b3ea7445df24 --- /dev/null +++ b/test/files/neg/yimports-stable/minidef_1.scala @@ -0,0 +1,11 @@ + +package hello + +trait stuff { + type Numb = Int + val magic = 42 +} + +object world { + val potions = new stuff {} +} diff --git a/test/files/pos/yimports-deep.scala b/test/files/pos/yimports-deep.scala new file mode 100644 index 000000000000..b1d0890251bb --- /dev/null +++ b/test/files/pos/yimports-deep.scala @@ -0,0 +1,12 @@ + +// as usual, the special import must be at package level + +package p { + package q { + object X { + import Predef.{identity=>_} + def f() = 1 -> 2 + def g() = 42 ensuring (_ > 0) + } + } +} diff --git a/test/files/pos/yimports-pkgobj/C_2.flags b/test/files/pos/yimports-pkgobj/C_2.flags new file mode 100644 index 000000000000..c64cb6561e54 --- /dev/null +++ b/test/files/pos/yimports-pkgobj/C_2.flags @@ -0,0 +1 @@ +-Yimports:scala,scala.Predef,hello.world diff --git a/test/files/pos/yimports-pkgobj/C_2.scala b/test/files/pos/yimports-pkgobj/C_2.scala new file mode 100644 index 000000000000..e583b22ef157 --- /dev/null +++ b/test/files/pos/yimports-pkgobj/C_2.scala @@ -0,0 +1,7 @@ + +import hello.world.{Numb => _, _} // no effect, world isPackage + +class C { + val v: Numb = 42 + def greet() = println("hello, world!") +} diff --git a/test/files/pos/yimports-pkgobj/minidef_1.flags b/test/files/pos/yimports-pkgobj/minidef_1.flags new file mode 100644 index 000000000000..d130bcbc973f --- /dev/null +++ b/test/files/pos/yimports-pkgobj/minidef_1.flags @@ -0,0 +1 @@ +-Yimports:scala diff --git a/test/files/pos/yimports-pkgobj/minidef_1.scala b/test/files/pos/yimports-pkgobj/minidef_1.scala new file mode 100644 index 000000000000..b589481d9997 --- /dev/null +++ b/test/files/pos/yimports-pkgobj/minidef_1.scala @@ -0,0 +1,6 @@ + +package hello + +package object world { + type Numb = Int +} From 42328aaf06451c54f7b1faba4d09c83321333898 Mon Sep 17 00:00:00 2001 From: Som Snytt Date: Fri, 8 Jun 2018 19:19:26 -0700 Subject: [PATCH 094/143] Minor tweak for readability --- .../tools/nsc/typechecker/Contexts.scala | 20 ++++++++----------- 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/src/compiler/scala/tools/nsc/typechecker/Contexts.scala b/src/compiler/scala/tools/nsc/typechecker/Contexts.scala index 500079430201..b751ae9e14fc 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Contexts.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Contexts.scala @@ -1116,12 +1116,6 @@ trait Contexts { self: Analyzer => def mt1 = t1 memberType imp1Symbol def mt2 = t2 memberType imp2Symbol - def characterize = List( - s"types: $t1 =:= $t2 ${t1 =:= t2} members: ${mt1 =:= mt2}", - s"member type 1: $mt1", - s"member type 2: $mt2" - ).mkString("\n ") - if (!ambiguous || !imp2Symbol.exists) Some(imp1) else if (!imp1Symbol.exists) Some(imp2) else ( @@ -1141,7 +1135,10 @@ trait Contexts { self: Analyzer => Some(imp1) } else { - log(s"Import is genuinely ambiguous:\n " + characterize) + log(s"""Import is genuinely ambiguous: + | types: $t1 =:= $t2 ${t1 =:= t2} members: ${mt1 =:= mt2} + | member type 1: $mt1 + | member type 2: $mt2""".stripMargin) None } ) @@ -1212,11 +1209,10 @@ trait Contexts { self: Analyzer => case _ => LookupSucceeded(qual, sym) } ) - def finishDefSym(sym: Symbol, pre0: Type): NameLookup = - if (requiresQualifier(sym)) - finish(gen.mkAttributedQualifier(pre0), sym) - else - finish(EmptyTree, sym) + def finishDefSym(sym: Symbol, pre0: Type): NameLookup = { + val qual = if (requiresQualifier(sym)) gen.mkAttributedQualifier(pre0) else EmptyTree + finish(qual, sym) + } def lookupInPrefix(name: Name) = { val sym = pre.member(name).filter(qualifies) From 6230b0650d737deacc31e86ae4036f415095915f Mon Sep 17 00:00:00 2001 From: Som Snytt Date: Mon, 18 Jun 2018 21:11:24 -0700 Subject: [PATCH 095/143] Update per review --- .../tools/nsc/settings/ScalaSettings.scala | 23 ++++++++++++++++++- .../tools/nsc/typechecker/Contexts.scala | 2 +- .../scala/reflect/internal/Trees.scala | 12 ---------- 3 files changed, 23 insertions(+), 14 deletions(-) diff --git a/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala b/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala index 7146aa4ec909..cf78faee3cb4 100644 --- a/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala +++ b/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala @@ -15,6 +15,7 @@ import scala.language.existentials import scala.annotation.elidable import scala.tools.util.PathResolver.Defaults import scala.collection.mutable +import scala.reflect.internal.util.StringContextStripMarginOps trait ScalaSettings extends AbsScalaSettings with StandardScalaSettings @@ -201,7 +202,27 @@ trait ScalaSettings extends AbsScalaSettings .withPostSetHook(bs => if (bs) imports.value = Nil) val nopredef = BooleanSetting ("-Yno-predef", "Compile without importing Predef.") .withPostSetHook(bs => if (bs && !noimports) imports.value = "java.lang" :: "scala" :: Nil) - val imports = MultiStringSetting("-Yimports", "import", "Custom preamble imports, default is java.lang, scala, scala.Predef.") + val imports = MultiStringSetting(name="-Yimports", arg="import", descr="Custom preamble imports, default is `java.lang,scala,scala.Predef`.", helpText=Some( + sm"""|Specify a list of packages and objects to import from as "root" imports. + |Root imports form the root context in which all Scala source is evaluated. + |The names supplied to `-Yimports` must be fully-qualified. + | + |For example, the default scala.Predef results in an `import scala.Predef._`. + |Ordinary access and scoping rules apply. Root imports increase the scoping + |depth, so that later root imports shadow earlier ones. In addition, + |names bound by root imports have lowest binding precedence, so that they + |cannot induce ambiguities in user code, where definitions and imports + |always have a higher precedence. Root imports are imports of last resort. + | + |By convention, an explicit import from a root import object such as + |Predef disables that root import for the current source file. The import + |is disabled when the import expression is compiled, so, also by convention, + |the import should be placed early in source code order. The textual name + |in the import does not need to match the value of `-Yimports`; the import + |works in the usual way, subject to renames and name binding precedence. + | + """ + )) val Yrecursion = IntSetting ("-Yrecursion", "Set recursion depth used when locking symbols.", 0, Some((0, Int.MaxValue)), (_: String) => None) val Xshowtrees = BooleanSetting ("-Yshow-trees", "(Requires -Xprint:) Print detailed ASTs in formatted form.") val XshowtreesCompact diff --git a/src/compiler/scala/tools/nsc/typechecker/Contexts.scala b/src/compiler/scala/tools/nsc/typechecker/Contexts.scala index b751ae9e14fc..62d9f765a322 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Contexts.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Contexts.scala @@ -1170,7 +1170,7 @@ trait Contexts { self: Analyzer => else imp.importedSymbol(name, requireExplicit, record) filter (s => isAccessible(s, imp.qual.tpe, superAccess = false)) private def isExcludedRootImport(imp: ImportInfo): Boolean = - imp.isRootImport && excludedRootImportsCached.get(unit).map(_.contains(imp.qual.symbol)).getOrElse(false) + imp.isRootImport && excludedRootImportsCached.get(unit).exists(_.contains(imp.qual.symbol)) private def requiresQualifier(s: Symbol): Boolean = ( s.owner.isClass diff --git a/src/reflect/scala/reflect/internal/Trees.scala b/src/reflect/scala/reflect/internal/Trees.scala index 4858cbb50391..7b4230fcaa9e 100644 --- a/src/reflect/scala/reflect/internal/Trees.scala +++ b/src/reflect/scala/reflect/internal/Trees.scala @@ -1302,18 +1302,6 @@ trait Trees extends api.Trees { } } - // Belongs in TreeInfo but then I can't reach it from Printers. - def isReferenceToScalaMember(t: Tree, Id: Name) = t match { - case Ident(Id) => true - case Select(Ident(nme.scala_), Id) => true - case Select(Select(Ident(nme.ROOTPKG), nme.scala_), Id) => true - case _ => false - } - - /** Is the tree Predef, scala.Predef, or _root_.scala.Predef? - */ - def isReferenceToPredef(t: Tree) = isReferenceToScalaMember(t, nme.Predef) - // --- modifiers implementation --------------------------------------- /** @param privateWithin the qualifier for a private (a type name) From fa034838963e307a265b7400b688934a75628fc7 Mon Sep 17 00:00:00 2001 From: Som Snytt Date: Fri, 27 Jul 2018 13:37:06 -0700 Subject: [PATCH 096/143] Custom root imports are not preamble --- src/compiler/scala/tools/nsc/settings/ScalaSettings.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala b/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala index cf78faee3cb4..c48f67681947 100644 --- a/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala +++ b/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala @@ -202,7 +202,7 @@ trait ScalaSettings extends AbsScalaSettings .withPostSetHook(bs => if (bs) imports.value = Nil) val nopredef = BooleanSetting ("-Yno-predef", "Compile without importing Predef.") .withPostSetHook(bs => if (bs && !noimports) imports.value = "java.lang" :: "scala" :: Nil) - val imports = MultiStringSetting(name="-Yimports", arg="import", descr="Custom preamble imports, default is `java.lang,scala,scala.Predef`.", helpText=Some( + val imports = MultiStringSetting(name="-Yimports", arg="import", descr="Custom root imports, default is `java.lang,scala,scala.Predef`.", helpText=Some( sm"""|Specify a list of packages and objects to import from as "root" imports. |Root imports form the root context in which all Scala source is evaluated. |The names supplied to `-Yimports` must be fully-qualified. From 99655e34851907f3353ee6c79f451ff8c62afce4 Mon Sep 17 00:00:00 2001 From: Som Snytt Date: Fri, 27 Jul 2018 14:18:55 -0700 Subject: [PATCH 097/143] No flags files --- test/files/neg/yimports-custom-b.check | 4 ++-- test/files/neg/yimports-custom-b/C_2.flags | 1 - test/files/neg/yimports-custom-b/C_2.scala | 1 + test/files/neg/yimports-custom-b/minidef_1.flags | 1 - test/files/neg/yimports-custom-b/minidef_1.scala | 1 + test/files/neg/yimports-custom.check | 2 +- test/files/neg/yimports-custom/C_2.flags | 1 - test/files/neg/yimports-custom/C_2.scala | 1 + test/files/neg/yimports-masked.check | 4 ++-- test/files/neg/yimports-masked/C_2.flags | 1 - test/files/neg/yimports-masked/C_2.scala | 1 + test/files/neg/yimports-nojava.check | 4 ++-- test/files/neg/yimports-nojava.flags | 1 - test/files/neg/yimports-nojava.scala | 1 + test/files/neg/yimports-nosuch.flags | 1 - test/files/neg/yimports-nosuch.scala | 3 ++- test/files/neg/yimports-predef.check | 2 +- test/files/neg/yimports-predef.flags | 1 - test/files/neg/yimports-predef.scala | 3 ++- test/files/neg/yimports-stable/C_2.flags | 1 - test/files/neg/yimports-stable/C_2.scala | 3 ++- test/files/pos/yimports-pkgobj/C_2.flags | 1 - test/files/pos/yimports-pkgobj/C_2.scala | 3 ++- test/files/pos/yimports-pkgobj/minidef_1.flags | 1 - test/files/pos/yimports-pkgobj/minidef_1.scala | 3 ++- 25 files changed, 23 insertions(+), 23 deletions(-) delete mode 100644 test/files/neg/yimports-custom-b/C_2.flags delete mode 100644 test/files/neg/yimports-custom-b/minidef_1.flags delete mode 100644 test/files/neg/yimports-custom/C_2.flags delete mode 100644 test/files/neg/yimports-masked/C_2.flags delete mode 100644 test/files/neg/yimports-nojava.flags delete mode 100644 test/files/neg/yimports-nosuch.flags delete mode 100644 test/files/neg/yimports-predef.flags delete mode 100644 test/files/neg/yimports-stable/C_2.flags delete mode 100644 test/files/pos/yimports-pkgobj/C_2.flags delete mode 100644 test/files/pos/yimports-pkgobj/minidef_1.flags diff --git a/test/files/neg/yimports-custom-b.check b/test/files/neg/yimports-custom-b.check index 96166b660c83..e2b0d5d1eca7 100644 --- a/test/files/neg/yimports-custom-b.check +++ b/test/files/neg/yimports-custom-b.check @@ -1,7 +1,7 @@ -C_2.scala:7: error: not found: type Numb +C_2.scala:8: error: not found: type Numb val v: Numb = Answer ^ -C_2.scala:8: error: not found: value println +C_2.scala:9: error: not found: value println def greet() = println("hello, world!") ^ two errors found diff --git a/test/files/neg/yimports-custom-b/C_2.flags b/test/files/neg/yimports-custom-b/C_2.flags deleted file mode 100644 index f5031ea530c5..000000000000 --- a/test/files/neg/yimports-custom-b/C_2.flags +++ /dev/null @@ -1 +0,0 @@ --Yimports:hello.world.minidef diff --git a/test/files/neg/yimports-custom-b/C_2.scala b/test/files/neg/yimports-custom-b/C_2.scala index a028f82f44aa..09940d0a6d42 100644 --- a/test/files/neg/yimports-custom-b/C_2.scala +++ b/test/files/neg/yimports-custom-b/C_2.scala @@ -1,3 +1,4 @@ +// scalac: -Yimports:hello.world.minidef import hello.{world => hw} import hw.minidef.{Magic => Answer} diff --git a/test/files/neg/yimports-custom-b/minidef_1.flags b/test/files/neg/yimports-custom-b/minidef_1.flags deleted file mode 100644 index d130bcbc973f..000000000000 --- a/test/files/neg/yimports-custom-b/minidef_1.flags +++ /dev/null @@ -1 +0,0 @@ --Yimports:scala diff --git a/test/files/neg/yimports-custom-b/minidef_1.scala b/test/files/neg/yimports-custom-b/minidef_1.scala index 5d18d0a39584..befc137b6ab6 100644 --- a/test/files/neg/yimports-custom-b/minidef_1.scala +++ b/test/files/neg/yimports-custom-b/minidef_1.scala @@ -1,3 +1,4 @@ +// scalac: -Yimports:scala package hello.world diff --git a/test/files/neg/yimports-custom.check b/test/files/neg/yimports-custom.check index 7a5bc3ab88a7..64d5bc8401a5 100644 --- a/test/files/neg/yimports-custom.check +++ b/test/files/neg/yimports-custom.check @@ -1,4 +1,4 @@ -C_2.scala:4: error: not found: value println +C_2.scala:5: error: not found: value println def greet() = println("hello, world!") ^ one error found diff --git a/test/files/neg/yimports-custom/C_2.flags b/test/files/neg/yimports-custom/C_2.flags deleted file mode 100644 index f5031ea530c5..000000000000 --- a/test/files/neg/yimports-custom/C_2.flags +++ /dev/null @@ -1 +0,0 @@ --Yimports:hello.world.minidef diff --git a/test/files/neg/yimports-custom/C_2.scala b/test/files/neg/yimports-custom/C_2.scala index cc31c1938337..660a580d6fee 100644 --- a/test/files/neg/yimports-custom/C_2.scala +++ b/test/files/neg/yimports-custom/C_2.scala @@ -1,3 +1,4 @@ +// scalac: -Yimports:hello.world.minidef class C { val v: Numb = Magic diff --git a/test/files/neg/yimports-masked.check b/test/files/neg/yimports-masked.check index cf2507d6dc22..24da863388b4 100644 --- a/test/files/neg/yimports-masked.check +++ b/test/files/neg/yimports-masked.check @@ -1,7 +1,7 @@ -C_2.scala:10: error: not found: type Numb +C_2.scala:11: error: not found: type Numb val v: Numb = Answer ^ -C_2.scala:11: error: not found: value println +C_2.scala:12: error: not found: value println def greet() = println("hello, world!") ^ two errors found diff --git a/test/files/neg/yimports-masked/C_2.flags b/test/files/neg/yimports-masked/C_2.flags deleted file mode 100644 index f578fa979117..000000000000 --- a/test/files/neg/yimports-masked/C_2.flags +++ /dev/null @@ -1 +0,0 @@ --Yimports:scala,hello.world.minidef diff --git a/test/files/neg/yimports-masked/C_2.scala b/test/files/neg/yimports-masked/C_2.scala index ae97a17ecf38..e3eade457876 100644 --- a/test/files/neg/yimports-masked/C_2.scala +++ b/test/files/neg/yimports-masked/C_2.scala @@ -1,3 +1,4 @@ +// scalac: -Yimports:scala,hello.world.minidef // import at top level or top of package disables implicit import. // the import can appear at any statement position, here, end of package. diff --git a/test/files/neg/yimports-nojava.check b/test/files/neg/yimports-nojava.check index 1c874f2fa410..5e440bfdf6ce 100644 --- a/test/files/neg/yimports-nojava.check +++ b/test/files/neg/yimports-nojava.check @@ -1,7 +1,7 @@ -yimports-nojava.scala:4: error: not found: type Integer +yimports-nojava.scala:5: error: not found: type Integer def g() = new Integer(42) ^ -yimports-nojava.scala:5: error: not found: value Thread +yimports-nojava.scala:6: error: not found: value Thread def sleep() = Thread.sleep(42000L) ^ two errors found diff --git a/test/files/neg/yimports-nojava.flags b/test/files/neg/yimports-nojava.flags deleted file mode 100644 index 9704adbb454e..000000000000 --- a/test/files/neg/yimports-nojava.flags +++ /dev/null @@ -1 +0,0 @@ --Yimports:scala,scala.Predef diff --git a/test/files/neg/yimports-nojava.scala b/test/files/neg/yimports-nojava.scala index dc8c2c0f5947..955685d16f7a 100644 --- a/test/files/neg/yimports-nojava.scala +++ b/test/files/neg/yimports-nojava.scala @@ -1,3 +1,4 @@ +// scalac: -Yimports:scala,scala.Predef trait T { def f() = println("hello, world!") diff --git a/test/files/neg/yimports-nosuch.flags b/test/files/neg/yimports-nosuch.flags deleted file mode 100644 index 46d0d3e36192..000000000000 --- a/test/files/neg/yimports-nosuch.flags +++ /dev/null @@ -1 +0,0 @@ --Yimports:skala,scala.Predeff diff --git a/test/files/neg/yimports-nosuch.scala b/test/files/neg/yimports-nosuch.scala index 311da69beba0..c868edfa3d6c 100644 --- a/test/files/neg/yimports-nosuch.scala +++ b/test/files/neg/yimports-nosuch.scala @@ -1,2 +1,3 @@ - +// scalac: -Yimports:skala,scala.Predeff +// class C diff --git a/test/files/neg/yimports-predef.check b/test/files/neg/yimports-predef.check index 438bdfd74a02..e47ede188187 100644 --- a/test/files/neg/yimports-predef.check +++ b/test/files/neg/yimports-predef.check @@ -1,4 +1,4 @@ -yimports-predef.scala:5: error: value + is not a member of type parameter A +yimports-predef.scala:6: error: value + is not a member of type parameter A def f[A](x: A) = x + 42 ^ one error found diff --git a/test/files/neg/yimports-predef.flags b/test/files/neg/yimports-predef.flags deleted file mode 100644 index 9704adbb454e..000000000000 --- a/test/files/neg/yimports-predef.flags +++ /dev/null @@ -1 +0,0 @@ --Yimports:scala,scala.Predef diff --git a/test/files/neg/yimports-predef.scala b/test/files/neg/yimports-predef.scala index 87a086f3855a..6165c566ac82 100644 --- a/test/files/neg/yimports-predef.scala +++ b/test/files/neg/yimports-predef.scala @@ -1,4 +1,5 @@ - +// scalac: -Yimports:scala,scala.Predef +// import Predef.{any2stringadd => _, _} class classic { diff --git a/test/files/neg/yimports-stable/C_2.flags b/test/files/neg/yimports-stable/C_2.flags deleted file mode 100644 index 02c413fc905c..000000000000 --- a/test/files/neg/yimports-stable/C_2.flags +++ /dev/null @@ -1 +0,0 @@ --Yimports:scala,scala.Predef,hello.world.potions diff --git a/test/files/neg/yimports-stable/C_2.scala b/test/files/neg/yimports-stable/C_2.scala index ea28e0b6b663..dfadaef12186 100644 --- a/test/files/neg/yimports-stable/C_2.scala +++ b/test/files/neg/yimports-stable/C_2.scala @@ -1,4 +1,5 @@ - +// scalac: -Yimports:scala,scala.Predef,hello.world.potions +// class C { val v: Numb = magic def greet() = println("hello, world!") diff --git a/test/files/pos/yimports-pkgobj/C_2.flags b/test/files/pos/yimports-pkgobj/C_2.flags deleted file mode 100644 index c64cb6561e54..000000000000 --- a/test/files/pos/yimports-pkgobj/C_2.flags +++ /dev/null @@ -1 +0,0 @@ --Yimports:scala,scala.Predef,hello.world diff --git a/test/files/pos/yimports-pkgobj/C_2.scala b/test/files/pos/yimports-pkgobj/C_2.scala index e583b22ef157..b0a418a6c69f 100644 --- a/test/files/pos/yimports-pkgobj/C_2.scala +++ b/test/files/pos/yimports-pkgobj/C_2.scala @@ -1,4 +1,5 @@ - +// scalac: -Yimports:scala,scala.Predef,hello.world +// import hello.world.{Numb => _, _} // no effect, world isPackage class C { diff --git a/test/files/pos/yimports-pkgobj/minidef_1.flags b/test/files/pos/yimports-pkgobj/minidef_1.flags deleted file mode 100644 index d130bcbc973f..000000000000 --- a/test/files/pos/yimports-pkgobj/minidef_1.flags +++ /dev/null @@ -1 +0,0 @@ --Yimports:scala diff --git a/test/files/pos/yimports-pkgobj/minidef_1.scala b/test/files/pos/yimports-pkgobj/minidef_1.scala index b589481d9997..1681f4b62312 100644 --- a/test/files/pos/yimports-pkgobj/minidef_1.scala +++ b/test/files/pos/yimports-pkgobj/minidef_1.scala @@ -1,4 +1,5 @@ - +// scalac: -Yimports:scala +// package hello package object world { From 15b1222f5b090c5492f211782fdc40e831c8efcd Mon Sep 17 00:00:00 2001 From: Som Snytt Date: Fri, 27 Jul 2018 16:14:44 -0700 Subject: [PATCH 098/143] Tests that order matters in import nullification --- test/files/neg/yimports-order.check | 10 ++++++++++ test/files/neg/yimports-order.scala | 13 +++++++++++++ test/files/pos/yimports-order-b.scala | 17 +++++++++++++++++ 3 files changed, 40 insertions(+) create mode 100644 test/files/neg/yimports-order.check create mode 100644 test/files/neg/yimports-order.scala create mode 100644 test/files/pos/yimports-order-b.scala diff --git a/test/files/neg/yimports-order.check b/test/files/neg/yimports-order.check new file mode 100644 index 000000000000..05e5d416d26b --- /dev/null +++ b/test/files/neg/yimports-order.check @@ -0,0 +1,10 @@ +yimports-order.scala:9: error: not found: value Map + def f() = Map("hello" -> "world") + ^ +yimports-order.scala:9: error: value -> is not a member of String + def f() = Map("hello" -> "world") + ^ +yimports-order.scala:10: error: not found: value println + def g() = println(f()) + ^ +three errors found diff --git a/test/files/neg/yimports-order.scala b/test/files/neg/yimports-order.scala new file mode 100644 index 000000000000..9de528b6cc85 --- /dev/null +++ b/test/files/neg/yimports-order.scala @@ -0,0 +1,13 @@ + +package top { + package middle { + class C { + def c() = println("hello, world") + } + import Predef.{Map => _} + object Test { + def f() = Map("hello" -> "world") + def g() = println(f()) + } + } +} diff --git a/test/files/pos/yimports-order-b.scala b/test/files/pos/yimports-order-b.scala new file mode 100644 index 000000000000..7905fc25a45a --- /dev/null +++ b/test/files/pos/yimports-order-b.scala @@ -0,0 +1,17 @@ + +package top { + package middle { + import bottom.B.b + class C { + def p() = println("hello, world") + def f = b // comment me to see Predef exclusion + } + } +} + +package bottom { + import Predef.{Set => _} + object B { + def b = Set(42) + } +} From 4c80fe2612c29cc14d5fcee01fca104031ac88c4 Mon Sep 17 00:00:00 2001 From: Jason Zaugg Date: Mon, 30 Jul 2018 10:42:42 +1000 Subject: [PATCH 099/143] Speedup some symbol lookups in Definitions --- .../scala/reflect/internal/Definitions.scala | 34 +++++++++++++++---- .../reflect/runtime/JavaUniverseForce.scala | 2 ++ 2 files changed, 30 insertions(+), 6 deletions(-) diff --git a/src/reflect/scala/reflect/internal/Definitions.scala b/src/reflect/scala/reflect/internal/Definitions.scala index 43d4336c50b8..b467cba6f2cc 100644 --- a/src/reflect/scala/reflect/internal/Definitions.scala +++ b/src/reflect/scala/reflect/internal/Definitions.scala @@ -107,7 +107,7 @@ trait Definitions extends api.StandardDefinitions { ) /** Is symbol a numeric value class? */ - def isNumericValueClass(sym: Symbol) = ScalaNumericValueClasses contains sym + def isNumericValueClass(sym: Symbol) = ScalaNumericValueClassesSet contains sym def isGetClass(sym: Symbol) = ( sym.name == nme.getClass_ // this condition is for performance only, this is called from `Typer#stabilize`. @@ -150,6 +150,26 @@ trait Definitions extends api.StandardDefinitions { FloatClass, DoubleClass ) + lazy val ScalaValueClassesSet: SymbolSet = new SymbolSet(ScalaValueClasses) + lazy val ScalaNumericValueClassesSet: SymbolSet = new SymbolSet(ScalaNumericValueClasses) + final class SymbolSet(syms: List[Symbol]) { + private[this] val ids: Array[Symbol] = syms.toArray + private[this] val commonOwner = syms.map(_.rawowner).distinct match { + case common :: Nil => common + case _ => null + } + final def contains(sym: Symbol): Boolean = { + if (commonOwner != null && (commonOwner ne sym.rawowner)) + return false + val array = ids + var i = 0 + while (i < array.length) { + if (array(i) eq sym) return true + i += 1 + } + false + } + } def ScalaPrimitiveValueClasses: List[ClassSymbol] = ScalaValueClasses def underlyingOfValueClass(clazz: Symbol): Type = @@ -575,6 +595,8 @@ trait Definitions extends api.StandardDefinitions { private val offset = countFrom - init.size private def isDefinedAt(i: Int) = i < seq.length + offset && i >= offset val seq: IndexedSeq[ClassSymbol] = (init ++: countFrom.to(maxArity).map { i => getRequiredClass("scala." + name + i) }).toVector + private val symSet = new SymbolSet(seq.toList) + def contains(sym: Symbol): Boolean = symSet.contains(sym) def apply(i: Int) = if (isDefinedAt(i)) seq(i - offset) else NoSymbol def specificType(args: List[Type], others: Type*): Type = { val arity = args.length @@ -615,10 +637,10 @@ trait Definitions extends api.StandardDefinitions { else nme.genericWrapArray } - def isTupleSymbol(sym: Symbol) = TupleClass.seq contains unspecializedSymbol(sym) - def isFunctionSymbol(sym: Symbol) = FunctionClass.seq contains unspecializedSymbol(sym) - def isAbstractFunctionSymbol(sym: Symbol) = AbstractFunctionClass.seq contains unspecializedSymbol(sym) - def isProductNSymbol(sym: Symbol) = ProductClass.seq contains unspecializedSymbol(sym) + def isTupleSymbol(sym: Symbol) = TupleClass contains unspecializedSymbol(sym) + def isFunctionSymbol(sym: Symbol) = FunctionClass contains unspecializedSymbol(sym) + def isAbstractFunctionSymbol(sym: Symbol) = AbstractFunctionClass contains unspecializedSymbol(sym) + def isProductNSymbol(sym: Symbol) = ProductClass contains unspecializedSymbol(sym) def unspecializedSymbol(sym: Symbol): Symbol = { if (sym hasFlag SPECIALIZED) { @@ -1388,7 +1410,7 @@ trait Definitions extends api.StandardDefinitions { private lazy val boxedValueClassesSet = boxedClass.values.toSet[Symbol] + BoxedUnitClass /** Is symbol a value class? */ - def isPrimitiveValueClass(sym: Symbol) = ScalaValueClasses contains sym + def isPrimitiveValueClass(sym: Symbol) = ScalaValueClassesSet contains sym def isPrimitiveValueType(tp: Type) = isPrimitiveValueClass(tp.typeSymbol) /** Is symbol a boxed value class, e.g. java.lang.Integer? */ diff --git a/src/reflect/scala/reflect/runtime/JavaUniverseForce.scala b/src/reflect/scala/reflect/runtime/JavaUniverseForce.scala index 8c59a96081a2..fc05f5b6159b 100644 --- a/src/reflect/scala/reflect/runtime/JavaUniverseForce.scala +++ b/src/reflect/scala/reflect/runtime/JavaUniverseForce.scala @@ -467,6 +467,8 @@ trait JavaUniverseForce { self: runtime.JavaUniverse => definitions.ScalaNumericValueClasses definitions.ScalaValueClassesNoUnit definitions.ScalaValueClasses + definitions.ScalaValueClassesSet + definitions.ScalaNumericValueClassesSet uncurry.VarargsSymbolAttachment uncurry.DesugaredParameterType From f05d16d9f1402284bfc03a0c7d028cd2f0ccf670 Mon Sep 17 00:00:00 2001 From: Jason Zaugg Date: Mon, 30 Jul 2018 10:44:00 +1000 Subject: [PATCH 100/143] Avoid some virtual call overhead to get to Symbol.equals --- src/reflect/scala/reflect/internal/Symbols.scala | 2 +- .../scala/reflect/internal/transform/Erasure.scala | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/reflect/scala/reflect/internal/Symbols.scala b/src/reflect/scala/reflect/internal/Symbols.scala index 91b2ad6d6fb7..ba8ecad31440 100644 --- a/src/reflect/scala/reflect/internal/Symbols.scala +++ b/src/reflect/scala/reflect/internal/Symbols.scala @@ -828,7 +828,7 @@ trait Symbols extends api.Symbols { self: SymbolTable => final def isDelambdafyFunction = isSynthetic && (name containsName tpnme.DELAMBDAFY_LAMBDA_CLASS_NAME) final def isDelambdafyTarget = isArtifact && isMethod && hasAttachment[DelambdafyTarget.type] final def isDefinedInPackage = effectiveOwner.isPackageClass - final def needsFlatClasses = phase.flatClasses && rawowner != NoSymbol && !rawowner.isPackageClass + final def needsFlatClasses = phase.flatClasses && (rawowner ne NoSymbol) && !rawowner.isPackageClass // TODO introduce a flag for these? final def isPatternTypeVariable: Boolean = diff --git a/src/reflect/scala/reflect/internal/transform/Erasure.scala b/src/reflect/scala/reflect/internal/transform/Erasure.scala index 64caafa978f6..0fc72ead1981 100644 --- a/src/reflect/scala/reflect/internal/transform/Erasure.scala +++ b/src/reflect/scala/reflect/internal/transform/Erasure.scala @@ -122,12 +122,12 @@ trait Erasure { case st: SubType => apply(st.supertype) case tref @ TypeRef(pre, sym, args) => - if (sym == ArrayClass) + if (sym eq ArrayClass) if (unboundedGenericArrayLevel(tp) == 1) ObjectTpe else if (args.head.typeSymbol.isBottomClass) arrayType(ObjectTpe) else typeRef(apply(pre), sym, args map applyInArray) - else if (sym == AnyClass || sym == AnyValClass || sym == SingletonClass) ObjectTpe - else if (sym == UnitClass) BoxedUnitTpe + else if ((sym eq AnyClass) || (sym eq AnyValClass) || (sym eq SingletonClass)) ObjectTpe + else if (sym eq UnitClass) BoxedUnitTpe else if (sym.isRefinementClass) apply(mergeParents(tp.parents)) else if (sym.isDerivedValueClass) eraseDerivedValueClassRef(tref) else if (sym.isClass) eraseNormalClassRef(tref) @@ -149,15 +149,15 @@ trait Erasure { apply(atp) case ClassInfoType(parents, decls, clazz) => val newParents = - if (parents.isEmpty || clazz == ObjectClass || isPrimitiveValueClass(clazz)) Nil - else if (clazz == ArrayClass) ObjectTpe :: Nil + if (parents.isEmpty || (clazz eq ObjectClass) || isPrimitiveValueClass(clazz)) Nil + else if (clazz eq ArrayClass) ObjectTpe :: Nil else { val erasedParents = parents mapConserve this // drop first parent for traits -- it has been normalized to a class by now, // but we should drop that in bytecode if (clazz.hasFlag(Flags.TRAIT) && !clazz.hasFlag(Flags.JAVA)) - ObjectTpe :: erasedParents.tail.filter(_.typeSymbol != ObjectClass) + ObjectTpe :: erasedParents.tail.filter(_.typeSymbol ne ObjectClass) else erasedParents } if (newParents eq parents) tp From ba4980be7d2ddda4bea25d06f590e2d8d4868e6f Mon Sep 17 00:00:00 2001 From: Julien Richard-Foy Date: Tue, 31 Jul 2018 09:12:03 +0200 Subject: [PATCH 101/143] Merge knownSize docs to IterableOnce --- src/library/scala/collection/IterableOnce.scala | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/library/scala/collection/IterableOnce.scala b/src/library/scala/collection/IterableOnce.scala index b76cc9630dcf..f650dee7481a 100644 --- a/src/library/scala/collection/IterableOnce.scala +++ b/src/library/scala/collection/IterableOnce.scala @@ -36,7 +36,9 @@ trait IterableOnce[+A] extends Any { /** Iterator can be used only once */ def iterator: Iterator[A] - /** @return The number of elements of this $coll if it can be computed in O(1) time, otherwise -1 */ + /** @return The number of elements in this $coll, if it can be cheaply computed, + * -1 otherwise. Cheaply usually means: Not requiring a collection traversal. + */ def knownSize: Int } @@ -419,9 +421,6 @@ trait IterableOnceOps[+A, +CC[_], +C] extends Any { this: IterableOnce[A] => /////////////////////////////////////////////////////////////// Concrete methods based on iterator - /** The number of elements in this $coll, if it can be cheaply computed, - * -1 otherwise. Cheaply usually means: Not requiring a collection traversal. - */ def knownSize: Int = -1 @deprecated("Use .knownSize >=0 instead of .hasDefiniteSize", "2.13.0") From cb627cd93f02f79b6eb469d055ab5a2f066a253b Mon Sep 17 00:00:00 2001 From: xuwei-k <6b656e6a69@gmail.com> Date: Tue, 31 Jul 2018 17:17:26 +0900 Subject: [PATCH 102/143] remove unused `@define` values in scaladoc --- src/library/scala/Array.scala | 5 ----- src/library/scala/Option.scala | 3 --- src/library/scala/collection/immutable/Vector.scala | 7 ------- 3 files changed, 15 deletions(-) diff --git a/src/library/scala/Array.scala b/src/library/scala/Array.scala index ba1fcc862a22..acea58956238 100644 --- a/src/library/scala/Array.scala +++ b/src/library/scala/Array.scala @@ -571,11 +571,6 @@ object Array { * @define willNotTerminateInf * @define collectExample * @define undefinedorder - * @define thatinfo the class of the returned collection. In the standard library configuration, - * `That` is either `Array[B]` if an ClassTag is available for B or `ArraySeq[B]` otherwise. - * @define zipthatinfo $thatinfo - * @define bfinfo an implicit value of class `CanBuildFrom` which determines the result class `That` from the current - * representation type `Repr` and the new element type `B`. */ final class Array[T](_length: Int) extends java.io.Serializable with java.lang.Cloneable { diff --git a/src/library/scala/Option.scala b/src/library/scala/Option.scala index 64c0efdba016..37c59e20078c 100644 --- a/src/library/scala/Option.scala +++ b/src/library/scala/Option.scala @@ -103,9 +103,6 @@ object Option { * @define willNotTerminateInf * @define collectExample * @define undefinedorder - * @define thatinfo the class of the returned collection. In the standard library configuration, `That` is `Iterable[B]` - * @define bfinfo an implicit value of class `CanBuildFrom` which determines the result class `That` from the current - * representation type `Repr` and the new element type `B`. */ @SerialVersionUID(-114498752079829388L) // value computed by serialver for 2.11.2, annotation added in 2.11.4 sealed abstract class Option[+A] extends Product with Serializable { diff --git a/src/library/scala/collection/immutable/Vector.scala b/src/library/scala/collection/immutable/Vector.scala index 7f810530c245..2829910b2b11 100644 --- a/src/library/scala/collection/immutable/Vector.scala +++ b/src/library/scala/collection/immutable/Vector.scala @@ -55,13 +55,6 @@ object Vector extends StrictOptimizedSeqFactory[Vector] { * * @define Coll `Vector` * @define coll vector - * @define thatinfo the class of the returned collection. In the standard library configuration, - * `That` is always `Vector[B]` because an implicit of type `CanBuildFrom[Vector, B, That]` - * is defined in object `Vector`. - * @define bfinfo an implicit value of class `CanBuildFrom` which determines the - * result class `That` from the current representation type `Repr` - * and the new element type `B`. This is usually the `canBuildFrom` value - * defined in object `Vector`. * @define orderDependent * @define orderDependentFold * @define mayNotTerminateInf From 0afba9dad13647765f3e54550b25229c8a720405 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Guillaume=20Mass=C3=A9?= Date: Wed, 1 Aug 2018 15:05:42 +0200 Subject: [PATCH 103/143] Unsorted return the most precise collection (fix scala/bug#11037) --- src/library/scala/collection/BitSet.scala | 3 ++ .../scala/collection/immutable/BitSet.scala | 2 ++ .../collection/immutable/SortedMap.scala | 4 +++ .../collection/immutable/SortedSet.scala | 7 ++++- .../scala/collection/mutable/BitSet.scala | 2 ++ .../scala/collection/mutable/SortedMap.scala | 7 ++++- .../scala/collection/mutable/SortedSet.scala | 7 ++++- .../junit/scala/collection/UnsortedTest.scala | 30 +++++++++++++++++++ 8 files changed, 59 insertions(+), 3 deletions(-) create mode 100644 test/junit/scala/collection/UnsortedTest.scala diff --git a/src/library/scala/collection/BitSet.scala b/src/library/scala/collection/BitSet.scala index 1a51ab7e1aa2..ec374a31788c 100644 --- a/src/library/scala/collection/BitSet.scala +++ b/src/library/scala/collection/BitSet.scala @@ -24,6 +24,7 @@ trait BitSet extends SortedSet[Int] with BitSetOps[BitSet] { override protected def newSpecificBuilder: Builder[Int, BitSetC] = bitSetFactory.newBuilder override def empty: BitSetC = bitSetFactory.empty override protected[this] def stringPrefix = "BitSet" + override def unsorted: Set[Int] = this } @SerialVersionUID(3L) @@ -73,6 +74,8 @@ trait BitSetOps[+C <: BitSet with BitSetOps[C]] def bitSetFactory: SpecificIterableFactory[Int, BitSetC] + def unsorted: Set[Int] + /** * Type alias to `C`. It is used to provide a default implementation of the `fromSpecificIterable` * and `newSpecificBuilder` operations. diff --git a/src/library/scala/collection/immutable/BitSet.scala b/src/library/scala/collection/immutable/BitSet.scala index a5b20cb236f7..3382048e05c5 100644 --- a/src/library/scala/collection/immutable/BitSet.scala +++ b/src/library/scala/collection/immutable/BitSet.scala @@ -25,6 +25,8 @@ sealed abstract class BitSet with StrictOptimizedIterableOps[Int, Set, BitSet] with StrictOptimizedSortedSetOps[Int, SortedSet, BitSet] { + override def unsorted: Set[Int] = this + def bitSetFactory = BitSet protected[collection] def fromBitMaskNoCopy(elems: Array[Long]): BitSet = BitSet.fromBitMaskNoCopy(elems) diff --git a/src/library/scala/collection/immutable/SortedMap.scala b/src/library/scala/collection/immutable/SortedMap.scala index 606c9d671ac4..36442f1b305d 100644 --- a/src/library/scala/collection/immutable/SortedMap.scala +++ b/src/library/scala/collection/immutable/SortedMap.scala @@ -11,6 +11,8 @@ trait SortedMap[K, +V] with collection.SortedMap[K, V] with SortedMapOps[K, V, SortedMap, SortedMap[K, V]] { + override def unsorted: Map[K, V] = this + override def sortedMapFactory: SortedMapFactory[SortedMapCC] = SortedMap /** The same map with a given default function. @@ -41,6 +43,8 @@ trait SortedMapOps[K, +V, +CC[X, +Y] <: Map[X, Y] with SortedMapOps[X, Y, CC, _] with collection.SortedMapOps[K, V, CC, C] { self => protected def coll: C with CC[K, V] + def unsorted: Map[K, V] + override def keySet: SortedSet[K] = new ImmutableKeySortedSet /** The implementation class of the set returned by `keySet` */ diff --git a/src/library/scala/collection/immutable/SortedSet.scala b/src/library/scala/collection/immutable/SortedSet.scala index e58524cafa7a..ac49cd35a411 100644 --- a/src/library/scala/collection/immutable/SortedSet.scala +++ b/src/library/scala/collection/immutable/SortedSet.scala @@ -10,6 +10,8 @@ trait SortedSet[A] with collection.SortedSet[A] with SortedSetOps[A, SortedSet, SortedSet[A]] { + override def unsorted: Set[A] = this + override def sortedIterableFactory: SortedIterableFactory[SortedIterableCC] = SortedSet } @@ -19,7 +21,10 @@ trait SortedSet[A] */ trait SortedSetOps[A, +CC[X] <: SortedSet[X], +C <: SortedSetOps[A, CC, C]] extends SetOps[A, Set, C] - with collection.SortedSetOps[A, CC, C] + with collection.SortedSetOps[A, CC, C] { + + def unsorted: Set[A] +} /** * $factoryInfo diff --git a/src/library/scala/collection/mutable/BitSet.scala b/src/library/scala/collection/mutable/BitSet.scala index a79b5e4626e3..055010645f28 100644 --- a/src/library/scala/collection/mutable/BitSet.scala +++ b/src/library/scala/collection/mutable/BitSet.scala @@ -39,6 +39,8 @@ class BitSet(protected[collection] final var elems: Array[Long]) def bitSetFactory = BitSet + override def unsorted: Set[Int] = this + protected[collection] final def nwords: Int = elems.length protected[collection] final def word(idx: Int): Long = diff --git a/src/library/scala/collection/mutable/SortedMap.scala b/src/library/scala/collection/mutable/SortedMap.scala index 68715e155979..7f0d88c99b38 100644 --- a/src/library/scala/collection/mutable/SortedMap.scala +++ b/src/library/scala/collection/mutable/SortedMap.scala @@ -12,6 +12,8 @@ trait SortedMap[K, V] with Map[K, V] with SortedMapOps[K, V, SortedMap, SortedMap[K, V]] { + override def unsorted: Map[K, V] = this + override def sortedMapFactory: SortedMapFactory[SortedMapCC] = SortedMap /** The same sorted map with a given default function. @@ -39,7 +41,10 @@ trait SortedMap[K, V] trait SortedMapOps[K, V, +CC[X, Y] <: Map[X, Y] with SortedMapOps[X, Y, CC, _], +C <: SortedMapOps[K, V, CC, C]] extends collection.SortedMapOps[K, V, CC, C] - with MapOps[K, V, Map, C] + with MapOps[K, V, Map, C] { + + def unsorted: Map[K, V] +} @SerialVersionUID(3L) object SortedMap extends SortedMapFactory.Delegate[SortedMap](TreeMap) { diff --git a/src/library/scala/collection/mutable/SortedSet.scala b/src/library/scala/collection/mutable/SortedSet.scala index 6d8b60c110ad..e80fdf3866ab 100644 --- a/src/library/scala/collection/mutable/SortedSet.scala +++ b/src/library/scala/collection/mutable/SortedSet.scala @@ -12,6 +12,8 @@ trait SortedSet[A] with collection.SortedSet[A] with SortedSetOps[A, SortedSet, SortedSet[A]] { + override def unsorted: Set[A] = this + override def sortedIterableFactory: SortedIterableFactory[SortedIterableCC] = SortedSet } @@ -21,7 +23,10 @@ trait SortedSet[A] */ trait SortedSetOps[A, +CC[X] <: SortedSet[X], +C <: SortedSetOps[A, CC, C]] extends SetOps[A, Set, C] - with collection.SortedSetOps[A, CC, C] + with collection.SortedSetOps[A, CC, C] { + + def unsorted: Set[A] +} /** * $factoryInfo diff --git a/test/junit/scala/collection/UnsortedTest.scala b/test/junit/scala/collection/UnsortedTest.scala new file mode 100644 index 000000000000..e18181ba22ae --- /dev/null +++ b/test/junit/scala/collection/UnsortedTest.scala @@ -0,0 +1,30 @@ +package scala.collection + +import org.junit.Test +import org.junit.runner.RunWith +import org.junit.runners.JUnit4 + +import scala.{collection => c} +import scala.collection.{immutable => i, mutable => m} + +@RunWith(classOf[JUnit4]) +class UnsortedTest { + @Test + def usortedIsSpecific(): Unit = { + c.BitSet(1).unsorted: c.Set[Int] + c.SortedMap(1 -> 1).unsorted: c.Map[Int, Int] + c.SortedSet(1).unsorted: c.Set[Int] + i.BitSet(1).unsorted: i.Set[Int] + + i.SortedMap(1 -> 1).unsorted: i.Map[Int, Int] + i.SortedSet(1).unsorted: i.Set[Int] + i.TreeMap(1 -> 1).unsorted: i.Map[Int, Int] + i.TreeSet(1).unsorted: i.Set[Int] + + m.BitSet(1).unsorted: m.Set[Int] + m.SortedMap(1 -> 1).unsorted: m.Map[Int, Int] + m.SortedSet(1).unsorted: m.Set[Int] + m.TreeMap(1 -> 1).unsorted: m.Map[Int, Int] + m.TreeSet(1).unsorted: m.Set[Int] + } +} From 30870007d3537af43e24e331dec7975d43eb4293 Mon Sep 17 00:00:00 2001 From: Jason Zaugg Date: Thu, 2 Aug 2018 12:32:42 +1000 Subject: [PATCH 104/143] Fix the build so setupPublishCore enabled the optimizer Regressed in #6964 Before: ``` $ sbt setupPublishCore 'show library/scalacOptions' 'show reflect/scalacOptions' 'show compiler/test:scalacOptions' 'show test/scalacOptions' [info] Loading global plugins from /Users/jz/.sbt/0.13/plugins [info] Loading project definition from /Users/jz/code/scala/project/project [info] Loading project definition from /Users/jz/code/scala/project [info] Resolving key references (11393 settings) ... [info] *** Welcome to the sbt build definition for Scala! *** [info] Check README.md for more information. [info] *** Welcome to the sbt build definition for Scala! *** [info] Check README.md for more information. [info] * -Xlint:-nullary-override,-inaccessible,_ [success] Total time: 0 s, completed 02/08/2018 12:33:38 PM [info] * -Xlint:-nullary-override,-inaccessible,_ [success] Total time: 0 s, completed 02/08/2018 12:33:38 PM [info] * -Xlint:-nullary-override,-inaccessible,_ [success] Total time: 0 s, completed 02/08/2018 12:33:38 PM [info] * [success] Total time: 0 s, completed 02/08/2018 12:33:38 PM ``` After: ``` $ sbt setupPublishCore 'show library/scalacOptions' 'show reflect/scalacOptions' 'show compiler/test:scalacOptions' 'show test/scalacOptions' [info] Loading global plugins from /Users/jz/.sbt/0.13/plugins [info] Loading project definition from /Users/jz/code/scala/project/project [info] Loading project definition from /Users/jz/code/scala/project [info] Resolving key references (11393 settings) ... [info] *** Welcome to the sbt build definition for Scala! *** [info] Check README.md for more information. [info] *** Welcome to the sbt build definition for Scala! *** [info] Check README.md for more information. [info] * -opt:l:inline [info] * -opt-inline-from:scala/** [info] * -Xlint:-nullary-override,-inaccessible,_ [info] * -sourcepath [info] * /Users/jz/code/scala/src/library [success] Total time: 0 s, completed 02/08/2018 12:31:18 PM [info] * -opt:l:inline [info] * -opt-inline-from:scala/** [info] * -Xlint:-nullary-override,-inaccessible,_ [success] Total time: 0 s, completed 02/08/2018 12:31:18 PM [info] * -opt:l:inline [info] * -opt-inline-from:scala/** [info] * -Xlint:-nullary-override,-inaccessible,_ [success] Total time: 0 s, completed 02/08/2018 12:31:18 PM [info] * -opt:l:inline [info] * -opt-inline-from:scala/** [success] Total time: 0 s, completed 02/08/2018 12:31:18 PM ``` --- build.sbt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/build.sbt b/build.sbt index a4a9eea6c91c..125118874088 100644 --- a/build.sbt +++ b/build.sbt @@ -157,7 +157,7 @@ lazy val commonSettings = instanceSettings ++ clearSourceAndResourceDirectories // END: Copy/pasted from SBT }, fork in run := true, - scalacOptions += "-Xlint:-nullary-override,-inaccessible,_", + scalacOptions in Compile += "-Xlint:-nullary-override,-inaccessible,_", //scalacOptions ++= Seq("-Xmaxerrs", "5", "-Xmaxwarns", "5"), scalacOptions in Compile in doc ++= Seq( "-doc-footer", "epfl", @@ -606,7 +606,7 @@ lazy val junit = project.in(file("test") / "junit") .dependsOn(library, reflect, compiler, partest, scaladoc) .settings(clearSourceAndResourceDirectories) .settings(commonSettings) - .settings(scalacOptions += "-Xlint:-nullary-unit,-adapted-args") + .settings(scalacOptions in Compile += "-Xlint:-nullary-unit,-adapted-args") .settings(disableDocs) .settings(disablePublishing) .settings( @@ -714,7 +714,7 @@ lazy val test = project .disablePlugins(plugins.JUnitXmlReportPlugin) .configs(IntegrationTest) .settings(commonSettings) - .settings(scalacOptions -= "-Xlint:-nullary-override,-inaccessible,_") + .settings(scalacOptions in Compile -= "-Xlint:-nullary-override,-inaccessible,_") .settings(disableDocs) .settings(disablePublishing) .settings(Defaults.itSettings) From 2e16c5d9b7df37dca0435ae5618ee66ddf5c9920 Mon Sep 17 00:00:00 2001 From: xuwei-k <6b656e6a69@gmail.com> Date: Thu, 2 Aug 2018 14:01:22 +0900 Subject: [PATCH 105/143] fix NegativeArraySizeException `StringOps#*` ``` Welcome to Scala 2.12.6 (Java HotSpot(TM) 64-Bit Server VM, Java 1.8.0_181). Type in expressions for evaluation. Or try :help. scala> "a" * -1 res0: String = "" ``` ``` Welcome to Scala 2.13.0-M4 (Java HotSpot(TM) 64-Bit Server VM, Java 1.8.0_181). Type in expressions for evaluation. Or try :help. scala> "a" * -1 java.lang.NegativeArraySizeException at java.lang.AbstractStringBuilder.(AbstractStringBuilder.java:68) at java.lang.StringBuilder.(StringBuilder.java:101) at scala.collection.StringOps$.$times$extension(StringOps.scala:555) ... 30 elided ``` --- src/library/scala/collection/StringOps.scala | 16 ++++++++++------ test/junit/scala/collection/StringOpsTest.scala | 7 +++++++ 2 files changed, 17 insertions(+), 6 deletions(-) diff --git a/src/library/scala/collection/StringOps.scala b/src/library/scala/collection/StringOps.scala index fa87465e22b0..b34ba95ac168 100644 --- a/src/library/scala/collection/StringOps.scala +++ b/src/library/scala/collection/StringOps.scala @@ -563,13 +563,17 @@ final class StringOps(private val s: String) extends AnyVal { /** Return the current string concatenated `n` times. */ def *(n: Int): String = { - val sb = new JStringBuilder(s.length * n) - var i = 0 - while (i < n) { - sb.append(s) - i += 1 + if (n <= 0) { + "" + } else { + val sb = new JStringBuilder(s.length * n) + var i = 0 + while (i < n) { + sb.append(s) + i += 1 + } + sb.toString } - sb.toString } @inline private[this] def isLineBreak(c: Char) = c == LF || c == FF diff --git a/test/junit/scala/collection/StringOpsTest.scala b/test/junit/scala/collection/StringOpsTest.scala index 6884e49684ea..bbc194a4f6c9 100644 --- a/test/junit/scala/collection/StringOpsTest.scala +++ b/test/junit/scala/collection/StringOpsTest.scala @@ -1,5 +1,6 @@ package scala.collection +import org.junit.Assert.assertEquals import org.junit.Test import org.junit.runner.RunWith import org.junit.runners.JUnit4 @@ -24,4 +25,10 @@ class StringOpsTest { @Test def toArray(): Unit = { assert("".toArray[Any].length == 0) // should not throw } + + @Test def *(): Unit = { + assertEquals("aaa", "a" * 3) + assertEquals("", "a" * 0) + assertEquals("", "a" * -1) + } } From f24fbcabc3aa2bec9a8fa358e87d79dd3fef0271 Mon Sep 17 00:00:00 2001 From: Allan Renucci Date: Thu, 26 Jul 2018 18:58:24 +0200 Subject: [PATCH 106/143] Remove some abstract overrides If a concrete members is overridden by an abstract member, children must provide an implementation in Dotty. See lampepfl/dotty#4770 --- src/library/scala/collection/Seq.scala | 5 ----- src/library/scala/reflect/ClassManifestDeprecatedApis.scala | 3 --- src/library/scala/reflect/ClassTag.scala | 3 ++- 3 files changed, 2 insertions(+), 9 deletions(-) diff --git a/src/library/scala/collection/Seq.scala b/src/library/scala/collection/Seq.scala index ad7d8061b8b4..204b4dc0a9f1 100644 --- a/src/library/scala/collection/Seq.scala +++ b/src/library/scala/collection/Seq.scala @@ -82,11 +82,6 @@ trait SeqOps[+A, +CC[_], +C] extends Any /** The length (number of elements) of the $coll. `size` is an alias for `length` in `Seq` collections. */ def length: Int - /** - * @return This collection as a `Seq[A]`. This is equivalent to `to(Seq)` but might be faster. - */ - def toSeq: immutable.Seq[A] - /** A copy of the $coll with an element prepended. * * Also, the original $coll is not modified, so you will want to capture the result. diff --git a/src/library/scala/reflect/ClassManifestDeprecatedApis.scala b/src/library/scala/reflect/ClassManifestDeprecatedApis.scala index 96f68be08b04..a36eef9aeadc 100644 --- a/src/library/scala/reflect/ClassManifestDeprecatedApis.scala +++ b/src/library/scala/reflect/ClassManifestDeprecatedApis.scala @@ -94,9 +94,6 @@ trait ClassManifestDeprecatedApis[T] extends OptManifest[T] { def arrayManifest: ClassManifest[Array[T]] = ClassManifest.classType[Array[T]](arrayClass[T](runtimeClass), this) - override def newArray(len: Int): Array[T] = - java.lang.reflect.Array.newInstance(runtimeClass, len).asInstanceOf[Array[T]] - @deprecated("use wrap.newArray instead", "2.10.0") def newArray2(len: Int): Array[Array[T]] = java.lang.reflect.Array.newInstance(arrayClass[T](runtimeClass), len) diff --git a/src/library/scala/reflect/ClassTag.scala b/src/library/scala/reflect/ClassTag.scala index c1f178c5339a..3bb1e5c6e93f 100644 --- a/src/library/scala/reflect/ClassTag.scala +++ b/src/library/scala/reflect/ClassTag.scala @@ -46,7 +46,8 @@ trait ClassTag[T] extends ClassManifestDeprecatedApis[T] with Equals with Serial def wrap: ClassTag[Array[T]] = ClassTag[Array[T]](arrayClass(runtimeClass)) /** Produces a new array with element type `T` and length `len` */ - override def newArray(len: Int): Array[T] + def newArray(len: Int): Array[T] = + java.lang.reflect.Array.newInstance(runtimeClass, len).asInstanceOf[Array[T]] /** A ClassTag[T] can serve as an extractor that matches only objects of type T. * From 713f07d36e72e8bb7b2c1a2cac3bab25e369237b Mon Sep 17 00:00:00 2001 From: Miles Sabin Date: Fri, 3 Aug 2018 10:09:30 +0100 Subject: [PATCH 107/143] Literal/constant-typed local lazy vals need refined values. (#6454) Literal/constant-typed local lazy vals need refined values. Compiling the following, object Test { type Id[T] = T def foo(x: Int): Id[x.type] = x { lazy val result: 1 = foo(1) } } crashes with an unexpected type error during the Fields phase, error: scala.reflect.internal.Types$TypeError: type mismatch; found : Int required: 1 This is because the translation of the local lazy val in Fields maps to a `LazyInt` which holds an `Int` value. This is too wide to assign to the `1`-typed val and results in a type error when the tree synthesized during Fields phase is typechecked. I've fixed this by inserting a cast to the narrower type, which is eliminated during erasure. In principle we could switch to a scheme similar to LazyUnit for literal typed local lazy vals, ie. eliminating the storage for the value whilst retaining the effects, but this seems like an unlikely enough scenario to warrant the additional complexity that this optimization would entail. This fixes scala/bug#10792. --- .../scala/tools/nsc/transform/Fields.scala | 15 +++++++++++---- test/files/pos/t10792.scala | 6 ++++++ 2 files changed, 17 insertions(+), 4 deletions(-) create mode 100644 test/files/pos/t10792.scala diff --git a/src/compiler/scala/tools/nsc/transform/Fields.scala b/src/compiler/scala/tools/nsc/transform/Fields.scala index b69679a6c1dd..aec6d884c5ab 100644 --- a/src/compiler/scala/tools/nsc/transform/Fields.scala +++ b/src/compiler/scala/tools/nsc/transform/Fields.scala @@ -593,9 +593,15 @@ abstract class Fields extends InfoTransform with ast.TreeDSL with TypingTransfor // LazyUnit does not have a `value` member val valueSym = if (isUnit) NoSymbol else refTpe.member(nme.value) + def refineLiteral(tree: Tree): Tree = + lazyValType match { + case _: ConstantType => gen.mkAsInstanceOf(tree, lazyValType) + case _ => tree + } + def initialized = Select(Ident(holderSym), initializedSym) def initialize = Select(Ident(holderSym), initializeSym) - def getValue = if (isUnit) UNIT else Apply(Select(Ident(holderSym), valueSym), Nil) + def getValue = if (isUnit) UNIT else refineLiteral(Apply(Select(Ident(holderSym), valueSym), Nil)) val computerSym = owner.newMethod(lazyName append nme.LAZY_SLOW_SUFFIX, pos, ARTIFACT | PRIVATE) setInfo MethodType(Nil, lazyValType) @@ -605,11 +611,12 @@ abstract class Fields extends InfoTransform with ast.TreeDSL with TypingTransfor val computer = mkAccessor(computerSym)(gen.mkSynchronized(Ident(holderSym))( If(initialized, getValue, if (isUnit) Block(rhsAtComputer :: Nil, Apply(initialize, Nil)) - else Apply(initialize, rhsAtComputer :: Nil)))) + else refineLiteral(Apply(initialize, rhsAtComputer :: Nil))))) val accessor = mkAccessor(lazySym)( - If(initialized, getValue, - Apply(Ident(computerSym), Nil))) + refineLiteral( + If(initialized, getValue, + Apply(Ident(computerSym), Nil)))) // do last! // remove STABLE: prevent replacing accessor call of type Unit by BoxedUnit.UNIT in erasure diff --git a/test/files/pos/t10792.scala b/test/files/pos/t10792.scala new file mode 100644 index 000000000000..300f1ccd1ed7 --- /dev/null +++ b/test/files/pos/t10792.scala @@ -0,0 +1,6 @@ +object Test { + type Id[T] = T + def foo(x: Int): Id[x.type] = x + + { lazy val result: 1 = foo(1) } +} From 0895874589b326b85685365a2ba1e981a7ce8b4c Mon Sep 17 00:00:00 2001 From: Adriaan Moors Date: Fri, 3 Aug 2018 19:04:25 +0200 Subject: [PATCH 108/143] Update line numbers in check file --- test/files/neg/warn-unused-params.check | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/files/neg/warn-unused-params.check b/test/files/neg/warn-unused-params.check index f174961dbb94..3d82dc836e68 100644 --- a/test/files/neg/warn-unused-params.check +++ b/test/files/neg/warn-unused-params.check @@ -13,13 +13,13 @@ case class CaseyAtTheBat(k: Int)(s: String) // warn warn-unused-params.scala:64: warning: parameter value readResolve in method f is never used def f(readResolve: Int) = 42 // warn ^ -warn-unused-params.scala:77: warning: parameter value dummy in method g is never used +warn-unused-params.scala:79: warning: parameter value dummy in method g is never used def g(dummy: DummyImplicit) = 42 ^ -warn-unused-params.scala:82: warning: parameter value ev in method f2 is never used +warn-unused-params.scala:84: warning: parameter value ev in method f2 is never used def f2[A, B](ev: A =:= B) = 42 ^ -warn-unused-params.scala:83: warning: parameter value ev in method g2 is never used +warn-unused-params.scala:85: warning: parameter value ev in method g2 is never used def g2[A, B](ev: A <:< B) = 42 ^ error: No warnings can be incurred under -Xfatal-warnings. From b4843ae1c63ead001f0010a63a7012e2e765e623 Mon Sep 17 00:00:00 2001 From: Jason Zaugg Date: Tue, 21 Nov 2017 14:12:35 +1000 Subject: [PATCH 109/143] Fixup symbol ownership in eta expansion The fix for scala/bug#6274 did this selectively when function symbols were introduced, but we really ought to insert the eta$n temp vals into the owner chain of all lifted expressions. --- .../tools/nsc/typechecker/EtaExpansion.scala | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/src/compiler/scala/tools/nsc/typechecker/EtaExpansion.scala b/src/compiler/scala/tools/nsc/typechecker/EtaExpansion.scala index 1dbb9ab9371e..8724875d59f6 100644 --- a/src/compiler/scala/tools/nsc/typechecker/EtaExpansion.scala +++ b/src/compiler/scala/tools/nsc/typechecker/EtaExpansion.scala @@ -56,16 +56,22 @@ trait EtaExpansion { self: Analyzer => else { val vname: Name = freshName() // Problem with ticket #2351 here + val valSym = typer.context.owner.newValue(vname.toTermName, tree.pos.focus, SYNTHETIC) defs += atPos(tree.pos) { val rhs = if (byName) { - val res = typer.typed(Function(List(), tree)) - new ChangeOwnerTraverser(typer.context.owner, res.symbol) traverse tree // scala/bug#6274 - res - } else tree - ValDef(Modifiers(SYNTHETIC), vname.toTermName, TypeTree(), rhs) + val funSym = valSym.newAnonymousFunctionValue(tree.pos.focus) + val tree1 = tree.changeOwner(typer.context.owner -> funSym) + val funType = definitions.functionType(Nil, tree1.tpe) + funSym.setInfo(funType) + Function(List(), tree1).setSymbol(funSym).setType(funType) + } else { + tree.changeOwner(typer.context.owner -> valSym) + } + valSym.setInfo(rhs.tpe) + ValDef(valSym, rhs) } atPos(tree.pos.focus) { - if (byName) Apply(Ident(vname), List()) else Ident(vname) + if (byName) Apply(Ident(valSym), List()) else Ident(valSym) } } val tree1 = tree match { From 05555e88c05e949f5ccfecd0d92000e86133e4fd Mon Sep 17 00:00:00 2001 From: Adriaan Moors Date: Fri, 3 Aug 2018 16:50:03 +0200 Subject: [PATCH 110/143] Eta-expansion doesn't need full typer Based on review by lrytz --- .../scala/tools/nsc/typechecker/EtaExpansion.scala | 11 ++++++----- src/compiler/scala/tools/nsc/typechecker/Typers.scala | 2 +- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/src/compiler/scala/tools/nsc/typechecker/EtaExpansion.scala b/src/compiler/scala/tools/nsc/typechecker/EtaExpansion.scala index 8724875d59f6..48f0040085e4 100644 --- a/src/compiler/scala/tools/nsc/typechecker/EtaExpansion.scala +++ b/src/compiler/scala/tools/nsc/typechecker/EtaExpansion.scala @@ -7,6 +7,7 @@ package scala.tools.nsc package typechecker import scala.collection.mutable.ListBuffer +import scala.reflect.internal.util.FreshNameCreator import symtab.Flags._ /** This trait ... @@ -38,12 +39,12 @@ trait EtaExpansion { self: Analyzer => * - typedEta (when type checking a method value, `m _`). * **/ - def etaExpand(unit: CompilationUnit, tree: Tree, typer: Typer): Tree = { + def etaExpand(unit: CompilationUnit, tree: Tree, owner: Symbol)(implicit creator: FreshNameCreator): Tree = { val tpe = tree.tpe var cnt = 0 // for NoPosition def freshName() = { cnt += 1 - freshTermName("eta$" + (cnt - 1) + "$")(typer.fresh) + freshTermName("eta$" + (cnt - 1) + "$") } val defs = new ListBuffer[Tree] @@ -56,16 +57,16 @@ trait EtaExpansion { self: Analyzer => else { val vname: Name = freshName() // Problem with ticket #2351 here - val valSym = typer.context.owner.newValue(vname.toTermName, tree.pos.focus, SYNTHETIC) + val valSym = owner.newValue(vname.toTermName, tree.pos.focus, SYNTHETIC) defs += atPos(tree.pos) { val rhs = if (byName) { val funSym = valSym.newAnonymousFunctionValue(tree.pos.focus) - val tree1 = tree.changeOwner(typer.context.owner -> funSym) + val tree1 = tree.changeOwner(owner -> funSym) val funType = definitions.functionType(Nil, tree1.tpe) funSym.setInfo(funType) Function(List(), tree1).setSymbol(funSym).setType(funType) } else { - tree.changeOwner(typer.context.owner -> valSym) + tree.changeOwner(owner -> valSym) } valSym.setInfo(rhs.tpe) ValDef(valSym, rhs) diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala index 387ab013d392..db7fbd49269b 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala @@ -3053,7 +3053,7 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper if (tree.tpe.isDependentMethodType) DependentMethodTpeConversionToFunctionError(tree, tree.tpe) // TODO: support this else { - val expansion = etaExpand(context.unit, tree, this) + val expansion = etaExpand(context.unit, tree, context.owner) if (context.undetparams.isEmpty) typed(expansion, mode, pt) else instantiate(typed(expansion, mode), mode, pt) } From f1bb47164a6802a6280c566502fdde90dd68696f Mon Sep 17 00:00:00 2001 From: Allan Renucci Date: Fri, 3 Aug 2018 11:50:23 +0200 Subject: [PATCH 111/143] Followup to #6984 It seems I forgot to update some definitions and use sites --- .../scala/collection/mutable/StringBuilder.scala | 2 +- src/library/scala/math/Numeric.scala | 14 +++++++------- src/library/scala/runtime/RichInt.scala | 2 +- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/library/scala/collection/mutable/StringBuilder.scala b/src/library/scala/collection/mutable/StringBuilder.scala index 72bd1d47462b..56f34ace5273 100644 --- a/src/library/scala/collection/mutable/StringBuilder.scala +++ b/src/library/scala/collection/mutable/StringBuilder.scala @@ -79,7 +79,7 @@ final class StringBuilder(val underlying: java.lang.StringBuilder) extends Abstr def result() = underlying.toString - override def toString = result + override def toString = result() override def toArray[B >: Char](implicit ct: scala.reflect.ClassTag[B]) = ct.runtimeClass match { diff --git a/src/library/scala/math/Numeric.scala b/src/library/scala/math/Numeric.scala index fc4f6043b314..60106ab2ddee 100644 --- a/src/library/scala/math/Numeric.scala +++ b/src/library/scala/math/Numeric.scala @@ -212,13 +212,13 @@ trait Numeric[T] extends Ordering[T] { def +(rhs: T) = plus(lhs, rhs) def -(rhs: T) = minus(lhs, rhs) def *(rhs: T) = times(lhs, rhs) - def unary_-() = negate(lhs) - def abs(): T = Numeric.this.abs(lhs) - def signum(): Int = Numeric.this.signum(lhs) - def toInt(): Int = Numeric.this.toInt(lhs) - def toLong(): Long = Numeric.this.toLong(lhs) - def toFloat(): Float = Numeric.this.toFloat(lhs) - def toDouble(): Double = Numeric.this.toDouble(lhs) + def unary_- = negate(lhs) + def abs: T = Numeric.this.abs(lhs) + def signum: Int = Numeric.this.signum(lhs) + def toInt: Int = Numeric.this.toInt(lhs) + def toLong: Long = Numeric.this.toLong(lhs) + def toFloat: Float = Numeric.this.toFloat(lhs) + def toDouble: Double = Numeric.this.toDouble(lhs) } implicit def mkNumericOps(lhs: T): NumericOps = new NumericOps(lhs) } diff --git a/src/library/scala/runtime/RichInt.scala b/src/library/scala/runtime/RichInt.scala index 327017f2d01a..9ba1f2bc5ceb 100644 --- a/src/library/scala/runtime/RichInt.scala +++ b/src/library/scala/runtime/RichInt.scala @@ -27,7 +27,7 @@ final class RichInt(val self: Int) extends AnyVal with ScalaNumberProxy[Int] wit /** Returns `'''true'''` if this number has no decimal component. * Always `'''true'''` for `RichInt`. */ - def isWhole() = true + def isWhole = true override def isValidInt = true def isValidLong = true From 469f3899b8c4f9a598e399fcbaf63d4411583545 Mon Sep 17 00:00:00 2001 From: xuwei-k <6b656e6a69@gmail.com> Date: Wed, 18 Jul 2018 01:14:11 +0900 Subject: [PATCH 112/143] fix ArrayOps#collect parameter name --- src/library/scala/collection/ArrayOps.scala | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/library/scala/collection/ArrayOps.scala b/src/library/scala/collection/ArrayOps.scala index af5891e89406..eb72a5235843 100644 --- a/src/library/scala/collection/ArrayOps.scala +++ b/src/library/scala/collection/ArrayOps.scala @@ -848,7 +848,7 @@ final class ArrayOps[A](val xs: Array[A]) extends AnyVal { * `pf` to each element on which it is defined and collecting the results. * The order of the elements is preserved. */ - def collect[B : ClassTag](f: PartialFunction[A, B]): Array[B] = { + def collect[B : ClassTag](pf: PartialFunction[A, B]): Array[B] = { var i = 0 var matched = true def d(x: A): B = { @@ -858,7 +858,7 @@ final class ArrayOps[A](val xs: Array[A]) extends AnyVal { val b = ArrayBuilder.make[B] while(i < xs.length) { matched = true - val v = f.applyOrElse(xs(i), d) + val v = pf.applyOrElse(xs(i), d) if(matched) b += v i += 1 } From 9a6b2890712dd2927f9cb5d92bf2e069a91a8ccd Mon Sep 17 00:00:00 2001 From: Som Snytt Date: Sat, 4 Aug 2018 14:41:18 -0700 Subject: [PATCH 113/143] Disable nonlocal return warning --- build.sbt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/build.sbt b/build.sbt index 125118874088..477fe948c1c9 100644 --- a/build.sbt +++ b/build.sbt @@ -157,7 +157,7 @@ lazy val commonSettings = instanceSettings ++ clearSourceAndResourceDirectories // END: Copy/pasted from SBT }, fork in run := true, - scalacOptions in Compile += "-Xlint:-nullary-override,-inaccessible,_", + scalacOptions in Compile += "-Xlint:-nullary-override,-inaccessible,-nonlocal-return,_", //scalacOptions ++= Seq("-Xmaxerrs", "5", "-Xmaxwarns", "5"), scalacOptions in Compile in doc ++= Seq( "-doc-footer", "epfl", @@ -714,7 +714,7 @@ lazy val test = project .disablePlugins(plugins.JUnitXmlReportPlugin) .configs(IntegrationTest) .settings(commonSettings) - .settings(scalacOptions in Compile -= "-Xlint:-nullary-override,-inaccessible,_") + .settings(scalacOptions in Compile -= "-Xlint:-nullary-override,-inaccessible,-nonlocal-return,_") // as in common settings .settings(disableDocs) .settings(disablePublishing) .settings(Defaults.itSettings) From 95fdf4481c4628582edf67325b290d70e578494c Mon Sep 17 00:00:00 2001 From: Som Snytt Date: Sat, 4 Aug 2018 14:49:14 -0700 Subject: [PATCH 114/143] Unused elements in partest --- .../scala/tools/partest/nest/AbstractRunner.scala | 3 +-- .../scala/tools/partest/nest/PathSettings.scala | 4 ++-- src/partest/scala/tools/partest/nest/Runner.scala | 10 +++------- 3 files changed, 6 insertions(+), 11 deletions(-) diff --git a/src/partest/scala/tools/partest/nest/AbstractRunner.scala b/src/partest/scala/tools/partest/nest/AbstractRunner.scala index d80b3a9438dd..2a3caecadd74 100644 --- a/src/partest/scala/tools/partest/nest/AbstractRunner.scala +++ b/src/partest/scala/tools/partest/nest/AbstractRunner.scala @@ -11,8 +11,7 @@ import utils.Properties._ import scala.tools.nsc.Properties.{propOrFalse, setProp, versionMsg} import scala.collection.mutable import scala.reflect.internal.util.Collections.distinctBy -import scala.util.{ Try, Success, Failure } -import scala.concurrent.duration.Duration +import scala.util.{Try, Success, Failure} import java.util.concurrent.Executors import java.util.concurrent.TimeUnit import java.util.concurrent.TimeUnit.NANOSECONDS diff --git a/src/partest/scala/tools/partest/nest/PathSettings.scala b/src/partest/scala/tools/partest/nest/PathSettings.scala index ae13d3616775..fb68f4975f33 100644 --- a/src/partest/scala/tools/partest/nest/PathSettings.scala +++ b/src/partest/scala/tools/partest/nest/PathSettings.scala @@ -5,8 +5,8 @@ package scala.tools.partest package nest -import scala.tools.nsc.io.{ Path, File, Directory } -import scala.tools.nsc.Properties.{ propOrNone } +import scala.tools.nsc.io.{Directory, File} +import scala.tools.nsc.Properties.propOrNone /** Get current value for path settings. * Default values are read from system properties `partest.srcdir` and `partest.root`. diff --git a/src/partest/scala/tools/partest/nest/Runner.scala b/src/partest/scala/tools/partest/nest/Runner.scala index a2383f5ecc0a..df64e28e47ca 100644 --- a/src/partest/scala/tools/partest/nest/Runner.scala +++ b/src/partest/scala/tools/partest/nest/Runner.scala @@ -9,22 +9,18 @@ import java.io.{Console => _, _} import java.lang.reflect.InvocationTargetException import java.nio.charset.Charset import java.nio.file.{Files, StandardOpenOption} -import java.util.concurrent.Executors -import java.util.concurrent.TimeUnit -import java.util.concurrent.TimeUnit.NANOSECONDS import scala.collection.mutable.ListBuffer import scala.concurrent.duration.Duration import scala.reflect.internal.FatalError import scala.reflect.internal.util.ScalaClassLoader import scala.sys.process.{Process, ProcessLogger} -import scala.tools.nsc.Properties.{isWin, javaHome, javaVmInfo, javaVmName, javaVmVersion, propOrEmpty, versionMsg} +import scala.tools.nsc.Properties.{isWin, propOrEmpty} import scala.tools.nsc.{CompilerCommand, Global, Settings} import scala.tools.nsc.reporters.ConsoleReporter import scala.tools.nsc.util.stackTraceString -import scala.util.{Failure, Success, Try} import ClassPath.join -import TestState.{Crash, Fail, Pass, Skip, Uninitialized, Updated} +import TestState.{Crash, Fail, Pass, Skip, Updated} import FileManager.{compareContents, joinPaths, withTempFile} import scala.reflect.internal.util.ScalaClassLoader.URLClassLoader import scala.util.control.ControlThrowable @@ -625,7 +621,7 @@ class Runner(val testInfo: TestInfo, val suiteRunner: AbstractRunner) { // res/t687.res depends on ignoring its compilation failure // and just looking at the diff, so I made them all do that // because this is long enough. - val res = Output.withRedirected(logWriter)(try loop() finally resReader.close()) + /*val res =*/ Output.withRedirected(logWriter)(try loop() finally resReader.close()) /*res andAlso*/ diffIsOk } From 87defdeadc78cfc8d4f1e2dff3ead5bd9cdd7d3f Mon Sep 17 00:00:00 2001 From: Som Snytt Date: Sat, 4 Aug 2018 14:55:43 -0700 Subject: [PATCH 115/143] Internal picadillos Overriding methods "inherit" an empty parameter list, so unit methods receive one at the top declaration. --- src/reflect/scala/reflect/internal/Types.scala | 2 +- src/reflect/scala/reflect/internal/util/WeakHashSet.scala | 2 +- .../scala/tools/nsc/doc/model/diagram/DiagramFactory.scala | 1 - 3 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/reflect/scala/reflect/internal/Types.scala b/src/reflect/scala/reflect/internal/Types.scala index 23bcbd75e5c9..57a92735685f 100644 --- a/src/reflect/scala/reflect/internal/Types.scala +++ b/src/reflect/scala/reflect/internal/Types.scala @@ -318,7 +318,7 @@ trait Types /** If this is a lazy type corresponding to a subclass add it to its * parents children */ - def forceDirectSuperclasses: Unit = () + def forceDirectSuperclasses(): Unit = () /** The term symbol associated with the type * Note that the symbol of the normalized type is returned (@see normalize) diff --git a/src/reflect/scala/reflect/internal/util/WeakHashSet.scala b/src/reflect/scala/reflect/internal/util/WeakHashSet.scala index 3a1fdc4fbf8d..d23dadc4621f 100644 --- a/src/reflect/scala/reflect/internal/util/WeakHashSet.scala +++ b/src/reflect/scala/reflect/internal/util/WeakHashSet.scala @@ -339,7 +339,7 @@ final class WeakHashSet[A <: AnyRef](val initialCapacity: Int, val loadFactor: D * the entries must be stable. If any are garbage collected during validation * then an assertion may inappropriately fire. */ - def fullyValidate: Unit = { + def fullyValidate(): Unit = { var computedCount = 0 var bucket = 0 while (bucket < table.size) { diff --git a/src/scaladoc/scala/tools/nsc/doc/model/diagram/DiagramFactory.scala b/src/scaladoc/scala/tools/nsc/doc/model/diagram/DiagramFactory.scala index f1545a4f335e..f11f502c88ef 100644 --- a/src/scaladoc/scala/tools/nsc/doc/model/diagram/DiagramFactory.scala +++ b/src/scaladoc/scala/tools/nsc/doc/model/diagram/DiagramFactory.scala @@ -19,7 +19,6 @@ trait DiagramFactory extends DiagramDirectiveParser { this: ModelFactory with ModelFactoryTypeSupport with DiagramFactory with CommentFactory with TreeFactory => import this.global.definitions._ - import this.global._ // the following can used for hardcoding different relations into the diagram, for bootstrapping purposes def aggregationNode(text: String) = From 06f83669a9c7266b861ffa493c96e8a44b844f5f Mon Sep 17 00:00:00 2001 From: Som Snytt Date: Sat, 4 Aug 2018 15:45:36 -0700 Subject: [PATCH 116/143] Collective imports Folks go to town with `empty`, even importing it twice. You can't have too much `empty`. Hopefully this doesn't annoy someone with a merge conflict. --- src/library/scala/collection/StrictOptimizedSortedSetOps.scala | 1 - src/library/scala/collection/immutable/ListSet.scala | 1 - src/library/scala/collection/immutable/Queue.scala | 1 - src/library/scala/collection/immutable/Set.scala | 1 - src/library/scala/collection/immutable/Vector.scala | 2 -- src/library/scala/collection/mutable/HashMap.scala | 3 +-- 6 files changed, 1 insertion(+), 8 deletions(-) diff --git a/src/library/scala/collection/StrictOptimizedSortedSetOps.scala b/src/library/scala/collection/StrictOptimizedSortedSetOps.scala index b9713f19b3ce..48a350275131 100644 --- a/src/library/scala/collection/StrictOptimizedSortedSetOps.scala +++ b/src/library/scala/collection/StrictOptimizedSortedSetOps.scala @@ -5,7 +5,6 @@ package collection import scala.annotation.implicitNotFound import scala.annotation.unchecked.uncheckedVariance import scala.language.higherKinds -import scala.runtime.Statics /** * Trait that overrides sorted set operations to take advantage of strict builders. diff --git a/src/library/scala/collection/immutable/ListSet.scala b/src/library/scala/collection/immutable/ListSet.scala index 8ce377c6acbf..5fedbd0a8ae0 100644 --- a/src/library/scala/collection/immutable/ListSet.scala +++ b/src/library/scala/collection/immutable/ListSet.scala @@ -6,7 +6,6 @@ import java.io.{ObjectInputStream, ObjectOutputStream} import mutable.{Builder, ImmutableBuilder} import scala.annotation.tailrec -import scala.collection.immutable.List.empty /** * This class implements immutable sets using a list-based data structure. List set iterators and diff --git a/src/library/scala/collection/immutable/Queue.scala b/src/library/scala/collection/immutable/Queue.scala index 5f85ee0bd97c..c27e8219147d 100644 --- a/src/library/scala/collection/immutable/Queue.scala +++ b/src/library/scala/collection/immutable/Queue.scala @@ -11,7 +11,6 @@ package immutable import java.io.{ObjectInputStream, ObjectOutputStream} -import scala.collection.immutable.List.empty import scala.collection.mutable.{Builder, ListBuffer} /** `Queue` objects implement data structures that allow to diff --git a/src/library/scala/collection/immutable/Set.scala b/src/library/scala/collection/immutable/Set.scala index 950da3c2fb2f..3f12d8028b00 100644 --- a/src/library/scala/collection/immutable/Set.scala +++ b/src/library/scala/collection/immutable/Set.scala @@ -4,7 +4,6 @@ package immutable import java.io.{ObjectInputStream, ObjectOutputStream} -import scala.collection.immutable.List.empty import scala.collection.mutable.{Builder, ImmutableBuilder} import scala.language.higherKinds diff --git a/src/library/scala/collection/immutable/Vector.scala b/src/library/scala/collection/immutable/Vector.scala index dbf0206460d2..eba281b44ac5 100644 --- a/src/library/scala/collection/immutable/Vector.scala +++ b/src/library/scala/collection/immutable/Vector.scala @@ -6,8 +6,6 @@ import java.io.{ObjectInputStream, ObjectOutputStream} import scala.collection.mutable.{Builder, ReusableBuilder} import scala.annotation.unchecked.uncheckedVariance -import scala.collection.immutable.List.empty -import scala.collection.immutable.Set.empty /** $factoryInfo * @define Coll `Vector` diff --git a/src/library/scala/collection/mutable/HashMap.scala b/src/library/scala/collection/mutable/HashMap.scala index 1d169cb596aa..3d72e369c798 100644 --- a/src/library/scala/collection/mutable/HashMap.scala +++ b/src/library/scala/collection/mutable/HashMap.scala @@ -1,8 +1,7 @@ package scala package collection.mutable -import scala.collection.{AbstractIterator, Iterator, MapFactory, StrictOptimizedIterableOps, StrictOptimizedMapOps} -import java.lang.String +import scala.collection.{Iterator, MapFactory, StrictOptimizedIterableOps, StrictOptimizedMapOps} /** This class implements mutable maps using a hashtable. * From a5d216351c023156047e285d4f531d873d65d8a0 Mon Sep 17 00:00:00 2001 From: Josh Lemer Date: Mon, 16 Jul 2018 19:01:51 -0400 Subject: [PATCH 117/143] [#8469] IterableOnce#copyToArray returns number of elements copied (Int) [#11048] Array and ArrayDeque copyToArray do not throw IndexOutOfBoundException [11048] Add junit tests for {Queue,mutable.Queue}.copyToArray --- src/library/scala/collection/ArrayOps.scala | 15 +++-- .../scala/collection/IterableOnce.scala | 42 ++++++++---- src/library/scala/collection/StringOps.scala | 32 +++++++--- .../scala/collection/immutable/ArraySeq.scala | 13 ++-- .../collection/mutable/ArrayBuffer.scala | 15 ++--- .../scala/collection/mutable/ArrayDeque.scala | 9 ++- .../scala/collection/mutable/ArraySeq.scala | 12 ++-- .../junit/scala/collection/ArrayOpsTest.scala | 6 ++ .../junit/scala/collection/IterableTest.scala | 64 +++++++++---------- .../junit/scala/collection/IteratorTest.scala | 52 +++++++-------- .../scala/collection/StringOpsTest.scala | 64 ++++++++++++++++++- .../collection/immutable/ArraySeqTest.scala | 5 ++ .../collection/immutable/QueueTest.scala | 18 +++++- .../collection/mutable/ArrayDequeTest.scala | 18 ++++-- .../scala/collection/mutable/QueueTest.scala | 8 ++- .../scala/tools/nsc/DeterminismTest.scala | 1 - 16 files changed, 252 insertions(+), 122 deletions(-) diff --git a/src/library/scala/collection/ArrayOps.scala b/src/library/scala/collection/ArrayOps.scala index af5891e89406..f00f73e398ea 100644 --- a/src/library/scala/collection/ArrayOps.scala +++ b/src/library/scala/collection/ArrayOps.scala @@ -1263,13 +1263,20 @@ final class ArrayOps[A](val xs: Array[A]) extends AnyVal { * @param len the maximal number of elements to copy. * @tparam B the type of the elements of the array. */ - def copyToArray[B >: A](dest: Array[B], start: Int, len: Int = Int.MaxValue): dest.type = { - Array.copy(xs, 0, dest, start, min(xs.length, min(dest.length-start, len))) - dest + def copyToArray[B >: A](dest: Array[B], start: Int, len: Int = Int.MaxValue): Int = { + val copied = IterableOnce.elemsToCopyToArray(xs.length, dest.length, start, len) + if (copied > 0) { + Array.copy(xs, 0, dest, start, copied) + } + copied } /** Create a copy of this array with the specified element type. */ - def toArray[B >: A: ClassTag]: Array[B] = copyToArray(new Array[B](xs.length), 0) + def toArray[B >: A: ClassTag]: Array[B] = { + val destination = new Array[B](xs.length) + copyToArray(destination, 0) + destination + } /** Counts the number of elements in this array which satisfy a predicate */ def count(p: A => Boolean): Int = { diff --git a/src/library/scala/collection/IterableOnce.scala b/src/library/scala/collection/IterableOnce.scala index 3e3ee6197e55..c58b89e82400 100644 --- a/src/library/scala/collection/IterableOnce.scala +++ b/src/library/scala/collection/IterableOnce.scala @@ -216,6 +216,17 @@ final class IterableOnceExtensionMethods[A](private val it: IterableOnce[A]) ext object IterableOnce { @`inline` implicit def iterableOnceExtensionMethods[A](it: IterableOnce[A]): IterableOnceExtensionMethods[A] = new IterableOnceExtensionMethods[A](it) + + /** Computes the number of elements to copy to an array from a source IterableOnce + * + * @param srcLen the length of the source collection + * @param destLen the length of the destination array + * @param start the index in the destination array at which to start copying elements to + * @param len the requested number of elements to copy (we may only be able to copy less than this) + * @return the number of elements that will be copied to the destination array + */ + @inline private[collection] def elemsToCopyToArray(srcLen: Int, destLen: Int, start: Int, len: Int): Int = + math.max(math.min(math.min(len, srcLen), destLen - start), 0) } /** This implementation trait can be mixed into an `IterableOnce` to get the basic methods that are shared between @@ -703,7 +714,7 @@ trait IterableOnceOps[+A, +CC[_], +C] extends Any { this: IterableOnce[A] => @deprecated("Use `dest ++= coll` instead", "2.13.0") @inline final def copyToBuffer[B >: A](dest: mutable.Buffer[B]): Unit = dest ++= this - /** Copy elements to an array. + /** Copy elements to an array, returning the number of elements written. * * Fills the given array `xs` starting at index `start` with values of this $coll. * @@ -712,14 +723,15 @@ trait IterableOnceOps[+A, +CC[_], +C] extends Any { this: IterableOnce[A] => * * @param xs the array to fill. * @tparam B the type of the elements of the array. + * @return the number of elements written to the array * - * @usecase def copyToArray(xs: Array[A]): Unit + * @usecase def copyToArray(xs: Array[A]): Int * * $willNotTerminateInf */ - def copyToArray[B >: A](xs: Array[B]): xs.type = copyToArray(xs, 0) + def copyToArray[B >: A](xs: Array[B]): Int = copyToArray(xs, 0) - /** Copy elements to an array. + /** Copy elements to an array, returning the number of elements written. * * Fills the given array `xs` starting at index `start` with values of this $coll. * @@ -729,13 +741,14 @@ trait IterableOnceOps[+A, +CC[_], +C] extends Any { this: IterableOnce[A] => * @param xs the array to fill. * @param start the starting index of xs. * @tparam B the type of the elements of the array. + * @return the number of elements written to the array * - * @usecase def copyToArray(xs: Array[A], start: Int): Unit + * @usecase def copyToArray(xs: Array[A], start: Int): Int * * $willNotTerminateInf */ - def copyToArray[B >: A](xs: Array[B], start: Int): xs.type = { + def copyToArray[B >: A](xs: Array[B], start: Int): Int = { val xsLen = xs.length val it = iterator var i = start @@ -743,10 +756,10 @@ trait IterableOnceOps[+A, +CC[_], +C] extends Any { this: IterableOnce[A] => xs(i) = it.next() i += 1 } - xs + i - start } - /** Copy elements to an array. + /** Copy elements to an array, returning the number of elements written. * * Fills the given array `xs` starting at index `start` with at most `len` elements of this $coll. * @@ -757,14 +770,15 @@ trait IterableOnceOps[+A, +CC[_], +C] extends Any { this: IterableOnce[A] => * @param start the starting index of xs. * @param len the maximal number of elements to copy. * @tparam B the type of the elements of the array. + * @return the number of elements written to the array * * @note Reuse: $consumesIterator * - * @usecase def copyToArray(xs: Array[A], start: Int, len: Int): Unit + * @usecase def copyToArray(xs: Array[A], start: Int, len: Int): Int * * $willNotTerminateInf */ - def copyToArray[B >: A](xs: Array[B], start: Int, len: Int): xs.type = { + def copyToArray[B >: A](xs: Array[B], start: Int, len: Int): Int = { val it = iterator var i = start val end = start + math.min(len, xs.length - start) @@ -772,7 +786,7 @@ trait IterableOnceOps[+A, +CC[_], +C] extends Any { this: IterableOnce[A] => xs(i) = it.next() i += 1 } - xs + i - start } /** Sums up the elements of this collection. @@ -1205,7 +1219,11 @@ trait IterableOnceOps[+A, +CC[_], +C] extends Any { this: IterableOnce[A] => /** Convert collection to array. */ def toArray[B >: A: ClassTag]: Array[B] = - if (knownSize >= 0) copyToArray(new Array[B](knownSize), 0) + if (knownSize >= 0) { + val destination = new Array[B](knownSize) + copyToArray(destination, 0) + destination + } else mutable.ArrayBuffer.from(this).toArray[B] // For internal use diff --git a/src/library/scala/collection/StringOps.scala b/src/library/scala/collection/StringOps.scala index b34ba95ac168..ff910bca8ae6 100644 --- a/src/library/scala/collection/StringOps.scala +++ b/src/library/scala/collection/StringOps.scala @@ -1141,16 +1141,14 @@ final class StringOps(private val s: String) extends AnyVal { @`inline` def filterNot(pred: Char => Boolean): String = filter(c => !pred(c)) /** Copy chars of this string to an array. - * Fills the given array `xs` starting at index `start` with at most `len` chars. - * Copying will stop once either the entire string has been copied, - * or the end of the array is reached or `len` chars have been copied. + * Fills the given array `xs` starting at index 0. + * Copying will stop once either the entire string has been copied + * or the end of the array is reached * * @param xs the array to fill. - * @param start the starting index. - * @param len the maximal number of elements to copy. */ - def copyToArray(xs: Array[Char], start: Int, len: Int): Unit = - s.getChars(0, min(min(s.length, len), xs.length-start), xs, start) + @`inline` def copyToArray(xs: Array[Char]): Int = + copyToArray(xs, 0, Int.MaxValue) /** Copy chars of this string to an array. * Fills the given array `xs` starting at index `start`. @@ -1159,11 +1157,27 @@ final class StringOps(private val s: String) extends AnyVal { * * @param xs the array to fill. * @param start the starting index. - * @param len the maximal number of elements to copy. */ - @`inline` def copyToArray(xs: Array[Char], start: Int): Unit = + @`inline` def copyToArray(xs: Array[Char], start: Int): Int = copyToArray(xs, start, Int.MaxValue) + /** Copy chars of this string to an array. + * Fills the given array `xs` starting at index `start` with at most `len` chars. + * Copying will stop once either the entire string has been copied, + * or the end of the array is reached or `len` chars have been copied. + * + * @param xs the array to fill. + * @param start the starting index. + * @param len the maximal number of elements to copy. + */ + def copyToArray(xs: Array[Char], start: Int, len: Int): Int = { + val copied = IterableOnce.elemsToCopyToArray(s.length, xs.length, start, len) + if (copied > 0) { + s.getChars(0, copied, xs, start) + } + copied + } + /** Finds index of the first char satisfying some predicate after or at some start index. * * @param p the predicate used to test elements. diff --git a/src/library/scala/collection/immutable/ArraySeq.scala b/src/library/scala/collection/immutable/ArraySeq.scala index 6fa3e6cfa4eb..673aa271b445 100644 --- a/src/library/scala/collection/immutable/ArraySeq.scala +++ b/src/library/scala/collection/immutable/ArraySeq.scala @@ -5,6 +5,7 @@ import java.io.{ObjectInputStream, ObjectOutputStream} import scala.collection.mutable.{ArrayBuffer, ArrayBuilder, Builder, ArraySeq => MutableArraySeq} import scala.collection.{ArrayOps, ClassTagSeqFactory, SeqFactory, StrictOptimizedClassTagSeqFactory, View} +import scala.collection.IterableOnce import scala.annotation.unchecked.uncheckedVariance import scala.util.hashing.MurmurHash3 import scala.reflect.ClassTag @@ -133,12 +134,14 @@ sealed abstract class ArraySeq[+A] override protected[this] def className = "ArraySeq" - override def copyToArray[B >: A](xs: Array[B], start: Int = 0): xs.type = copyToArray[B](xs, start, length) + override def copyToArray[B >: A](xs: Array[B], start: Int = 0): Int = copyToArray[B](xs, start, length) - override def copyToArray[B >: A](xs: Array[B], start: Int, len: Int): xs.type = { - val l = scala.math.min(scala.math.min(len, length), xs.length-start) - if(l > 0) Array.copy(unsafeArray, 0, xs, start, l) - xs + override def copyToArray[B >: A](xs: Array[B], start: Int, len: Int): Int = { + val copied = IterableOnce.elemsToCopyToArray(length, xs.length, start, len) + if(copied > 0) { + Array.copy(unsafeArray, 0, xs, start, copied) + } + copied } override protected[this] def writeReplace(): AnyRef = this diff --git a/src/library/scala/collection/mutable/ArrayBuffer.scala b/src/library/scala/collection/mutable/ArrayBuffer.scala index e01ca6931702..f4bdf1b6dafa 100644 --- a/src/library/scala/collection/mutable/ArrayBuffer.scala +++ b/src/library/scala/collection/mutable/ArrayBuffer.scala @@ -2,9 +2,6 @@ package scala package collection package mutable -import java.lang.{IndexOutOfBoundsException, IllegalArgumentException} - - /** An implementation of the `Buffer` class using an array to * represent the assembled sequence internally. Append, update and random * access take constant time (amortized time). Prepends and removes are @@ -159,12 +156,14 @@ class ArrayBuffer[A] private (initialElements: Array[AnyRef], initialSize: Int) override protected[this] def stringPrefix = "ArrayBuffer" - override def copyToArray[B >: A](xs: Array[B], start: Int): xs.type = copyToArray[B](xs, start, length) + override def copyToArray[B >: A](xs: Array[B], start: Int): Int = copyToArray[B](xs, start, length) - override def copyToArray[B >: A](xs: Array[B], start: Int, len: Int): xs.type = { - val l = scala.math.min(scala.math.min(len, length), xs.length-start) - if(l > 0) Array.copy(array, 0, xs, start, l) - xs + override def copyToArray[B >: A](xs: Array[B], start: Int, len: Int): Int = { + val copied = IterableOnce.elemsToCopyToArray(length, xs.length, start, len) + if(copied > 0) { + Array.copy(array, 0, xs, start, copied) + } + copied } /** Sorts this $coll in place according to an Ordering. diff --git a/src/library/scala/collection/mutable/ArrayDeque.scala b/src/library/scala/collection/mutable/ArrayDeque.scala index 3ed2b2688fe0..e9194a545854 100644 --- a/src/library/scala/collection/mutable/ArrayDeque.scala +++ b/src/library/scala/collection/mutable/ArrayDeque.scala @@ -434,8 +434,13 @@ class ArrayDeque[A] protected ( override def grouped(n: Int): Iterator[IterableCC[A]] = sliding(n, n) - override def copyToArray[B >: A](dest: Array[B], destStart: Int, len: Int): dest.type = - copySliceToArray(srcStart = 0, dest = dest, destStart = destStart, maxItems = len) + override def copyToArray[B >: A](dest: Array[B], destStart: Int, len: Int): Int = { + val copied = IterableOnce.elemsToCopyToArray(length, dest.length, destStart, len) + if (copied > 0) { + copySliceToArray(srcStart = 0, dest = dest, destStart = destStart, maxItems = len) + } + copied + } override def toArray[B >: A: ClassTag]: Array[B] = copySliceToArray(srcStart = 0, dest = new Array[B](length), destStart = 0, maxItems = length) diff --git a/src/library/scala/collection/mutable/ArraySeq.scala b/src/library/scala/collection/mutable/ArraySeq.scala index a3275e359ba3..637ca15c7da6 100644 --- a/src/library/scala/collection/mutable/ArraySeq.scala +++ b/src/library/scala/collection/mutable/ArraySeq.scala @@ -59,12 +59,14 @@ sealed abstract class ArraySeq[T] /** Clones this object, including the underlying Array. */ override def clone(): ArraySeq[T] = ArraySeq.make(array.clone()).asInstanceOf[ArraySeq[T]] - override def copyToArray[B >: T](xs: Array[B], start: Int): xs.type = copyToArray[B](xs, start, length) + override def copyToArray[B >: T](xs: Array[B], start: Int): Int = copyToArray[B](xs, start, length) - override def copyToArray[B >: T](xs: Array[B], start: Int, len: Int): xs.type = { - val l = scala.math.min(scala.math.min(len, length), xs.length-start) - if(l > 0) Array.copy(array, 0, xs, start, l) - xs + override def copyToArray[B >: T](xs: Array[B], start: Int, len: Int): Int = { + val copied = IterableOnce.elemsToCopyToArray(length, xs.length, start, len) + if(copied > 0) { + Array.copy(array, 0, xs, start, copied) + } + copied } override protected[this] def writeReplace(): AnyRef = this diff --git a/test/junit/scala/collection/ArrayOpsTest.scala b/test/junit/scala/collection/ArrayOpsTest.scala index e26c9c3eb77a..8904f75209b5 100644 --- a/test/junit/scala/collection/ArrayOpsTest.scala +++ b/test/junit/scala/collection/ArrayOpsTest.scala @@ -100,4 +100,10 @@ class ArrayOpsTest { assertArrayEquals(Array[Int](), Array[Int](1).slice(1052471512, -1496048404)) assertArrayEquals(Array[Int](), Array[Int](1).slice(2, 3)) } + + @Test + def copyToArrayOutOfBoundsTest: Unit = { + val target = Array[Int]() + assertEquals(0, Array(1,2).copyToArray(target, 1, 0)) + } } diff --git a/test/junit/scala/collection/IterableTest.scala b/test/junit/scala/collection/IterableTest.scala index 5b2a154fa722..491c7fa370e6 100644 --- a/test/junit/scala/collection/IterableTest.scala +++ b/test/junit/scala/collection/IterableTest.scala @@ -7,6 +7,7 @@ import org.junit.runners.JUnit4 import scala.collection.immutable.{ArraySeq, List, Range, Vector} import scala.language.higherKinds import scala.tools.testing.AssertUtil._ +import org.junit.Assert.assertEquals @RunWith(classOf[JUnit4]) class IterableTest { @@ -57,7 +58,7 @@ class IterableTest { val xs = Seq('a', 'b', 'b', 'c', 'a', 'a', 'a', 'b') val expected = Map('a' -> 4, 'b' -> 3, 'c' -> 1) - Assert.assertEquals(expected, occurrences(xs)) + assertEquals(expected, occurrences(xs)) } @Test @@ -89,54 +90,46 @@ class IterableTest { } @Test def copyToArray(): Unit = { - def check(a: Array[Int], start: Int, end: Int) = { + def check(a: Array[Int], copyToArray: Array[Int] => Int, elemsWritten: Int, start: Int, end: Int) = { + + assertEquals(copyToArray(a), elemsWritten) + var i = 0 while (i < start) { - assert(a(i) == 0) + assertEquals(a(i),0) i += 1 } while (i < a.length && i < end) { - assert(a(i) == i - start) + assertEquals(a(i), i - start) i += 1 } while (i < a.length) { - assert(a(i) == 0) + assertEquals(a(i), 0) i += 1 } } val far = 100000 val l = Iterable.from(Range(0, 100)) - check(l.copyToArray(new Array(100)), - 0, far) - check(l.copyToArray(new Array(10)), - 0, far) - check(l.copyToArray(new Array(1000)), - 0, 100) - - check(l.copyToArray(new Array(100), 5), - 5, 105) - check(l.copyToArray(new Array(10), 5), - 5, 10) - check(l.copyToArray(new Array(1000), 5), - 5, 105) - - check(l.copyToArray(new Array(100), 5, 50), - 5, 55) - check(l.copyToArray(new Array(10), 5, 50), - 5, 10) - check(l.copyToArray(new Array(1000), 5, 50), - 5, 55) - - assertThrows[ArrayIndexOutOfBoundsException](l.copyToArray(new Array(10), -1)) - assertThrows[ArrayIndexOutOfBoundsException](l.copyToArray(new Array(10), -1, 10)) - - check(l.copyToArray(new Array(10), 10), - 0, 0) - check(l.copyToArray(new Array(10), 10, 10), - 0, 0) - check(l.copyToArray(new Array(10), 0, -1), - 0, 0) + check(new Array(100), l.copyToArray(_), 100, 0, far) + check(new Array(10), l.copyToArray(_), 10, 0, far) + check(new Array(100), l.copyToArray(_), 100, 0, 100) + + check(new Array(100), l.copyToArray(_, 5), 95, 5, 105) + check(new Array(10), l.copyToArray(_, 5), 5, 5, 10) + check(new Array(1000), l.copyToArray(_, 5), 100, 5, 105) + + check(new Array(100), l.copyToArray(_, 5, 50), 50, 5, 55) + check(new Array(10), l.copyToArray(_, 5, 50), 5, 5, 10) + check(new Array(1000), l.copyToArray(_, 5, 50), 50, 5, 55) + + assertThrows[ArrayIndexOutOfBoundsException]( l.copyToArray(new Array(10), -1)) + assertThrows[ArrayIndexOutOfBoundsException]( l.copyToArray(new Array(10), -1, 10)) + assertEquals(l.copyToArray(new Array(10), 1, -1), 0) + + check(new Array(10), l.copyToArray(_, 10), 0, 0, 0) + check(new Array(10), l.copyToArray(_, 10, 10), 0, 0, 0) + check(new Array(10), l.copyToArray(_, 0, -1), 0, 0, 0) } @Test @@ -267,4 +260,5 @@ class IterableTest { val foo = new Foo Assert.assertEquals("Fu()", foo.toString) } + } diff --git a/test/junit/scala/collection/IteratorTest.scala b/test/junit/scala/collection/IteratorTest.scala index 04fdf9049cd7..3bc17cac3c46 100644 --- a/test/junit/scala/collection/IteratorTest.scala +++ b/test/junit/scala/collection/IteratorTest.scala @@ -428,54 +428,46 @@ class IteratorTest { } @Test def copyToArray(): Unit = { - def check(a: Array[Int], start: Int, end: Int) = { + def check(a: Array[Int], copyTo: Array[Int] => Int, elemsWritten: Int, start: Int, end: Int): Unit = { + + val copied = copyTo(a) + assertEquals(elemsWritten, copied) + var i = 0 while (i < start) { - assert(a(i) == 0) + assertEquals(a(i), 0) i += 1 } while (i < a.length && i < end) { - assert(a(i) == i - start) + assertEquals(a(i), i - start) i += 1 } while (i < a.length) { - assert(a(i) == 0) + assertEquals(a(i), 0) i += 1 } } val far = 100000 def l = Iterable.from(Range(0, 100)).iterator - check(l.copyToArray(new Array(100)), - 0, far) - check(l.copyToArray(new Array(10)), - 0, far) - check(l.copyToArray(new Array(1000)), - 0, 100) - - check(l.copyToArray(new Array(100), 5), - 5, 105) - check(l.copyToArray(new Array(10), 5), - 5, 10) - check(l.copyToArray(new Array(1000), 5), - 5, 105) - - check(l.copyToArray(new Array(100), 5, 50), - 5, 55) - check(l.copyToArray(new Array(10), 5, 50), - 5, 10) - check(l.copyToArray(new Array(1000), 5, 50), - 5, 55) + check(new Array(100), l.copyToArray(_), 100, 0, far) + check(new Array(10), l.copyToArray(_), 10, 0, far) + check(new Array(1000), l.copyToArray(_), 100, 0, 100) + + check(new Array(100), l.copyToArray(_, 5), 95, 5, 105) + check(new Array(10), l.copyToArray(_, 5), 5, 5, 10) + check(new Array(1000), l.copyToArray(_, 5), 100, 5, 105) + + check(new Array(100), l.copyToArray(_, 5, 50), 50, 5, 55) + check(new Array(10), l.copyToArray(_, 5, 50), 5, 5, 10) + check(new Array(1000), l.copyToArray(_, 5, 50), 50, 5, 55) assertThrows[ArrayIndexOutOfBoundsException](l.copyToArray(new Array(10), -1)) assertThrows[ArrayIndexOutOfBoundsException](l.copyToArray(new Array(10), -1, 10)) - check(l.copyToArray(new Array(10), 10), - 0, 0) - check(l.copyToArray(new Array(10), 10, 10), - 0, 0) - check(l.copyToArray(new Array(10), 0, -1), - 0, 0) + check(new Array(10), l.copyToArray(_, 10), 0, 0, 0) + check(new Array(10), l.copyToArray(_, 10, 10), 0, 0, 0) + check(new Array(10), l.copyToArray(_, 0, -1), 0, 0, 0) } // scala/bug#10709 diff --git a/test/junit/scala/collection/StringOpsTest.scala b/test/junit/scala/collection/StringOpsTest.scala index bbc194a4f6c9..cb94283aa835 100644 --- a/test/junit/scala/collection/StringOpsTest.scala +++ b/test/junit/scala/collection/StringOpsTest.scala @@ -1,9 +1,11 @@ package scala.collection -import org.junit.Assert.assertEquals import org.junit.Test import org.junit.runner.RunWith import org.junit.runners.JUnit4 +import org.junit.Assert.assertEquals +import scala.tools.testing.AssertUtil.assertThrows + @RunWith(classOf[JUnit4]) class StringOpsTest { @@ -24,6 +26,66 @@ class StringOpsTest { @Test def toArray(): Unit = { assert("".toArray[Any].length == 0) // should not throw + assertEquals("".mkString(""), "") + assertEquals("".mkString(","), "") + assertEquals("a".mkString(","), "a") + assertEquals("ab".mkString(","), "a,b") + } + // Test for scala/bug#8469 + @Test def copyToArray(): Unit = { + + def check(string: String, array: Array[Char], copied: Int, after: Array[Char]): Unit = { + assertEquals(copied, string.copyToArray(array)) + assert(array.sameElements(after)) + } + + check(string = "", array = Array(), copied = 0, after = Array()) + check(string = "", array = Array('a', 'b'), copied = 0, after = Array('a', 'b')) + + check(string = "abc", array = Array('x', 'y', 'z'), copied = 3, after = Array('a', 'b', 'c')) + check(string = "abc", array = Array('x'), copied = 1, after = Array('a')) + check(string = "abc", array = Array(), copied = 0, after = Array()) + } + + // Test for scala/bug#8469 + @Test def copyToArrayStart(): Unit = { + def check(string: String, start: Int, array: Array[Char], copied: Int, after: Array[Char]): Unit = { + assertEquals(copied, string.copyToArray(array,start)) + assert(array.sameElements(after)) + } + + check(string = "", start = 0, array = Array(), copied = 0, after = Array()) + check(string = "", start = 1, array = Array(), copied = 0, after = Array()) + check(string = "", start = -1, array = Array(), copied = 0, after = Array()) + + assertThrows[ArrayIndexOutOfBoundsException](check(string = "abcd", start = -13, array = Array('x', 'y'), copied = 0, after = Array('x', 'y'))) + check(string = "abcd", start = 0, array = Array('x', 'y'), copied = 2, after = Array('a', 'b')) + check(string = "abcd", start = 1, array = Array('x', 'y'), copied = 1, after = Array('x', 'a')) + check(string = "abcd", start = 2, array = Array('x', 'y'), copied = 0, after = Array('x', 'y')) + check(string = "abcd", start = 3, array = Array('x', 'y'), copied = 0, after = Array('x', 'y')) + check(string = "abcd", start = 4, array = Array('x', 'y'), copied = 0, after = Array('x', 'y')) + check(string = "abcd", start = 5, array = Array('x', 'y'), copied = 0, after = Array('x', 'y')) + } + + // Test for scala/bug#8469 + @Test def copyToArrayStartLen(): Unit = { + + def check(string: String, start: Int, len: Int, array: Array[Char], copied: Int, after: Array[Char]): Unit = { + assertEquals(copied, string.copyToArray(array, start, len)) + assert(array.sameElements(after)) + } + + check(string = "", start = 0, len = 0, array = Array(), copied = 0, after = Array()) + check(string = "", start = 1, len = 0, array = Array(), copied = 0, after = Array()) + check(string = "", start = 1, len = 1, array = Array(), copied = 0, after = Array()) + + check(string = "abcd", start = -1, len = 0, array = Array('x', 'y'), copied = 0, after = Array('x', 'y')) + check(string = "abcd", start = 0, len = 0, array = Array('x', 'y'), copied = 0, after = Array('x', 'y')) + check(string = "abcd", start = 0, len = 1, array = Array('x', 'y'), copied = 1, after = Array('a', 'y')) + check(string = "abcd", start = 1, len = 1, array = Array('x', 'y'), copied = 1, after = Array('x', 'a')) + check(string = "abcd", start = 0, len = 2, array = Array('x', 'y'), copied = 2, after = Array('a', 'b')) + check(string = "abcd", start = 0, len = 20, array = Array('x', 'y'), copied = 2, after = Array('a', 'b')) + check(string = "abcd", start = 7, len = 20, array = Array('x', 'y'), copied = 0, after = Array('x', 'y')) } @Test def *(): Unit = { diff --git a/test/junit/scala/collection/immutable/ArraySeqTest.scala b/test/junit/scala/collection/immutable/ArraySeqTest.scala index e42d2134877f..e35bcb331fc6 100644 --- a/test/junit/scala/collection/immutable/ArraySeqTest.scala +++ b/test/junit/scala/collection/immutable/ArraySeqTest.scala @@ -63,6 +63,11 @@ class ArraySeqTest { a.toArray.update(0, 100) assertEquals(a, List(1,2,3)) } + @Test + def copyToArrayReturnsNonNegative(): Unit = { + val a = ArraySeq(1,2,3) + assertEquals(a.copyToArray(Array(1,1,2), 0, -1), 0) + } private def check[T : ClassTag](array: ArraySeq[T], expectedSliceResult1: ArraySeq[T], expectedSliceResult2: ArraySeq[T]) { assertEquals(array, array.slice(-1, 4)) diff --git a/test/junit/scala/collection/immutable/QueueTest.scala b/test/junit/scala/collection/immutable/QueueTest.scala index d69325febb72..d0bb46cbbada 100644 --- a/test/junit/scala/collection/immutable/QueueTest.scala +++ b/test/junit/scala/collection/immutable/QueueTest.scala @@ -4,6 +4,9 @@ import org.junit.runner.RunWith import org.junit.runners.JUnit4 import org.junit.Test + +import org.junit.Assert.assertEquals + @RunWith(classOf[JUnit4]) /* Tests for collection.immutable.Queue */ class QueueTest { @@ -11,18 +14,27 @@ class QueueTest { val oneAdded = emptyQueue.enqueue(1) val threeAdded = emptyQueue.enqueue(1 to 3) + + @Test def dequeueOptionOnEmpty(): Unit = { - assert( emptyQueue.dequeueOption == None ) + assertEquals(emptyQueue.dequeueOption, None) } @Test def dequeueOptionOneAdded(): Unit = { - assert( oneAdded.dequeueOption == Some((1,emptyQueue)) ) + assertEquals(oneAdded.dequeueOption, Some((1,emptyQueue))) } @Test def dequeueOptionThreeAdded(): Unit = { - assert( threeAdded.dequeueOption == Some((1,Queue(2 to 3:_*))) ) + assertEquals(threeAdded.dequeueOption, Some((1,Queue(2 to 3:_*)))) } + + @Test + def copyToArrayOutOfBounds: Unit = { + val target = Array[Int]() + assertEquals(0, Queue(1,2).copyToArray(target, 1, 0)) + } + } diff --git a/test/junit/scala/collection/mutable/ArrayDequeTest.scala b/test/junit/scala/collection/mutable/ArrayDequeTest.scala index aa9e75192cca..33f987b0646c 100644 --- a/test/junit/scala/collection/mutable/ArrayDequeTest.scala +++ b/test/junit/scala/collection/mutable/ArrayDequeTest.scala @@ -14,9 +14,9 @@ class ArrayDequeTest { def apply[U](f: Buffer[Int] => U) = { //println(s"Before: [buffer1=${buffer}; buffer2=${buffer2}]") - assert(f(buffer) == f(buffer2)) - assert(buffer == buffer2) - assert(buffer.reverse == buffer2.reverse) + assertEquals(f(buffer), f(buffer2)) + assertEquals(buffer, buffer2) + assertEquals(buffer.reverse, buffer2.reverse) } apply(_ += (1, 2, 3, 4, 5)) @@ -40,15 +40,15 @@ class ArrayDequeTest { apply(_.addAll(collection.immutable.Vector.tabulate(10)(identity))) (-100 to 100) foreach {i => - assert(buffer.splitAt(i) == buffer2.splitAt(i)) + assertEquals(buffer.splitAt(i), buffer2.splitAt(i)) } for { i <- -100 to 100 j <- -100 to 100 } { - assert(buffer.slice(i, j) == buffer2.slice(i, j)) - if (i > 0 && j > 0) assert(List.from(buffer.sliding(i, j)) == List.from(buffer2.sliding(i, j))) + assertEquals(buffer.slice(i, j), buffer2.slice(i, j)) + if (i > 0 && j > 0) assertEquals(List.from(buffer.sliding(i, j)), List.from(buffer2.sliding(i, j))) } } @@ -65,4 +65,10 @@ class ArrayDequeTest { xs.insert(0, 0) assertEquals(Queue(0), xs) } + + @Test + def copyToArrayOutOfBounds: Unit = { + val target = Array[Int]() + assertEquals(0, collection.mutable.ArrayDeque(1, 2).copyToArray(target, 1, 0)) + } } diff --git a/test/junit/scala/collection/mutable/QueueTest.scala b/test/junit/scala/collection/mutable/QueueTest.scala index ae3b8720380a..38f0595bd387 100644 --- a/test/junit/scala/collection/mutable/QueueTest.scala +++ b/test/junit/scala/collection/mutable/QueueTest.scala @@ -4,7 +4,7 @@ import org.junit.Assert._ import org.junit.Test import org.junit.runner.RunWith import org.junit.runners.JUnit4 -import scala.collection.IterableFactory +import scala.collection.mutable @RunWith(classOf[JUnit4]) class QueueTest { @@ -29,4 +29,10 @@ class QueueTest { assertEquals(q.enqueue(5), List(1, 2, 3, 4, 5)) assertEquals(s, List(2, 3, 4)) } + + @Test + def copyToArrayOutOfBounds: Unit = { + val target = Array[Int]() + assertEquals(0, mutable.Queue(1,2).copyToArray(target, 1, 0)) + } } diff --git a/test/junit/scala/tools/nsc/DeterminismTest.scala b/test/junit/scala/tools/nsc/DeterminismTest.scala index 8651f23dcf0f..eb36e16c5aa2 100644 --- a/test/junit/scala/tools/nsc/DeterminismTest.scala +++ b/test/junit/scala/tools/nsc/DeterminismTest.scala @@ -2,7 +2,6 @@ package scala.tools.nsc import java.nio.file.attribute.BasicFileAttributes import java.nio.file.{FileVisitResult, Files, Path, SimpleFileVisitor} -import java.util import org.junit.Test From 233508cb90140d029fb868259b06de121fb71b4e Mon Sep 17 00:00:00 2001 From: Josh Lemer Date: Mon, 16 Jul 2018 22:30:58 -0400 Subject: [PATCH 118/143] [#11017] Various Map.WithDefault classes expose the more specific WithDefault class as return type of concat method --- .../scala/collection/IterableOnce.scala | 1 - .../scala/collection/immutable/Map.scala | 3 + .../collection/immutable/SortedMap.scala | 6 +- .../scala/collection/mutable/Map.scala | 4 +- .../scala/collection/mutable/SortedMap.scala | 3 + test/files/run/t3326.flags | 1 + .../collection/immutable/HashMapTest.scala | 30 +++++++++- .../collection/immutable/SortedMapTest.scala | 32 +++++++++++ .../collection/immutable/TreeMapTest.scala | 32 +++++++++++ .../collection/mutable/HashMapTest.scala | 54 ++++++++++++++++++ .../collection/mutable/SortedMapTest.scala | 55 +++++++++++++++++++ 11 files changed, 216 insertions(+), 5 deletions(-) create mode 100644 test/files/run/t3326.flags diff --git a/src/library/scala/collection/IterableOnce.scala b/src/library/scala/collection/IterableOnce.scala index 3e3ee6197e55..59d74a502c83 100644 --- a/src/library/scala/collection/IterableOnce.scala +++ b/src/library/scala/collection/IterableOnce.scala @@ -5,7 +5,6 @@ import scala.language.{higherKinds, implicitConversions} import scala.annotation.unchecked.uncheckedVariance import scala.math.{Numeric, Ordering} import scala.reflect.ClassTag -import java.lang.{StringBuilder => JStringBuilder} import scala.collection.mutable.StringBuilder /** diff --git a/src/library/scala/collection/immutable/Map.scala b/src/library/scala/collection/immutable/Map.scala index 6441d1a67b60..58df27908a93 100644 --- a/src/library/scala/collection/immutable/Map.scala +++ b/src/library/scala/collection/immutable/Map.scala @@ -153,6 +153,9 @@ object Map extends MapFactory[Map] { override def mapFactory: MapFactory[Map] = underlying.mapFactory + override def concat [V2 >: V](xs: collection.Iterable[(K, V2)]): WithDefault[K, V2] = + new WithDefault(underlying.concat(xs), defaultValue) + def remove(key: K): WithDefault[K, V] = new WithDefault[K, V](underlying.remove(key), defaultValue) def updated[V1 >: V](key: K, value: V1): WithDefault[K, V1] = diff --git a/src/library/scala/collection/immutable/SortedMap.scala b/src/library/scala/collection/immutable/SortedMap.scala index 36442f1b305d..f4019f9d8515 100644 --- a/src/library/scala/collection/immutable/SortedMap.scala +++ b/src/library/scala/collection/immutable/SortedMap.scala @@ -96,8 +96,10 @@ object SortedMap extends SortedMapFactory.Delegate[SortedMap](TreeMap) { override def updated[V1 >: V](key: K, value: V1): WithDefault[K, V1] = new WithDefault[K, V1](underlying.updated(key, value), defaultValue) - override def remove(key: K): WithDefault[K, V] = - new WithDefault[K, V](underlying.remove(key), defaultValue) + override def concat [V2 >: V](xs: collection.Iterable[(K, V2)]): WithDefault[K, V2] = + new WithDefault( underlying.concat(xs) , defaultValue) + + override def remove(key: K): WithDefault[K, V] = new WithDefault[K, V](underlying.remove(key), defaultValue) override def empty: WithDefault[K, V] = new WithDefault[K, V](underlying.empty, defaultValue) diff --git a/src/library/scala/collection/mutable/Map.scala b/src/library/scala/collection/mutable/Map.scala index f62e90025b51..fb948d95b79a 100644 --- a/src/library/scala/collection/mutable/Map.scala +++ b/src/library/scala/collection/mutable/Map.scala @@ -2,7 +2,6 @@ package scala package collection package mutable -import scala.collection.MapFactory import scala.language.higherKinds /** Base type of mutable Maps */ @@ -187,6 +186,9 @@ object Map extends MapFactory.Delegate[Map](HashMap) { def addOne(elem: (K, V)): WithDefault.this.type = { underlying.addOne(elem); this } + override def concat[V2 >: V](suffix: collection.Iterable[(K, V2)]): WithDefault[K, V2] = + underlying.concat(suffix).withDefault(defaultValue) + override def empty: WithDefault[K, V] = new WithDefault[K, V](underlying.empty, defaultValue) override protected def fromSpecificIterable(coll: scala.collection.Iterable[(K, V)]): WithDefault[K, V] = diff --git a/src/library/scala/collection/mutable/SortedMap.scala b/src/library/scala/collection/mutable/SortedMap.scala index 7f0d88c99b38..6ce1283d60ca 100644 --- a/src/library/scala/collection/mutable/SortedMap.scala +++ b/src/library/scala/collection/mutable/SortedMap.scala @@ -73,6 +73,9 @@ object SortedMap extends SortedMapFactory.Delegate[SortedMap](TreeMap) { override def empty: WithDefault[K, V] = new WithDefault[K, V](underlying.empty, defaultValue) + override def concat[V2 >: V](suffix: collection.Iterable[(K, V2)]): WithDefault[K, V2] = + underlying.concat(suffix).withDefault(defaultValue) + override protected def fromSpecificIterable(coll: scala.collection.Iterable[(K, V)]): WithDefault[K, V] = new WithDefault[K, V](sortedMapFactory.from(coll), defaultValue) diff --git a/test/files/run/t3326.flags b/test/files/run/t3326.flags new file mode 100644 index 000000000000..ba97e343a125 --- /dev/null +++ b/test/files/run/t3326.flags @@ -0,0 +1 @@ +-opt-warnings \ No newline at end of file diff --git a/test/junit/scala/collection/immutable/HashMapTest.scala b/test/junit/scala/collection/immutable/HashMapTest.scala index f48eca550358..32a6ec452c8a 100644 --- a/test/junit/scala/collection/immutable/HashMapTest.scala +++ b/test/junit/scala/collection/immutable/HashMapTest.scala @@ -68,10 +68,38 @@ class HashMapTest { assertEquals("a", m1.getOrElse(1, ???)) assertEquals("c", m1.getOrElse(3, "c")) - class Collider { override def hashCode = 0 } + class Collider { + override def hashCode = 0 + } val a, b, c = new Collider val m2 = HashMap(a -> "a", b -> "b") assertEquals("a", m2.getOrElse(a, ???)) assertEquals("c", m2.getOrElse(c, "c")) } + + @Test + def testWithDefault: Unit = { + val m1 = HashMap(1 -> "a", 2 -> "b") + + val m2: Map.WithDefault[Int, String] = + m1.withDefault(i => (i + 1).toString) + .updated(1, "aa") + .updated(100, "bb") + .concat(List(500 -> "c", 501 -> "c")) + + assertEquals(m2(1), "aa") + assertEquals(m2(2), "b") + assertEquals(m2(3), "4") + assertEquals(m2(4), "5") + assertEquals(m2(500), "c") + assertEquals(m2(501), "c") + assertEquals(m2(502), "503") + + val m3: Map.WithDefault[Int, String] = m2 - 1 + assertEquals(m3(1), "2") + + val m4: Map.WithDefault[Int, String] = m3 -- List(2, 100) + assertEquals(m4(2), "3") + assertEquals(m4(100), "101") + } } diff --git a/test/junit/scala/collection/immutable/SortedMapTest.scala b/test/junit/scala/collection/immutable/SortedMapTest.scala index 85fdfddd3afc..ec69fee1fa3e 100644 --- a/test/junit/scala/collection/immutable/SortedMapTest.scala +++ b/test/junit/scala/collection/immutable/SortedMapTest.scala @@ -106,4 +106,36 @@ class SortedMapTest { private def defaultValueFunction: Int => String = { i => s"$i is not present in this map" } + @Test + def testWithDefaultValue: Unit = { + val m1 = SortedMap(1 -> "a", 2 -> "b") + val m2 = m1.withDefaultValue(0) + assertEquals("a", m2(1)) + assertEquals(0, m2(3)) + } + @Test + def testWithDefault: Unit = { + val m1 = SortedMap(1 -> "a", 2 -> "b") + + val m2: Map.WithDefault[Int, String] = + m1.withDefault(i => (i + 1).toString) + .updated(1, "aa") + .updated(100, "bb") + .concat(List(500 -> "c", 501 -> "c")) + + assertEquals(m2(1), "aa") + assertEquals(m2(2), "b") + assertEquals(m2(3), "4") + assertEquals(m2(4), "5") + assertEquals(m2(500), "c") + assertEquals(m2(501), "c") + assertEquals(m2(502), "503") + + val m3: Map.WithDefault[Int, String] = m2 - 1 + assertEquals(m3(1), "2") + + val m4: Map.WithDefault[Int, String] = m3 -- List(2, 100) + assertEquals(m4(2), "3") + assertEquals(m4(100), "101") + } } diff --git a/test/junit/scala/collection/immutable/TreeMapTest.scala b/test/junit/scala/collection/immutable/TreeMapTest.scala index a152945cd5a3..6d8dae019bd1 100644 --- a/test/junit/scala/collection/immutable/TreeMapTest.scala +++ b/test/junit/scala/collection/immutable/TreeMapTest.scala @@ -23,4 +23,36 @@ class TreeMapTest { val m = TreeMap("a" -> "a") assertSame(m, TreeMap.from(m)) } + @Test + def testWithDefaultValue: Unit = { + val m1 = TreeMap(1 -> "a", 2 -> "b") + val m2 = m1.withDefaultValue(0) + assertEquals("a", m2(1)) + assertEquals(0, m2(3)) + } + @Test + def testWithDefault: Unit = { + val m1 = TreeMap(1 -> "a", 2 -> "b") + + val m2: Map.WithDefault[Int, String] = + m1.withDefault(i => (i + 1).toString) + .updated(1, "aa") + .updated(100, "bb") + .concat(List(500 -> "c", 501 -> "c")) + + assertEquals(m2(1), "aa") + assertEquals(m2(2), "b") + assertEquals(m2(3), "4") + assertEquals(m2(4), "5") + assertEquals(m2(500), "c") + assertEquals(m2(501), "c") + assertEquals(m2(502), "503") + + val m3: Map.WithDefault[Int, String] = m2 - 1 + assertEquals(m3(1), "2") + + val m4: Map.WithDefault[Int, String] = m3 -- List(2, 100) + assertEquals(m4(2), "3") + assertEquals(m4(100), "101") + } } diff --git a/test/junit/scala/collection/mutable/HashMapTest.scala b/test/junit/scala/collection/mutable/HashMapTest.scala index 5b0eb727be03..bde6b6e8bfe4 100644 --- a/test/junit/scala/collection/mutable/HashMapTest.scala +++ b/test/junit/scala/collection/mutable/HashMapTest.scala @@ -56,4 +56,58 @@ class HashMapTest { assertEquals("a", gotItAll.getOrElse("a", "b")) assertEquals("a", gotItAll.getOrElseUpdate("a", "b")) } + @Test + def testWithDefaultValue: Unit = { + val m1 = mutable.HashMap(1 -> "a", 2 -> "b") + val m2 = m1.withDefaultValue("") + + assertEquals(m2(1), "a") + assertEquals(m2(3), "") + + m2 += (3 -> "c") + assertEquals(m2(3), "c") + assertEquals(m2(4), "") + + m2 ++= List(4 -> "d", 5 -> "e", 6 -> "f") + assertEquals(m2(3), "c") + assertEquals(m2(4), "d") + assertEquals(m2(5), "e") + assertEquals(m2(6), "f") + assertEquals(m2(7), "") + + m2 --= List(3, 4, 5) + assertEquals(m2(3), "") + assertEquals(m2(4), "") + assertEquals(m2(5), "") + assertEquals(m2(6), "f") + assertEquals(m2(7), "") + + val m3 = m2 ++ List(3 -> "333") + assertEquals(m2(3), "") + assertEquals(m3(3), "333") + } + @Test + def testWithDefault: Unit = { + val m1 = mutable.HashMap(1 -> "a", 2 -> "b") + + val m2: mutable.Map.WithDefault[Int, String] = m1.withDefault(i => (i + 1).toString) + m2.update(1, "aa") + m2.update(100, "bb") + m2.addAll(List(500 -> "c", 501 -> "c")) + + assertEquals(m2(1), "aa") + assertEquals(m2(2), "b") + assertEquals(m2(3), "4") + assertEquals(m2(4), "5") + assertEquals(m2(500), "c") + assertEquals(m2(501), "c") + assertEquals(m2(502), "503") + + val m3: mutable.Map.WithDefault[Int, String] = m2 - 1 + assertEquals(m3(1), "2") + + val m4: mutable.Map.WithDefault[Int, String] = m3 -- List(2, 100) + assertEquals(m4(2), "3") + assertEquals(m4(100), "101") + } } diff --git a/test/junit/scala/collection/mutable/SortedMapTest.scala b/test/junit/scala/collection/mutable/SortedMapTest.scala index 0a6fc6a7865b..316013a69260 100644 --- a/test/junit/scala/collection/mutable/SortedMapTest.scala +++ b/test/junit/scala/collection/mutable/SortedMapTest.scala @@ -7,6 +7,7 @@ import org.junit.Test import org.junit.runner.RunWith import org.junit.runners.JUnit4 +import scala.collection.mutable import scala.{Option, Unit} @RunWith(classOf[JUnit4]) @@ -105,4 +106,58 @@ class SortedMapTest { private def defaultValueFunction: Int => String = { i => s"$i is not present in this map" } + @Test + def testWithDefaultValue: Unit = { + val m1 = mutable.SortedMap(1 -> "a", 2 -> "b") + val m2 = m1.withDefaultValue("") + + assertEquals(m2(1), "a") + assertEquals(m2(3), "") + + m2 += (3 -> "c") + assertEquals(m2(3), "c") + assertEquals(m2(4), "") + + m2 ++= List(4 -> "d", 5 -> "e", 6 -> "f") + assertEquals(m2(3), "c") + assertEquals(m2(4), "d") + assertEquals(m2(5), "e") + assertEquals(m2(6), "f") + assertEquals(m2(7), "") + + m2 --= List(3, 4, 5) + assertEquals(m2(3), "") + assertEquals(m2(4), "") + assertEquals(m2(5), "") + assertEquals(m2(6), "f") + assertEquals(m2(7), "") + + val m3 = m2 ++ List(3 -> "333") + assertEquals(m2(3), "") + assertEquals(m3(3), "333") + } + @Test + def testWithDefault: Unit = { + val m1 = mutable.SortedMap(1 -> "a", 2 -> "b") + + val m2: mutable.Map.WithDefault[Int, String] = m1.withDefault(i => (i + 1).toString) + m2.update(1, "aa") + m2.update(100, "bb") + m2.addAll(List(500 -> "c", 501 -> "c")) + + assertEquals(m2(1), "aa") + assertEquals(m2(2), "b") + assertEquals(m2(3), "4") + assertEquals(m2(4), "5") + assertEquals(m2(500), "c") + assertEquals(m2(501), "c") + assertEquals(m2(502), "503") + + val m3: mutable.Map.WithDefault[Int, String] = m2 - 1 + assertEquals(m3(1), "2") + + val m4: mutable.Map.WithDefault[Int, String] = m3 -- List(2, 100) + assertEquals(m4(2), "3") + assertEquals(m4(100), "101") + } } From ce7978aa2467876dc073b0b80aba8854505ba3c7 Mon Sep 17 00:00:00 2001 From: Josh Lemer Date: Sat, 4 Aug 2018 21:50:45 -0400 Subject: [PATCH 119/143] [11049] Fixes scala/bug#11049 --- src/library/scala/collection/IndexedSeqView.scala | 4 +++- .../scala/collection/mutable/ArrayBuffer.scala | 2 +- .../scala/collection/mutable/PriorityQueue.scala | 10 +--------- .../scala/collection/mutable/PriorityQueueTest.scala | 11 ++++++++++- 4 files changed, 15 insertions(+), 12 deletions(-) diff --git a/src/library/scala/collection/IndexedSeqView.scala b/src/library/scala/collection/IndexedSeqView.scala index 6342f0c2aa17..842ad9b9cf06 100644 --- a/src/library/scala/collection/IndexedSeqView.scala +++ b/src/library/scala/collection/IndexedSeqView.scala @@ -26,10 +26,12 @@ object IndexedSeqView { private[this] var current = 0 override def knownSize: Int = self.size - current def hasNext = current < self.size - def next(): A = { + def next(): A = try { val r = self.apply(current) current += 1 r + } catch { + case _: IndexOutOfBoundsException => throw new NoSuchElementException("last of empty iterator") } } diff --git a/src/library/scala/collection/mutable/ArrayBuffer.scala b/src/library/scala/collection/mutable/ArrayBuffer.scala index e01ca6931702..ed7708df31d1 100644 --- a/src/library/scala/collection/mutable/ArrayBuffer.scala +++ b/src/library/scala/collection/mutable/ArrayBuffer.scala @@ -210,7 +210,7 @@ object ArrayBuffer extends StrictOptimizedSeqFactory[ArrayBuffer] { final class ArrayBufferView[A](val array: Array[AnyRef], val length: Int) extends AbstractIndexedSeqView[A] { @throws[ArrayIndexOutOfBoundsException] - def apply(n: Int) = array(n).asInstanceOf[A] + def apply(n: Int) = if (n < length) array(n).asInstanceOf[A] else throw new IndexOutOfBoundsException(n.toString) override protected[this] def className = "ArrayBufferView" } diff --git a/src/library/scala/collection/mutable/PriorityQueue.scala b/src/library/scala/collection/mutable/PriorityQueue.scala index c03ccb0188e9..48fc83fa33bf 100644 --- a/src/library/scala/collection/mutable/PriorityQueue.scala +++ b/src/library/scala/collection/mutable/PriorityQueue.scala @@ -247,15 +247,7 @@ sealed class PriorityQueue[A](implicit val ord: Ordering[A]) * * @return an iterator over all the elements. */ - override def iterator: Iterator[A] = new AbstractIterator[A] { - private[this] var i = 1 - def hasNext: Boolean = i < resarr.p_size0 - def next(): A = { - val n = resarr.p_array(i) - i += 1 - toA(n) - } - } + override def iterator: Iterator[A] = resarr.iterator.drop(1) /** Returns the reverse of this priority queue. The new priority queue has * the same elements as the original, but the opposite ordering. diff --git a/test/junit/scala/collection/mutable/PriorityQueueTest.scala b/test/junit/scala/collection/mutable/PriorityQueueTest.scala index 6c2e480973dc..727b25eb2c5e 100644 --- a/test/junit/scala/collection/mutable/PriorityQueueTest.scala +++ b/test/junit/scala/collection/mutable/PriorityQueueTest.scala @@ -3,8 +3,13 @@ package scala.collection.mutable import org.junit.runner.RunWith import org.junit.runners.JUnit4 import org.junit.Test + import scala.collection.mutable -import java.io.{ObjectInputStream, ByteArrayInputStream, ByteArrayOutputStream, ObjectOutputStream} +import java.io.{ByteArrayInputStream, ByteArrayOutputStream, ObjectInputStream, ObjectOutputStream} + +import scala.tools.testing.AssertUtil.assertThrows + + @RunWith(classOf[JUnit4]) /* Test for scala/bug#7568 */ @@ -42,4 +47,8 @@ class PriorityQueueTest { //correct sequencing is also tested here: assert(deserializedPriorityQueue.dequeueAll == elements.sorted.reverse) } + @Test + def lastOfEmptyThrowsException(): Unit = { + assertThrows[NoSuchElementException](collection.mutable.PriorityQueue[Int]().last) + } } From a8c47a5c8e494f8abff11e542602cd9da6ffcd88 Mon Sep 17 00:00:00 2001 From: Josh Lemer Date: Sun, 5 Aug 2018 10:18:28 -0400 Subject: [PATCH 120/143] [11049] Instead of catching thrown exception in IndexSeqViewIterator, proactively throw if the iterator is empty --- src/library/scala/collection/IndexedSeqView.scala | 13 ++++++------- .../collection/mutable/PriorityQueueTest.scala | 3 +-- 2 files changed, 7 insertions(+), 9 deletions(-) diff --git a/src/library/scala/collection/IndexedSeqView.scala b/src/library/scala/collection/IndexedSeqView.scala index 842ad9b9cf06..cd4061725756 100644 --- a/src/library/scala/collection/IndexedSeqView.scala +++ b/src/library/scala/collection/IndexedSeqView.scala @@ -26,13 +26,12 @@ object IndexedSeqView { private[this] var current = 0 override def knownSize: Int = self.size - current def hasNext = current < self.size - def next(): A = try { - val r = self.apply(current) - current += 1 - r - } catch { - case _: IndexOutOfBoundsException => throw new NoSuchElementException("last of empty iterator") - } + def next(): A = + if (hasNext) { + val r = self.apply(current) + current += 1 + r + } else Iterator.empty.next() } /** An `IndexedSeqOps` whose collection type and collection type constructor are unknown */ diff --git a/test/junit/scala/collection/mutable/PriorityQueueTest.scala b/test/junit/scala/collection/mutable/PriorityQueueTest.scala index 727b25eb2c5e..080799acc636 100644 --- a/test/junit/scala/collection/mutable/PriorityQueueTest.scala +++ b/test/junit/scala/collection/mutable/PriorityQueueTest.scala @@ -9,8 +9,6 @@ import java.io.{ByteArrayInputStream, ByteArrayOutputStream, ObjectInputStream, import scala.tools.testing.AssertUtil.assertThrows - - @RunWith(classOf[JUnit4]) /* Test for scala/bug#7568 */ class PriorityQueueTest { @@ -49,6 +47,7 @@ class PriorityQueueTest { } @Test def lastOfEmptyThrowsException(): Unit = { + assert(List(1,2,3,4,5).contains(collection.mutable.PriorityQueue[Int](1,2,3,4,5).last)) assertThrows[NoSuchElementException](collection.mutable.PriorityQueue[Int]().last) } } From 094a52fe3420c2f9c1542e3efe09dbc8bcd1d431 Mon Sep 17 00:00:00 2001 From: Josh Lemer Date: Sun, 5 Aug 2018 10:26:14 -0400 Subject: [PATCH 121/143] [11049] add test that new ArrayBuffer[Int].iterator.drop(1).next throws exception --- test/junit/scala/collection/mutable/ArrayBufferTest.scala | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/test/junit/scala/collection/mutable/ArrayBufferTest.scala b/test/junit/scala/collection/mutable/ArrayBufferTest.scala index be272065932c..df47ac04df26 100644 --- a/test/junit/scala/collection/mutable/ArrayBufferTest.scala +++ b/test/junit/scala/collection/mutable/ArrayBufferTest.scala @@ -5,7 +5,9 @@ import org.junit.runners.JUnit4 import org.junit.Test import org.junit.Assert.assertEquals + import scala.tools.testing.AssertUtil +import scala.tools.testing.AssertUtil.assertThrows /* Test for scala/bug#9043 */ @RunWith(classOf[JUnit4]) @@ -307,4 +309,10 @@ class ArrayBufferTest { assertEquals(builder.result(), "4,3,2,1") } + + @Test + def emptyIteratorDropOneMustBeEmpty: Unit = { + assertThrows[NoSuchElementException](new ArrayBuffer[Int].iterator.drop(1).next()) + } + } From f4a8bf86b35d2a175767e1e86aa712d3da4f56f2 Mon Sep 17 00:00:00 2001 From: Miles Sabin Date: Tue, 6 Mar 2018 12:09:55 +0000 Subject: [PATCH 122/143] Downwards comparisons for implicit search and overloading resolution This is a backport of the following Dotty change to scalac, https://github.com/lampepfl/dotty/commit/89540268e6c49fb92b9ca61249e46bb59981bf5a As in the Dotty implementation the specificity comparison which is used for overload resolution and implicit selection is now performed as-if all contravariant positions in type constructors were covariant. Fixes scala/bug#2509. Fixes scala/bug#7768. --- .../tools/nsc/settings/ScalaSettings.scala | 3 + .../scala/tools/nsc/typechecker/Infer.scala | 25 ++- .../scala/reflect/internal/Symbols.scala | 10 ++ test/files/neg/t2509-2.check | 7 + test/files/neg/t2509-2.flags | 1 + test/files/neg/t2509-2.scala | 28 +++ test/files/neg/t2509-3.check | 4 + test/files/neg/t2509-3.flags | 1 + test/files/neg/t2509-3.scala | 33 ++++ test/files/neg/t2509-7b.check | 7 + test/files/neg/t2509-7b.flags | 1 + test/files/neg/t2509-7b.scala | 31 ++++ test/files/pos/t2030.flags | 1 + test/files/pos/t2030.scala | 8 + test/files/pos/t2509-5.flags | 1 + test/files/pos/t2509-5.scala | 13 ++ test/files/pos/t2509-6.flags | 1 + test/files/pos/t2509-6.scala | 33 ++++ test/files/pos/t2509-7a.flags | 1 + test/files/pos/t2509-7a.scala | 31 ++++ test/files/run/t2509-1.check | 2 + test/files/run/t2509-1.flags | 1 + test/files/run/t2509-1.scala | 33 ++++ test/files/run/t2509-4.check | 2 + test/files/run/t2509-4.flags | 1 + test/files/run/t2509-4.scala | 35 ++++ test/files/run/t7768.check | 3 + test/files/run/t7768.flags | 1 + test/files/run/t7768.scala | 89 +++++++++ .../scala/tools/nsc/typechecker/Infer.scala | 169 ++++++++++++++++++ 30 files changed, 575 insertions(+), 1 deletion(-) create mode 100644 test/files/neg/t2509-2.check create mode 100644 test/files/neg/t2509-2.flags create mode 100644 test/files/neg/t2509-2.scala create mode 100644 test/files/neg/t2509-3.check create mode 100644 test/files/neg/t2509-3.flags create mode 100644 test/files/neg/t2509-3.scala create mode 100644 test/files/neg/t2509-7b.check create mode 100644 test/files/neg/t2509-7b.flags create mode 100644 test/files/neg/t2509-7b.scala create mode 100644 test/files/pos/t2030.flags create mode 100644 test/files/pos/t2030.scala create mode 100644 test/files/pos/t2509-5.flags create mode 100644 test/files/pos/t2509-5.scala create mode 100644 test/files/pos/t2509-6.flags create mode 100644 test/files/pos/t2509-6.scala create mode 100644 test/files/pos/t2509-7a.flags create mode 100644 test/files/pos/t2509-7a.scala create mode 100644 test/files/run/t2509-1.check create mode 100644 test/files/run/t2509-1.flags create mode 100644 test/files/run/t2509-1.scala create mode 100644 test/files/run/t2509-4.check create mode 100644 test/files/run/t2509-4.flags create mode 100644 test/files/run/t2509-4.scala create mode 100644 test/files/run/t7768.check create mode 100644 test/files/run/t7768.flags create mode 100644 test/files/run/t7768.scala create mode 100644 test/junit/scala/tools/nsc/typechecker/Infer.scala diff --git a/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala b/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala index 12adcd62b76e..5a4b5984e5ee 100644 --- a/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala +++ b/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala @@ -98,6 +98,9 @@ trait ScalaSettings extends AbsScalaSettings def isScala213: Boolean = source.value >= version213 private[this] val version214 = ScalaVersion("2.14.0") def isScala214: Boolean = source.value >= version214 + private[this] val version300 = ScalaVersion("3.0.0") + def isScala300: Boolean = source.value >= version300 + /** * -X "Advanced" settings diff --git a/src/compiler/scala/tools/nsc/typechecker/Infer.scala b/src/compiler/scala/tools/nsc/typechecker/Infer.scala index 809c010a27b6..50cf286a676f 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Infer.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Infer.scala @@ -806,13 +806,36 @@ trait Infer extends Checkable { case _ => onRight } } + private def isAsSpecificValueType(tpe1: Type, tpe2: Type, undef1: List[Symbol], undef2: List[Symbol]): Boolean = tpe1 match { case PolyType(tparams1, rtpe1) => isAsSpecificValueType(rtpe1, tpe2, undef1 ::: tparams1, undef2) case _ => tpe2 match { case PolyType(tparams2, rtpe2) => isAsSpecificValueType(tpe1, rtpe2, undef1, undef2 ::: tparams2) - case _ => existentialAbstraction(undef1, tpe1) <:< existentialAbstraction(undef2, tpe2) + case _ if !settings.isScala300 => existentialAbstraction(undef1, tpe1) <:< existentialAbstraction(undef2, tpe2) + case _ => + // Backport of fix for https://github.com/scala/bug/issues/2509 + // from Dotty https://github.com/lampepfl/dotty/commit/89540268e6c49fb92b9ca61249e46bb59981bf5a + // + // Note that as of https://github.com/lampepfl/dotty/commit/b9f3084205bc9fcbd2a5181d3f0e539e2a20253a + // Dotty flips variances throughout, not just at the top level. We follow that behaviour here. + + val e1 = existentialAbstraction(undef1, tpe1) + val e2 = existentialAbstraction(undef2, tpe2) + + val flip = new TypeMap(trackVariance = true) { + def apply(tp: Type): Type = tp match { + case TypeRef(pre, sym, args) if variance > 0 && sym.typeParams.exists(_.isContravariant) => + mapOver(TypeRef(pre, sym.flipped, args)) + case _ => + mapOver(tp) + } + } + + val bt = e1.baseType(e2.typeSymbol) + val lhs = if(bt != NoType) bt else e1 + flip(lhs) <:< flip(e2) } } diff --git a/src/reflect/scala/reflect/internal/Symbols.scala b/src/reflect/scala/reflect/internal/Symbols.scala index ba8ecad31440..40a2dbaffe98 100644 --- a/src/reflect/scala/reflect/internal/Symbols.scala +++ b/src/reflect/scala/reflect/internal/Symbols.scala @@ -2017,6 +2017,8 @@ trait Symbols extends api.Symbols { self: SymbolTable => /** Internal method to clone a symbol's implementation with the given flags and no info. */ def cloneSymbolImpl(owner: Symbol, newFlags: Long): TypeOfClonedSymbol + def flipped: Symbol = this + // ------ access to related symbols -------------------------------------------------- /** The next enclosing class. */ @@ -3386,6 +3388,14 @@ trait Symbols extends api.Symbols { self: SymbolTable => clone } + override lazy val flipped: ClassSymbol = { + val clone = cloneSymbol(owner) + clone.rawInfo.typeParams.foreach { sym => + if (sym.isContravariant) sym.resetFlag(Flag.CONTRAVARIANT).setFlag(Flag.COVARIANT) + } + clone + } + override def derivedValueClassUnbox = // (info.decl(nme.unbox)) orElse uncomment once we accept unbox methods (info.decls.find(_ hasAllFlags PARAMACCESSOR | METHOD) getOrElse diff --git a/test/files/neg/t2509-2.check b/test/files/neg/t2509-2.check new file mode 100644 index 000000000000..f87a7e6bb52d --- /dev/null +++ b/test/files/neg/t2509-2.check @@ -0,0 +1,7 @@ +t2509-2.scala:26: error: ambiguous implicit values: + both value xb in object Test of type => X[B,Int] + and value xa in object Test of type => X[A,Boolean] + match expected type X[B,U] + val fb = f(new B) + ^ +one error found diff --git a/test/files/neg/t2509-2.flags b/test/files/neg/t2509-2.flags new file mode 100644 index 000000000000..cab9e99af3a9 --- /dev/null +++ b/test/files/neg/t2509-2.flags @@ -0,0 +1 @@ +-Xsource:3.0 diff --git a/test/files/neg/t2509-2.scala b/test/files/neg/t2509-2.scala new file mode 100644 index 000000000000..609bd8785f8a --- /dev/null +++ b/test/files/neg/t2509-2.scala @@ -0,0 +1,28 @@ +class A +class B extends A +class C extends B + +trait X[-T, U] { + val u: U +} + +object XA extends X[A, Boolean] { + val u = true +} + +object XB extends X[B, Int] { + val u = 23 +} + +object Test { + implicit def f[T, U](t: T)(implicit x: X[T, U]): U = x.u + implicit val xa: X[A, Boolean] = XA + implicit val xb: X[B, Int] = XB + + val fa = f(new A) + val ffa: Boolean = fa + + // Should be ambiguous + val fb = f(new B) + val ffb: Int = fb +} diff --git a/test/files/neg/t2509-3.check b/test/files/neg/t2509-3.check new file mode 100644 index 000000000000..68d20ddd2293 --- /dev/null +++ b/test/files/neg/t2509-3.check @@ -0,0 +1,4 @@ +t2509-3.scala:31: error: value value is not a member of B + println("B: " + b.value) + ^ +one error found diff --git a/test/files/neg/t2509-3.flags b/test/files/neg/t2509-3.flags new file mode 100644 index 000000000000..cab9e99af3a9 --- /dev/null +++ b/test/files/neg/t2509-3.flags @@ -0,0 +1 @@ +-Xsource:3.0 diff --git a/test/files/neg/t2509-3.scala b/test/files/neg/t2509-3.scala new file mode 100644 index 000000000000..5606765d0992 --- /dev/null +++ b/test/files/neg/t2509-3.scala @@ -0,0 +1,33 @@ +class A +class B extends A + +trait Y { + def value: String +} + +trait X[-T] { + def y(t: T): Y +} + +trait Z[-T] extends X[T] + +object ZA extends Z[A] { + def y(a: A) = new Y { def value = s"${a.getClass}: AValue" } +} + +object XB extends X[B] { + def y(b: B) = new Y { def value = s"S{b.getClass}: BValue" } +} + +object Test { + implicit def f[T](t: T)(implicit x: X[T]): Y = x.y(t) + implicit val za: Z[A] = ZA + implicit val xb: X[B] = XB + + def main(argv: Array[String]): Unit = { + val a = new A + val b = new B + println("A: " + a.value) + println("B: " + b.value) + } +} diff --git a/test/files/neg/t2509-7b.check b/test/files/neg/t2509-7b.check new file mode 100644 index 000000000000..12436339f81d --- /dev/null +++ b/test/files/neg/t2509-7b.check @@ -0,0 +1,7 @@ +t2509-7b.scala:30: error: ambiguous implicit values: + both method make in object X of type => Both[X,X] + and method make in trait Factory of type => Both[Y,Y] + match expected type Both[Y,X] + get + ^ +one error found diff --git a/test/files/neg/t2509-7b.flags b/test/files/neg/t2509-7b.flags new file mode 100644 index 000000000000..cab9e99af3a9 --- /dev/null +++ b/test/files/neg/t2509-7b.flags @@ -0,0 +1 @@ +-Xsource:3.0 diff --git a/test/files/neg/t2509-7b.scala b/test/files/neg/t2509-7b.scala new file mode 100644 index 000000000000..ebffe3c67512 --- /dev/null +++ b/test/files/neg/t2509-7b.scala @@ -0,0 +1,31 @@ +class Both[-A, +B] + +trait Factory[A] { + implicit def make: Both[A, A] = new Both[A, A] +} + +trait X +object X extends Factory[X] { + override implicit def make: Both[X, X] = super.make +} + +class Y extends X +object Y extends Factory[Y] { + // See test/files/pos/t2509-7a.scala ... discussion below + // override implicit def make: Both[Y, Y] = super.make +} + +object Test { + def get(implicit ev: Both[Y, X]) = ev + + // There are two possible implicits here: X.make and Y.make, neither are + // subtype of each other, so who wins? + // - Under the old scheme it's X.make because `isAsGood` sees that X.make is defined + // in X whereas Y.make is defined in Factory + // - Under the new scheme it's ambiguous because we replace contravariance by covariance + // in top-level type parameters so Y.make is treated as a subtype of X.make + // In both schemes we can get Y.make to win by uncommenting the override for make in Y + // (Y wins against X because `isDerived` also considers the subtyping relationships + // of companion classes) + get +} diff --git a/test/files/pos/t2030.flags b/test/files/pos/t2030.flags new file mode 100644 index 000000000000..cab9e99af3a9 --- /dev/null +++ b/test/files/pos/t2030.flags @@ -0,0 +1 @@ +-Xsource:3.0 diff --git a/test/files/pos/t2030.scala b/test/files/pos/t2030.scala new file mode 100644 index 000000000000..2333c3981b99 --- /dev/null +++ b/test/files/pos/t2030.scala @@ -0,0 +1,8 @@ +import scala.collection.immutable._ + +object Test extends App { + val res0 = TreeSet(1, 2, 3, 4, 5, 6) + val res1 = res0.map(x => x) + println(res0.toList == res1.toList) + println(res1.getClass) +} diff --git a/test/files/pos/t2509-5.flags b/test/files/pos/t2509-5.flags new file mode 100644 index 000000000000..cab9e99af3a9 --- /dev/null +++ b/test/files/pos/t2509-5.flags @@ -0,0 +1 @@ +-Xsource:3.0 diff --git a/test/files/pos/t2509-5.scala b/test/files/pos/t2509-5.scala new file mode 100644 index 000000000000..c8ebd04d3886 --- /dev/null +++ b/test/files/pos/t2509-5.scala @@ -0,0 +1,13 @@ +// See https://github.com/lampepfl/dotty/issues/2974 +trait Foo[-T] + +trait Bar[-T] extends Foo[T] + +object Test { + implicit val fa: Foo[Any] = ??? + implicit val ba: Bar[Int] = ??? + + def test: Unit = { + implicitly[Foo[Int]] + } +} diff --git a/test/files/pos/t2509-6.flags b/test/files/pos/t2509-6.flags new file mode 100644 index 000000000000..cab9e99af3a9 --- /dev/null +++ b/test/files/pos/t2509-6.flags @@ -0,0 +1 @@ +-Xsource:3.0 diff --git a/test/files/pos/t2509-6.scala b/test/files/pos/t2509-6.scala new file mode 100644 index 000000000000..2c2ef2e821ed --- /dev/null +++ b/test/files/pos/t2509-6.scala @@ -0,0 +1,33 @@ +class A +class B extends A + +trait Y { + def value: String +} + +trait X[-T] { + def y(t: T): Y +} + +trait Z[-T] extends X[T] + +object XA extends X[A] { + def y(a: A) = new Y { def value = s"${a.getClass}: AValue" } +} + +object ZB extends Z[B] { + def y(b: B) = new Y { def value = s"${b.getClass}: BValue" } +} + +object Test { + implicit def f[T](t: T)(implicit x: X[T]): Y = x.y(t) + implicit val za: X[A] = XA + implicit val xb: Z[B] = ZB + + def main(argv: Array[String]): Unit = { + val a = new A + val b = new B + println("A: " + a.value) + println("B: " + b.value) + } +} diff --git a/test/files/pos/t2509-7a.flags b/test/files/pos/t2509-7a.flags new file mode 100644 index 000000000000..cab9e99af3a9 --- /dev/null +++ b/test/files/pos/t2509-7a.flags @@ -0,0 +1 @@ +-Xsource:3.0 diff --git a/test/files/pos/t2509-7a.scala b/test/files/pos/t2509-7a.scala new file mode 100644 index 000000000000..a6a7241d186f --- /dev/null +++ b/test/files/pos/t2509-7a.scala @@ -0,0 +1,31 @@ +class Both[-A, +B] + +trait Factory[A] { + implicit def make: Both[A, A] = new Both[A, A] +} + +trait X +object X extends Factory[X] { + override implicit def make: Both[X, X] = super.make +} + +class Y extends X +object Y extends Factory[Y] { + // See test/files/neg/t2509-7b.scala ... discussion below + override implicit def make: Both[Y, Y] = super.make +} + +object Test { + def get(implicit ev: Both[Y, X]) = ev + + // There are two possible implicits here: X.make and Y.make, neither are + // subtype of each other, so who wins? + // - Under the old scheme it's X.make because `isAsGood` sees that X.make is defined + // in X whereas Y.make is defined in Factory + // - Under the new scheme it's ambiguous because we replace contravariance by covariance + // in top-level type parameters so Y.make is treated as a subtype of X.make + // In both schemes we can get Y.make to win by uncommenting the override for make in Y + // (Y wins against X because `isDerived` also considers the subtyping relationships + // of companion classes) + get +} diff --git a/test/files/run/t2509-1.check b/test/files/run/t2509-1.check new file mode 100644 index 000000000000..f219e05cd02d --- /dev/null +++ b/test/files/run/t2509-1.check @@ -0,0 +1,2 @@ +A: class A: AValue +B: class B: BValue diff --git a/test/files/run/t2509-1.flags b/test/files/run/t2509-1.flags new file mode 100644 index 000000000000..cab9e99af3a9 --- /dev/null +++ b/test/files/run/t2509-1.flags @@ -0,0 +1 @@ +-Xsource:3.0 diff --git a/test/files/run/t2509-1.scala b/test/files/run/t2509-1.scala new file mode 100644 index 000000000000..e408209530e0 --- /dev/null +++ b/test/files/run/t2509-1.scala @@ -0,0 +1,33 @@ +import scala.language.implicitConversions + +class A +class B extends A + +trait Y { + def value: String +} + +trait X[-T] { + def y(t: T): Y +} + +object XA extends X[A] { + def y(a: A) = new Y { def value = s"${a.getClass}: AValue" } +} + +object XB extends X[B] { + def y(b: B) = new Y { def value = s"${b.getClass}: BValue" } +} + +object Test { + implicit def f[T](t: T)(implicit x: X[T]): Y = x.y(t) + implicit val xa: X[A] = XA + implicit val xb: X[B] = XB + + def main(argv: Array[String]): Unit = { + val a = new A + val b = new B + println(s"A: ${a.value}") + println(s"B: ${b.value}") + } +} diff --git a/test/files/run/t2509-4.check b/test/files/run/t2509-4.check new file mode 100644 index 000000000000..f219e05cd02d --- /dev/null +++ b/test/files/run/t2509-4.check @@ -0,0 +1,2 @@ +A: class A: AValue +B: class B: BValue diff --git a/test/files/run/t2509-4.flags b/test/files/run/t2509-4.flags new file mode 100644 index 000000000000..cab9e99af3a9 --- /dev/null +++ b/test/files/run/t2509-4.flags @@ -0,0 +1 @@ +-Xsource:3.0 diff --git a/test/files/run/t2509-4.scala b/test/files/run/t2509-4.scala new file mode 100644 index 000000000000..b511b10d48ad --- /dev/null +++ b/test/files/run/t2509-4.scala @@ -0,0 +1,35 @@ +import scala.language.implicitConversions + +class A +class B extends A + +trait Y { + def value: String +} + +trait X[-T] { + def y(t: T): Y +} + +trait Z[-T] extends X[T] + +object XA extends Z[A] { + def y(a: A) = new Y { def value = s"${a.getClass}: AValue" } +} + +object ZB extends Z[B] { + def y(b: B) = new Y { def value = s"${b.getClass}: BValue" } +} + +object Test { + implicit def f[T](t: T)(implicit x: X[T]): Y = x.y(t) + implicit val za: X[A] = XA + implicit val xb: Z[B] = ZB + + def main(argv: Array[String]): Unit = { + val a = new A + val b = new B + println(s"A: ${a.value}") + println(s"B: ${b.value}") + } +} diff --git a/test/files/run/t7768.check b/test/files/run/t7768.check new file mode 100644 index 000000000000..d7b53d035df3 --- /dev/null +++ b/test/files/run/t7768.check @@ -0,0 +1,3 @@ +Inv[A] Inv[B] Inv[C] Inv[D] Inv[E] +Con[A] Con[A] Con[C] Con[C] Con[E] +Cov[E] Cov[E] Cov[E] Cov[E] Cov[E] diff --git a/test/files/run/t7768.flags b/test/files/run/t7768.flags new file mode 100644 index 000000000000..cab9e99af3a9 --- /dev/null +++ b/test/files/run/t7768.flags @@ -0,0 +1 @@ +-Xsource:3.0 diff --git a/test/files/run/t7768.scala b/test/files/run/t7768.scala new file mode 100644 index 000000000000..23c1d6e2b41e --- /dev/null +++ b/test/files/run/t7768.scala @@ -0,0 +1,89 @@ +class A +class B extends A +class C extends B +class D extends C +class E extends D + +class Inv[T](override val toString: String) +class Con[-T](override val toString: String) +class Cov[+T](override val toString: String) + +object InvTest { + implicit val a : Inv[A] = new Inv[A]("Inv[A]") + implicit val b : Inv[B] = new Inv[B]("Inv[B]") + implicit val c : Inv[C] = new Inv[C]("Inv[C]") + implicit val d : Inv[D] = new Inv[D]("Inv[D]") + implicit val e : Inv[E] = new Inv[E]("Inv[E]") +} +object ConTest { + implicit val a : Con[A] = new Con[A]("Con[A]") + implicit val c : Con[C] = new Con[C]("Con[C]") + implicit val e : Con[E] = new Con[E]("Con[E]") +} +object CovTest { + implicit val a : Cov[A] = new Cov[A]("Cov[A]") + implicit val c : Cov[C] = new Cov[C]("Cov[C]") + implicit val e : Cov[E] = new Cov[E]("Cov[E]") +} + +object Test { + def f0(): Unit = { + import InvTest._ + println(List( + implicitly[Inv[A]], + implicitly[Inv[B]], + implicitly[Inv[C]], + implicitly[Inv[D]], + implicitly[Inv[E]] + ) mkString " ") + } + def f1(): Unit = { + import ConTest._ + println(List( + implicitly[Con[A]], + implicitly[Con[B]], + implicitly[Con[C]], + implicitly[Con[D]], + implicitly[Con[E]] + ) mkString " ") + } + def f2(): Unit = { + import CovTest._ + println(List( + implicitly[Cov[A]], + implicitly[Cov[B]], + implicitly[Cov[C]], + implicitly[Cov[D]], + implicitly[Cov[E]] + ) mkString " ") + } + + def main(args: Array[String]): Unit = { + f0() + f1() + f2() + } +} + +/*** + +Previously: + +Inv[A] Inv[B] Inv[C] Inv[D] Inv[E] +Con[A] Con[A] Con[A] Con[A] Con[A] +Cov[E] Cov[E] Cov[E] Cov[E] Cov[E] + +Currently (and in Dotty): + +Inv[A] Inv[B] Inv[C] Inv[D] Inv[E] +Con[A] Con[A] Con[C] Con[C] Con[E] +Cov[E] Cov[E] Cov[E] Cov[E] Cov[E] + +Note that @paulp thinks that f2 should produce, + +Cov[A] Cov[C] Cov[C] Cov[E] Cov[E] + +I don't think that behaviour would be desirable: in the covariant case the +expectation that the most derived should be selected as the most specific +seems reasonable. +***/ diff --git a/test/junit/scala/tools/nsc/typechecker/Infer.scala b/test/junit/scala/tools/nsc/typechecker/Infer.scala new file mode 100644 index 000000000000..3362086d157d --- /dev/null +++ b/test/junit/scala/tools/nsc/typechecker/Infer.scala @@ -0,0 +1,169 @@ +package scala.tools.nsc +package typechecker + +import org.junit.{ After, Before, Test } +import org.junit.runner.RunWith +import org.junit.runners.JUnit4 + +import scala.tools.nsc.settings.ScalaVersion +import scala.tools.testing.BytecodeTesting + +class A +class B extends A + +trait C + +trait X[+T] +trait Y[T] +trait Z[-T] +trait Quux[-T] extends Z[T] + +trait SubZB extends Z[B] +trait ZwC[-T] extends Z[T] with C + +@RunWith(classOf[JUnit4]) +class InferencerTests extends BytecodeTesting { + import compiler.global._, analyzer._ + + var storedXsource: ScalaVersion = null + @Before + def storeXsource: Unit = { + storedXsource = settings.source.value + } + @After + def restoreXsource: Unit = { + settings.source.value = storedXsource + } + + @Test + def isAsSpecificScala2(): Unit = { + val run = new global.Run + + enteringPhase(run.typerPhase) { + val XA = typeOf[X[A]] + val XB = typeOf[X[B]] + + val YA = typeOf[Y[A]] + val YB = typeOf[Y[B]] + + val ZA = typeOf[Z[A]] + val ZB = typeOf[Z[B]] + + val LZA = typeOf[List[Z[A]]] + val LZB = typeOf[List[Z[B]]] + + val QuuxA = typeOf[Quux[A]] + val QuuxB = typeOf[Quux[B]] + + val SubZB = typeOf[SubZB] + val ZBwC = typeOf[ZwC[B]] + + // https://github.com/scala/bug/issues/2509 + // See discussion at https://github.com/lampepfl/dotty/blob/89540268e6c49fb92b9ca61249e46bb59981bf5a/src/dotty/tools/dotc/typer/Applications.scala#L925-L951 + + // Covariant + assert(!typer.infer.isAsSpecific(XA, XB)) + assert(typer.infer.isAsSpecific(XB, XA)) + + // Invariant + assert(!typer.infer.isAsSpecific(YA, YB)) + assert(!typer.infer.isAsSpecific(YB, YA)) + + // Contravariant: Scala 2 treats subtype/least derived as most specific + assert(typer.infer.isAsSpecific(ZA, ZB)) + assert(!typer.infer.isAsSpecific(ZB, ZA)) + + // Inner contravariant: Scala 2 treats subtype/least derived as most specific + assert(typer.infer.isAsSpecific(LZA, LZB)) + assert(!typer.infer.isAsSpecific(LZB, LZA)) + + // Subtypes of contravaraint effectively unrelated + assert(!typer.infer.isAsSpecific(ZA, SubZB)) + assert(!typer.infer.isAsSpecific(SubZB, ZA)) + + // Subtypes of contravaraint effectively unrelated + assert(!typer.infer.isAsSpecific(ZA, ZBwC)) + assert(!typer.infer.isAsSpecific(ZBwC, ZA)) + + // Contravariant outer subtypes + assert(!typer.infer.isAsSpecific(ZA, QuuxA)) + assert(typer.infer.isAsSpecific(QuuxA, ZA)) + + assert(!typer.infer.isAsSpecific(ZA, QuuxB)) + assert(!typer.infer.isAsSpecific(QuuxB, ZA)) + + assert(!typer.infer.isAsSpecific(ZB, QuuxA)) + assert(typer.infer.isAsSpecific(QuuxA, ZB)) + + assert(!typer.infer.isAsSpecific(ZB, QuuxB)) + assert(typer.infer.isAsSpecific(QuuxB, ZB)) + } + } + + @Test + def isAsSpecificScala3(): Unit = { + settings.source.value = ScalaVersion("3.0") + + val run = new global.Run + + enteringPhase(run.typerPhase) { + val XA = typeOf[X[A]] + val XB = typeOf[X[B]] + + val YA = typeOf[Y[A]] + val YB = typeOf[Y[B]] + + val ZA = typeOf[Z[A]] + val ZB = typeOf[Z[B]] + + val LZA = typeOf[List[Z[A]]] + val LZB = typeOf[List[Z[B]]] + + val QuuxA = typeOf[Quux[A]] + val QuuxB = typeOf[Quux[B]] + + val SubZB = typeOf[SubZB] + val ZBwC = typeOf[ZwC[B]] + + // https://github.com/scala/bug/issues/2509 + // See discussion at https://github.com/lampepfl/dotty/blob/89540268e6c49fb92b9ca61249e46bb59981bf5a/src/dotty/tools/dotc/typer/Applications.scala#L925-L951 + + // Covariant + assert(!typer.infer.isAsSpecific(XA, XB)) + assert(typer.infer.isAsSpecific(XB, XA)) + + // Invariant + assert(!typer.infer.isAsSpecific(YA, YB)) + assert(!typer.infer.isAsSpecific(YB, YA)) + + // Contravariant: treat top level as covariant + assert(!typer.infer.isAsSpecific(ZA, ZB)) + assert(typer.infer.isAsSpecific(ZB, ZA)) + + // Inner contravariant: also changed + assert(!typer.infer.isAsSpecific(LZA, LZB)) + assert(typer.infer.isAsSpecific(LZB, LZA)) + + // Subtypes of contravaraint effectively unrelated + assert(!typer.infer.isAsSpecific(ZA, SubZB)) + assert(typer.infer.isAsSpecific(SubZB, ZA)) + + // Subtypes of contravaraint effectively unrelated + assert(!typer.infer.isAsSpecific(ZA, ZBwC)) + assert(typer.infer.isAsSpecific(ZBwC, ZA)) + + // Contravariant outer subtypes + assert(!typer.infer.isAsSpecific(ZA, QuuxA)) + assert(typer.infer.isAsSpecific(QuuxA, ZA)) + + assert(!typer.infer.isAsSpecific(ZA, QuuxB)) + assert(typer.infer.isAsSpecific(QuuxB, ZA)) + + assert(!typer.infer.isAsSpecific(ZB, QuuxA)) + assert(!typer.infer.isAsSpecific(QuuxA, ZB)) + + assert(!typer.infer.isAsSpecific(ZB, QuuxB)) + assert(typer.infer.isAsSpecific(QuuxB, ZB)) + } + } +} From 8a08d250504b7e09b255fe9ea89259737ad2f6a1 Mon Sep 17 00:00:00 2001 From: Josh Lemer Date: Sat, 4 Aug 2018 20:43:17 -0400 Subject: [PATCH 123/143] [11050] ArrayDeque correctly resets with new Array when inserting and resize is necessary. Fixes scala/bug#11050 --- src/library/scala/collection/mutable/ArrayDeque.scala | 1 + test/junit/scala/collection/mutable/ArrayDequeTest.scala | 7 +++++++ test/junit/scala/collection/mutable/QueueTest.scala | 9 ++++++++- test/junit/scala/collection/mutable/StackTest.scala | 7 +++++++ 4 files changed, 23 insertions(+), 1 deletion(-) diff --git a/src/library/scala/collection/mutable/ArrayDeque.scala b/src/library/scala/collection/mutable/ArrayDeque.scala index e9194a545854..595e9ad3e263 100644 --- a/src/library/scala/collection/mutable/ArrayDeque.scala +++ b/src/library/scala/collection/mutable/ArrayDeque.scala @@ -138,6 +138,7 @@ class ArrayDeque[A] protected ( copySliceToArray(srcStart = 0, dest = array2, destStart = 0, maxItems = idx) array2(idx) = elem.asInstanceOf[AnyRef] copySliceToArray(srcStart = idx, dest = array2, destStart = idx + 1, maxItems = n) + reset(array = array2, start = 0, end = finalLength) } else if (n <= idx * 2) { var i = n - 1 while(i >= idx) { diff --git a/test/junit/scala/collection/mutable/ArrayDequeTest.scala b/test/junit/scala/collection/mutable/ArrayDequeTest.scala index 33f987b0646c..effefb85bc45 100644 --- a/test/junit/scala/collection/mutable/ArrayDequeTest.scala +++ b/test/junit/scala/collection/mutable/ArrayDequeTest.scala @@ -71,4 +71,11 @@ class ArrayDequeTest { val target = Array[Int]() assertEquals(0, collection.mutable.ArrayDeque(1, 2).copyToArray(target, 1, 0)) } + + @Test + def insertsWhenResizeIsNeeded: Unit = { + val arrayDeque = ArrayDeque.from(Array.range(0, 15)) + arrayDeque.insert(1, -1) + assertEquals(ArrayDeque(0, -1, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14), arrayDeque) + } } diff --git a/test/junit/scala/collection/mutable/QueueTest.scala b/test/junit/scala/collection/mutable/QueueTest.scala index 38f0595bd387..23407ff85fe2 100644 --- a/test/junit/scala/collection/mutable/QueueTest.scala +++ b/test/junit/scala/collection/mutable/QueueTest.scala @@ -33,6 +33,13 @@ class QueueTest { @Test def copyToArrayOutOfBounds: Unit = { val target = Array[Int]() - assertEquals(0, mutable.Queue(1,2).copyToArray(target, 1, 0)) + assertEquals(0, mutable.Queue(1, 2).copyToArray(target, 1, 0)) + } + + @Test + def insertsWhenResizeIsNeeded: Unit = { + val q = Queue.from(Array.range(0, 15)) + q.insert(1, -1) + assertEquals(Queue(0, -1, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14), q) } } diff --git a/test/junit/scala/collection/mutable/StackTest.scala b/test/junit/scala/collection/mutable/StackTest.scala index 99b0e1d7e572..3d36b20c0696 100644 --- a/test/junit/scala/collection/mutable/StackTest.scala +++ b/test/junit/scala/collection/mutable/StackTest.scala @@ -15,4 +15,11 @@ class StackTest { val s2: Stack[Int] = s1.reverse assertEquals("Stack", s2.collectionClassName) } + + @Test + def insertsWhenResizeIsNeeded: Unit = { + val stack = Stack.from(Array.range(0, 15)) + stack.insert(1, -1) + assertEquals(Stack(0, -1, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14), stack) + } } From 36ed6d48d66f85684aced477ae627411e852a4e0 Mon Sep 17 00:00:00 2001 From: Georgi Krastev Date: Mon, 26 Feb 2018 16:46:53 +0100 Subject: [PATCH 124/143] lub/glb uses correct kind for higher-order type args When computing the `lub/glb` of HKTs take care to produce well-kinded types when merging type constructor arguments that are supplied for a type constructor parameter. This improves type inference. A few tests with `-Xstrict-inference` were changed. Other tests reveal a limitation of higher-kinded existentials. Fixes scala/bug#8882 and promotes scala/bug#10700 to an error. --- .../scala/reflect/internal/Types.scala | 29 ++++++++----- test/files/neg/hk-bad-bounds.check | 4 +- test/files/neg/t10700.check | 4 ++ test/files/neg/t10700.flags | 1 + test/files/neg/t10700.scala | 4 ++ test/files/pos/t8882.flags | 1 + test/files/pos/t8882.scala | 8 ++++ test/files/run/invalid-lubs.check | 41 +++---------------- test/files/run/invalid-lubs.scala | 2 +- 9 files changed, 45 insertions(+), 49 deletions(-) create mode 100644 test/files/neg/t10700.check create mode 100644 test/files/neg/t10700.flags create mode 100644 test/files/neg/t10700.scala create mode 100644 test/files/pos/t8882.flags create mode 100644 test/files/pos/t8882.scala diff --git a/src/reflect/scala/reflect/internal/Types.scala b/src/reflect/scala/reflect/internal/Types.scala index 57a92735685f..7dfa2141e2ef 100644 --- a/src/reflect/scala/reflect/internal/Types.scala +++ b/src/reflect/scala/reflect/internal/Types.scala @@ -4697,9 +4697,9 @@ trait Types case tp :: Nil => tp case TypeRef(_, sym, _) :: rest => val pres = tps map (_.prefix) // prefix normalizes automatically - val pre = if (variance.isPositive) lub(pres, depth) else glb(pres, depth) + val pre = if (variance.isPositive) lub(pres, depth) else glb(pres, depth) val argss = tps map (_.normalize.typeArgs) // symbol equality (of the tp in tps) was checked using typeSymbol, which normalizes, so should normalize before retrieving arguments - val capturedParams = new ListBuffer[Symbol] + val capturedParams = new ListBuffer[Symbol] try { if (sym == ArrayClass && phase.erasedTypes) { // special treatment for lubs of array types after erasure: @@ -4736,19 +4736,28 @@ trait Types NoType } else { - if (tparam.variance == variance) lub(as, depth.decr) - else if (tparam.variance == variance.flip) glb(as, depth.decr) + val hktParams = tparam.initialize.typeParams + val hktArgs = hktParams.map(_.typeConstructor) + def applyHK(tp: Type) = appliedType(tp, hktArgs) + def bindHK(tp: Type) = typeFun(hktParams, tp) + // Make `as` well-kinded by binding higher-order type params of `tparam` + // (so that the type arguments in `as` have the same kind as the type parameter `tparam`). + val asKinded = if (hktParams.isEmpty) as else as.map(a => bindHK(applyHK(a))) + + if (tparam.variance == variance) lub(asKinded, depth.decr) + else if (tparam.variance == variance.flip) glb(asKinded, depth.decr) else { - val l = lub(as, depth.decr) - val g = glb(as, depth.decr) + val l = lub(asKinded, depth.decr) + val g = glb(asKinded, depth.decr) if (l <:< g) l - else { // Martin: I removed this, because incomplete. Not sure there is a good way to fix it. For the moment we + else { + // @M this has issues with f-bounds, see #2251 + // Martin: Not sure there is a good way to fix it. For the moment we // just err on the conservative side, i.e. with a bound that is too high. - // if(!(tparam.info.bounds contains tparam)) //@M can't deal with f-bounds, see #2251 capturedParamIds += 1 val capturedParamId = capturedParamIds - - val qvar = commonOwner(as).freshExistential("", capturedParamId) setInfo TypeBounds(g, l) + val bounds = if (hktParams.isEmpty) TypeBounds(g, l) else bindHK(TypeBounds(applyHK(g), applyHK(l))) + val qvar = commonOwner(as).freshExistential("", capturedParamId) setInfo bounds capturedParams += qvar qvar.tpe } diff --git a/test/files/neg/hk-bad-bounds.check b/test/files/neg/hk-bad-bounds.check index 73947078a9e9..26c30d9f0e5f 100644 --- a/test/files/neg/hk-bad-bounds.check +++ b/test/files/neg/hk-bad-bounds.check @@ -1,4 +1,4 @@ -hk-bad-bounds.scala:4: error: type arguments [Set] do not conform to trait SeqFactory's type parameter bounds [CC[X] <: Seq[X]] +hk-bad-bounds.scala:4: error: can't existentially abstract over parameterized type _1[X] def f(x: Boolean) = if (x) (null: SeqFactory[List]) else (null: SeqFactory[Set]) - ^ + ^ one error found diff --git a/test/files/neg/t10700.check b/test/files/neg/t10700.check new file mode 100644 index 000000000000..5143d59bba62 --- /dev/null +++ b/test/files/neg/t10700.check @@ -0,0 +1,4 @@ +t10700.scala:3: error: can't existentially abstract over parameterized type _1[_] + def foo(b: Boolean) = if (b) new Foo[List] else new Foo[Option] + ^ +one error found diff --git a/test/files/neg/t10700.flags b/test/files/neg/t10700.flags new file mode 100644 index 000000000000..b5c02117c012 --- /dev/null +++ b/test/files/neg/t10700.flags @@ -0,0 +1 @@ +-language:higherKinds diff --git a/test/files/neg/t10700.scala b/test/files/neg/t10700.scala new file mode 100644 index 000000000000..3fd610a1a6de --- /dev/null +++ b/test/files/neg/t10700.scala @@ -0,0 +1,4 @@ +object Test { + class Foo[F[_]] + def foo(b: Boolean) = if (b) new Foo[List] else new Foo[Option] +} diff --git a/test/files/pos/t8882.flags b/test/files/pos/t8882.flags new file mode 100644 index 000000000000..b5c02117c012 --- /dev/null +++ b/test/files/pos/t8882.flags @@ -0,0 +1 @@ +-language:higherKinds diff --git a/test/files/pos/t8882.scala b/test/files/pos/t8882.scala new file mode 100644 index 000000000000..7681a9a95fb6 --- /dev/null +++ b/test/files/pos/t8882.scala @@ -0,0 +1,8 @@ +object Test { + class A[T[_]] + object B extends A[List] + object C extends A[Option] + + val values1 = Seq[Any](B, C) + val values2 = Seq(B, C) +} diff --git a/test/files/run/invalid-lubs.check b/test/files/run/invalid-lubs.check index b2671e823d63..0683e29c1d3d 100644 --- a/test/files/run/invalid-lubs.check +++ b/test/files/run/invalid-lubs.check @@ -1,48 +1,17 @@ scala> def foo(a: Boolean, b: List[Any], c: collection.mutable.ListBuffer[Any]) = if (a) b else c - ^ - error: kinds of the type arguments (Any,scala.collection.AbstractSeq with scala.collection.StrictOptimizedSeqOps[Any,scala.collection.AbstractSeq with scala.collection.StrictOptimizedSeqOps[Any,scala.collection.AbstractSeq,Serializable with Equals],scala.collection.AbstractSeq[Any] with scala.collection.StrictOptimizedSeqOps[Any,scala.collection.AbstractSeq,Serializable with Equals]],scala.collection.AbstractSeq[Any] with scala.collection.StrictOptimizedSeqOps[Any,scala.collection.AbstractSeq with scala.collection.StrictOptimizedSeqOps[Any,scala.collection.AbstractSeq,Serializable with Equals],scala.collection.AbstractSeq[Any] with scala.collection.StrictOptimizedSeqOps[Any,scala.collection.AbstractSeq,scala.collection.AbstractSeq[Any]]]) do not conform to the expected kinds of the type parameters (type A,type CC,type C) in trait StrictOptimizedSeqOps. - scala.collection.AbstractSeq with scala.collection.StrictOptimizedSeqOps[Any,scala.collection.AbstractSeq with scala.collection.StrictOptimizedSeqOps[Any,scala.collection.AbstractSeq,Serializable with Equals],scala.collection.AbstractSeq[Any] with scala.collection.StrictOptimizedSeqOps[Any,scala.collection.AbstractSeq,Serializable with Equals]]'s type parameters do not match type CC's expected parameters: - A with scala.collection.StrictOptimizedSeqOps[Any,scala.collection.AbstractSeq with scala.collection.StrictOptimizedSeqOps[Any,scala.collection.AbstractSeq,Serializable with Equals],scala.collection.AbstractSeq[Any] with scala.collection.StrictOptimizedSeqOps[Any,scala.collection.AbstractSeq,Serializable with Equals]]> has no type parameters, but type CC has one +foo: (a: Boolean, b: List[Any], c: scala.collection.mutable.ListBuffer[Any])scala.collection.AbstractSeq[Any] with scala.collection.StrictOptimizedSeqOps[Any,[_]scala.collection.AbstractSeq[_] with scala.collection.StrictOptimizedSeqOps[_,[_]scala.collection.AbstractSeq[_] with scala.collection.StrictOptimizedSeqOps[_,[_]scala.collection.AbstractSeq[_],scala.collection.AbstractSeq[_]],scala.collection.AbstractSeq[_] with scala.collection.StrictOptimizedSeqOps[_,[_]scala.collection.AbstractSeq[_],scala.collection.AbstractSeq[_]]],scala.collection.AbstractSeq[Any] with scala.collection.StrictOptimizedSeqOps[Any,[_]scala.collection.AbstractSeq[_] with scala.collection.StrictOptimizedSeqOps[_,[_]scala.collection.AbstractSeq[_],scala.collection.AbstractSeq[_]],scala.collection.AbstractSeq[Any] with scala.collection.StrictOptimizedSeqOps[Any,[_]scala.collection.AbstractSeq[_],scala.collection.AbstractSeq[Any]]]] scala> List(List[Any](), collection.mutable.ListBuffer[Any]()) - ^ - error: type mismatch; - found : List[Any] - required: scala.collection.AbstractSeq[Any] with scala.collection.StrictOptimizedSeqOps[Any,scala.collection.AbstractSeq with scala.collection.StrictOptimizedSeqOps[Any,scala.collection.AbstractSeq with scala.collection.StrictOptimizedSeqOps[Any,scala.collection.AbstractSeq,Serializable with Equals],scala.collection.AbstractSeq[Any] with scala.collection.StrictOptimizedSeqOps[Any,scala.collection.AbstractSeq,Serializable with Equals]],scala.collection.AbstractSeq[Any] with scala.collection.StrictOptimizedSeqOps[Any,scala.collection.AbstractSeq with scala.collection.StrictOptimizedSeqOps[Any,scala.collection.AbstractSeq,Serializable with Equals],scala.collection.AbstractSeq[Any] with scala.collection.StrictOptimizedSeqOps[Any,scala.collection.AbstractSeq,scala.collection.AbstractSeq[Any]]]] - ^ - error: type mismatch; - found : scala.collection.mutable.ListBuffer[Any] - required: scala.collection.AbstractSeq[Any] with scala.collection.StrictOptimizedSeqOps[Any,scala.collection.AbstractSeq with scala.collection.StrictOptimizedSeqOps[Any,scala.collection.AbstractSeq with scala.collection.StrictOptimizedSeqOps[Any,scala.collection.AbstractSeq,Serializable with Equals],scala.collection.AbstractSeq[Any] with scala.collection.StrictOptimizedSeqOps[Any,scala.collection.AbstractSeq,Serializable with Equals]],scala.collection.AbstractSeq[Any] with scala.collection.StrictOptimizedSeqOps[Any,scala.collection.AbstractSeq with scala.collection.StrictOptimizedSeqOps[Any,scala.collection.AbstractSeq,Serializable with Equals],scala.collection.AbstractSeq[Any] with scala.collection.StrictOptimizedSeqOps[Any,scala.collection.AbstractSeq,scala.collection.AbstractSeq[Any]]]] +res0: List[scala.collection.AbstractSeq[Any] with scala.collection.StrictOptimizedSeqOps[Any,[_]scala.collection.AbstractSeq[_] with scala.collection.StrictOptimizedSeqOps[_,[_]scala.collection.AbstractSeq[_] with scala.collection.StrictOptimizedSeqOps[_,[_]scala.collection.AbstractSeq[_],scala.collection.AbstractSeq[_]],scala.collection.AbstractSeq[_] with scala.collection.StrictOptimizedSeqOps[_,[_]scala.collection.AbstractSeq[_],scala.collection.AbstractSeq[_]]],scala.collection.AbstractSeq[Any] with scala.collection.StrictOptimizedSeqOps[Any,[_]scala.collection.AbstractSeq[_] with scala.collection.StrictOptimizedSeqOps[_,[_]scala.collection.AbstractSeq[_],scala.collection.AbstractSeq[_]],scala.collection.AbstractSeq[Any] with scala.collection.StrictOptimizedSeqOps[Any,[_]scala.collection.AbstractSeq[_],scala.collection.AbstractSeq[Any]]]]] = List(List(), ListBuffer()) scala> List(List(), collection.mutable.ListBuffer()) - ^ - error: type mismatch; - found : List[Nothing] - required: scala.collection.AbstractSeq[Nothing] with scala.collection.StrictOptimizedSeqOps[Nothing,scala.collection.AbstractSeq with scala.collection.StrictOptimizedSeqOps[Any,scala.collection.AbstractSeq with scala.collection.StrictOptimizedSeqOps[Any,scala.collection.AbstractSeq,Serializable with Equals],scala.collection.AbstractSeq[Any] with scala.collection.StrictOptimizedSeqOps[Any,scala.collection.AbstractSeq,Serializable with Equals]],scala.collection.AbstractSeq[Nothing] with scala.collection.StrictOptimizedSeqOps[Nothing,scala.collection.AbstractSeq with scala.collection.StrictOptimizedSeqOps[Any,scala.collection.AbstractSeq,Serializable with Equals],scala.collection.AbstractSeq[Nothing] with scala.collection.StrictOptimizedSeqOps[Nothing,scala.collection.AbstractSeq,scala.collection.AbstractSeq[Nothing]]]] - ^ - error: type mismatch; - found : scala.collection.mutable.ListBuffer[Nothing] - required: scala.collection.AbstractSeq[Nothing] with scala.collection.StrictOptimizedSeqOps[Nothing,scala.collection.AbstractSeq with scala.collection.StrictOptimizedSeqOps[Any,scala.collection.AbstractSeq with scala.collection.StrictOptimizedSeqOps[Any,scala.collection.AbstractSeq,Serializable with Equals],scala.collection.AbstractSeq[Any] with scala.collection.StrictOptimizedSeqOps[Any,scala.collection.AbstractSeq,Serializable with Equals]],scala.collection.AbstractSeq[Nothing] with scala.collection.StrictOptimizedSeqOps[Nothing,scala.collection.AbstractSeq with scala.collection.StrictOptimizedSeqOps[Any,scala.collection.AbstractSeq,Serializable with Equals],scala.collection.AbstractSeq[Nothing] with scala.collection.StrictOptimizedSeqOps[Nothing,scala.collection.AbstractSeq,scala.collection.AbstractSeq[Nothing]]]] +res1: List[scala.collection.AbstractSeq[Nothing] with scala.collection.StrictOptimizedSeqOps[Nothing,[_]scala.collection.AbstractSeq[_] with scala.collection.StrictOptimizedSeqOps[_,[_]scala.collection.AbstractSeq[_] with scala.collection.StrictOptimizedSeqOps[_,[_]scala.collection.AbstractSeq[_],scala.collection.AbstractSeq[_]],scala.collection.AbstractSeq[_] with scala.collection.StrictOptimizedSeqOps[_,[_]scala.collection.AbstractSeq[_],scala.collection.AbstractSeq[_]]],scala.collection.AbstractSeq[Nothing] with scala.collection.StrictOptimizedSeqOps[Nothing,[_]scala.collection.AbstractSeq[_] with scala.collection.StrictOptimizedSeqOps[_,[_]scala.collection.AbstractSeq[_],scala.collection.AbstractSeq[_]],scala.collection.AbstractSeq[Nothing] with scala.collection.StrictOptimizedSeqOps[Nothing,[_]scala.collection.AbstractSeq[_],scala.collection.AbstractSeq[Nothing]]]]] = List(List(), ListBuffer()) scala> List(List(), Vector()) - ^ - error: type mismatch; - found : List[Nothing] - required: scala.collection.immutable.AbstractSeq[Nothing] with scala.collection.immutable.StrictOptimizedSeqOps[Nothing,scala.collection.immutable.AbstractSeq with scala.collection.immutable.StrictOptimizedSeqOps[Any,scala.collection.immutable.AbstractSeq with scala.collection.immutable.StrictOptimizedSeqOps[Any,scala.collection.immutable.AbstractSeq,Serializable with Equals],scala.collection.immutable.AbstractSeq[Any] with scala.collection.immutable.StrictOptimizedSeqOps[Any,scala.collection.immutable.AbstractSeq,Serializable with Equals]],scala.collection.immutable.AbstractSeq[Nothing] with scala.collection.immutable.StrictOptimizedSeqOps[Nothing,scala.collection.immutable.AbstractSeq with scala.collection.immutable.StrictOptimizedSeqOps[Any,scala.collection.immutable.AbstractSeq,Serializable with Equals],scala.collection.immutable.AbstractSeq[Nothing] with scala.collection.immutable.StrictOptimizedSeqOps[Nothing,scala.collection.immutable.AbstractSeq,scala.collection.immutable.AbstractSeq[Nothing]]]] - ^ - error: type mismatch; - found : scala.collection.immutable.Vector[Nothing] - required: scala.collection.immutable.AbstractSeq[Nothing] with scala.collection.immutable.StrictOptimizedSeqOps[Nothing,scala.collection.immutable.AbstractSeq with scala.collection.immutable.StrictOptimizedSeqOps[Any,scala.collection.immutable.AbstractSeq with scala.collection.immutable.StrictOptimizedSeqOps[Any,scala.collection.immutable.AbstractSeq,Serializable with Equals],scala.collection.immutable.AbstractSeq[Any] with scala.collection.immutable.StrictOptimizedSeqOps[Any,scala.collection.immutable.AbstractSeq,Serializable with Equals]],scala.collection.immutable.AbstractSeq[Nothing] with scala.collection.immutable.StrictOptimizedSeqOps[Nothing,scala.collection.immutable.AbstractSeq with scala.collection.immutable.StrictOptimizedSeqOps[Any,scala.collection.immutable.AbstractSeq,Serializable with Equals],scala.collection.immutable.AbstractSeq[Nothing] with scala.collection.immutable.StrictOptimizedSeqOps[Nothing,scala.collection.immutable.AbstractSeq,scala.collection.immutable.AbstractSeq[Nothing]]]] +res2: List[scala.collection.immutable.AbstractSeq[Nothing] with scala.collection.immutable.StrictOptimizedSeqOps[Nothing,[_]scala.collection.immutable.AbstractSeq[_] with scala.collection.immutable.StrictOptimizedSeqOps[_,[_]scala.collection.immutable.AbstractSeq[_] with scala.collection.immutable.StrictOptimizedSeqOps[_,[_]scala.collection.immutable.AbstractSeq[_],scala.collection.immutable.AbstractSeq[_]],scala.collection.immutable.AbstractSeq[_] with scala.collection.immutable.StrictOptimizedSeqOps[_,[_]scala.collection.immutable.AbstractSeq[_],scala.collection.immutable.AbstractSeq[_]]],scala.collection.immutable.AbstractSeq[Nothing] with scala.collection.immutable.StrictOptimizedSeqOps[Nothing,[_]scala.collection.immutable.AbstractSeq[_] with scala.collection.immutable.StrictOptimizedSeqOps[_,[_]scala.collection.immutable.AbstractSeq[_],scala.collection.immutable.AbstractSeq[_]],scala.collection.immutable.AbstractSeq[Nothing] with scala.collection.immutable.StrictOptimizedSeqOps[Nothing,[_]scala.collection.immutable.AbstractSeq[_],scala.collection.immutable.AbstractSeq[Nothing]]]]] = List(List(), Vector()) scala> List(collection.mutable.Queue(), List()) - ^ - error: type mismatch; - found : scala.collection.mutable.Queue[Nothing] - required: scala.collection.AbstractSeq[Nothing] with scala.collection.StrictOptimizedSeqOps[Nothing,scala.collection.AbstractSeq with scala.collection.StrictOptimizedSeqOps[Any,scala.collection.AbstractSeq with scala.collection.StrictOptimizedSeqOps[Any,scala.collection.AbstractSeq,Serializable with Equals],scala.collection.AbstractSeq[Any] with scala.collection.StrictOptimizedSeqOps[Any,scala.collection.AbstractSeq,Serializable with Equals]],scala.collection.AbstractSeq[Nothing] with scala.collection.StrictOptimizedSeqOps[Nothing,scala.collection.AbstractSeq with scala.collection.StrictOptimizedSeqOps[Any,scala.collection.AbstractSeq,Serializable with Equals],scala.collection.AbstractSeq[Nothing] with scala.collection.StrictOptimizedSeqOps[Nothing,scala.collection.AbstractSeq,scala.collection.AbstractSeq[Nothing]]]] - ^ - error: type mismatch; - found : List[Nothing] - required: scala.collection.AbstractSeq[Nothing] with scala.collection.StrictOptimizedSeqOps[Nothing,scala.collection.AbstractSeq with scala.collection.StrictOptimizedSeqOps[Any,scala.collection.AbstractSeq with scala.collection.StrictOptimizedSeqOps[Any,scala.collection.AbstractSeq,Serializable with Equals],scala.collection.AbstractSeq[Any] with scala.collection.StrictOptimizedSeqOps[Any,scala.collection.AbstractSeq,Serializable with Equals]],scala.collection.AbstractSeq[Nothing] with scala.collection.StrictOptimizedSeqOps[Nothing,scala.collection.AbstractSeq with scala.collection.StrictOptimizedSeqOps[Any,scala.collection.AbstractSeq,Serializable with Equals],scala.collection.AbstractSeq[Nothing] with scala.collection.StrictOptimizedSeqOps[Nothing,scala.collection.AbstractSeq,scala.collection.AbstractSeq[Nothing]]]] +res3: List[scala.collection.AbstractSeq[Nothing] with scala.collection.StrictOptimizedSeqOps[Nothing,[_]scala.collection.AbstractSeq[_] with scala.collection.StrictOptimizedSeqOps[_,[_]scala.collection.AbstractSeq[_] with scala.collection.StrictOptimizedSeqOps[_,[_]scala.collection.AbstractSeq[_],scala.collection.AbstractSeq[_]],scala.collection.AbstractSeq[_] with scala.collection.StrictOptimizedSeqOps[_,[_]scala.collection.AbstractSeq[_],scala.collection.AbstractSeq[_]]],scala.collection.AbstractSeq[Nothing] with scala.collection.StrictOptimizedSeqOps[Nothing,[_]scala.collection.AbstractSeq[_] with scala.collection.StrictOptimizedSeqOps[_,[_]scala.collection.AbstractSeq[_],scala.collection.AbstractSeq[_]],scala.collection.AbstractSeq[Nothing] with scala.collection.StrictOptimizedSeqOps[Nothing,[_]scala.collection.AbstractSeq[_],scala.collection.AbstractSeq[Nothing]]]]] = List(Queue(), List()) scala> :quit diff --git a/test/files/run/invalid-lubs.scala b/test/files/run/invalid-lubs.scala index 397d49921898..b5862d70f729 100644 --- a/test/files/run/invalid-lubs.scala +++ b/test/files/run/invalid-lubs.scala @@ -1,5 +1,5 @@ import scala.tools.partest.ReplTest -// f-bounded types involved in LUBs can sometimes produce an ill-bounded LUB. +// These LUBs are no longer invalid. // ReplTest because some errors shadow others object Test extends ReplTest { def code = From d131c1df4e844bf60462d04b16d9eb8bbd1e3129 Mon Sep 17 00:00:00 2001 From: valydia Date: Sat, 9 Jun 2018 12:44:21 +0100 Subject: [PATCH 125/143] `partitionWith` in `IterableOps` A function that partitions a collection in two, using a split function `f: A => Either[A1, A2]` --- src/library/scala/collection/Iterable.scala | 25 +++++++ .../StrictOptimizedIterableOps.scala | 13 ++++ src/library/scala/collection/View.scala | 67 ++++++++++++++++++- .../scala/collection/BuildFromTest.scala | 8 +-- .../junit/scala/collection/IterableTest.scala | 11 +++ 5 files changed, 119 insertions(+), 5 deletions(-) diff --git a/src/library/scala/collection/Iterable.scala b/src/library/scala/collection/Iterable.scala index de29a812b060..593f9e0db842 100644 --- a/src/library/scala/collection/Iterable.scala +++ b/src/library/scala/collection/Iterable.scala @@ -648,6 +648,31 @@ trait IterableOps[+A, +CC[_], +C] extends Any with IterableOnce[A] with Iterable def collect[B](pf: PartialFunction[A, B]): CC[B] = fromIterable(new View.Collect(this, pf)) + /** A pair of ${coll}s, first, consisting of the values that are produced by `f` applied to this $coll elements contained in [[scala.util.Left]] and, second, + * all the values contained in [[scala.util.Right]]. + * + * Example: + * {{{ + * val xs = $Coll(1, "one", 2, "two", 3, "three") partitionWith { + * case i: Int => Left(i) + * case s: String => Right(s) + * } + * // xs == ($Coll(1, 2, 3), + * // $Coll(one, two, three)) + * }}} + * + * @tparam A1 element type of the first resulting collection + * @tparam A2 element type of the second resulting collection + * @param f split function that map the element of the $coll into an [[scala.util.Either]][A1, A2] + * + * @return a pair of ${coll}s, first, consisting of the values that are produced by `f` applied to this $coll + * elements contained in [[scala.util.Left]] and, second, all the values contained in [[scala.util.Right]]. + */ + def partitionWith[A1, A2](f: A => Either[A1, A2]): (CC[A1], CC[A2]) = { + val mp = new View.PartitionWith(this, f) + (fromIterable(mp.left), fromIterable(mp.right)) + } + /** Returns a new $coll containing the elements from the left hand operand followed by the elements from the * right hand operand. The element type of the $coll is the most specific superclass encompassing * the element types of the two operands. diff --git a/src/library/scala/collection/StrictOptimizedIterableOps.scala b/src/library/scala/collection/StrictOptimizedIterableOps.scala index 5ecd78a76d0b..420bab67f239 100644 --- a/src/library/scala/collection/StrictOptimizedIterableOps.scala +++ b/src/library/scala/collection/StrictOptimizedIterableOps.scala @@ -224,4 +224,17 @@ trait StrictOptimizedIterableOps[+A, +CC[_], +C] b.result() } + // Optimized, push-based version of `partitionWith` + override def partitionWith[A1, A2](f: A => Either[A1, A2]): (CC[A1], CC[A2]) = { + val l = iterableFactory.newBuilder[A1] + val r = iterableFactory.newBuilder[A2] + foreach { x => + f(x) match { + case Left(x1) => l += x1 + case Right(x2) => r += x2 + } + } + (l.result(), r.result()) + } + } diff --git a/src/library/scala/collection/View.scala b/src/library/scala/collection/View.scala index c1fb3744e43f..3a39c8e2a60c 100644 --- a/src/library/scala/collection/View.scala +++ b/src/library/scala/collection/View.scala @@ -160,7 +160,7 @@ object View extends IterableFactory[View] { override def isEmpty: Boolean = underlying.isEmpty } - /** A view that partitions an underlying collection into two views */ + /** A class that partitions an underlying collection into two views */ @SerialVersionUID(3L) class Partition[A](val underlying: SomeIterableOps[A], val p: A => Boolean) extends Serializable { @@ -183,6 +183,71 @@ object View extends IterableFactory[View] { override def isEmpty: Boolean = iterator.isEmpty } + /** A class that splits an underlying collection into two views */ + @SerialVersionUID(3L) + class PartitionWith[A, A1, A2](val underlying: SomeIterableOps[A], val f: A => Either[A1, A2]) extends Serializable { + + /** The view consisting of all elements of the underlying collection + * that map to `Left`. + */ + val left: View[A1] = new LeftPartitionedWith(this, f) + + + /** The view consisting of all elements of the underlying collection + * that map to `Right`. + */ + val right: View[A2] = new RightPartitionedWith(this, f) + + } + + @SerialVersionUID(3L) + class LeftPartitionedWith[A, A1, A2](partitionWith: PartitionWith[A, A1, A2], f: A => Either[A1, A2]) extends AbstractView[A1] { + def iterator = new AbstractIterator[A1] { + private val self = partitionWith.underlying.iterator + private var hd: A1 = _ + private var hdDefined: Boolean = false + def hasNext = hdDefined || { + def findNext(): Boolean = + if (self.hasNext) { + f(self.next()) match { + case Left(a1) => hd = a1; hdDefined = true; true + case Right(_) => findNext() + } + } else false + findNext() + } + def next() = + if (hasNext) { + hdDefined = false + hd + } else Iterator.empty.next() + } + } + + @SerialVersionUID(3L) + class RightPartitionedWith[A, A1, A2](partitionWith: PartitionWith[A, A1, A2], f: A => Either[A1, A2]) extends AbstractView[A2] { + def iterator = new AbstractIterator[A2] { + private val self = partitionWith.underlying.iterator + private var hd: A2 = _ + private var hdDefined: Boolean = false + def hasNext = hdDefined || { + def findNext(): Boolean = + if (self.hasNext) { + f(self.next()) match { + case Left(_) => findNext() + case Right(a2) => hd = a2; hdDefined = true; true + } + } else false + findNext() + } + def next() = + if (hasNext) { + hdDefined = false + hd + } else Iterator.empty.next() + } + } + /** A view that drops leading elements of the underlying collection. */ @SerialVersionUID(3L) class Drop[A](underlying: SomeIterableOps[A], n: Int) extends AbstractView[A] { diff --git a/test/junit/scala/collection/BuildFromTest.scala b/test/junit/scala/collection/BuildFromTest.scala index 1a3bc60f0488..cac3f724b201 100644 --- a/test/junit/scala/collection/BuildFromTest.scala +++ b/test/junit/scala/collection/BuildFromTest.scala @@ -105,7 +105,7 @@ class BuildFromTest { builder.result() } - def mapSplit[A, B, C, ToL, ToR](coll: Iterable[A])(f: A => Either[B, C]) + def partitionWith[A, B, C, ToL, ToR](coll: Iterable[A])(f: A => Either[B, C]) (implicit bfLeft: BuildFrom[coll.type, B, ToL], bfRight: BuildFrom[coll.type, C, ToR]): (ToL, ToR) = { val left = bfLeft.newBuilder(coll) val right = bfRight.newBuilder(coll) @@ -135,14 +135,14 @@ class BuildFromTest { } @Test - def mapSplitTest: Unit = { + def partitionWithTest: Unit = { val xs1 = immutable.List(1, 2, 3) - val (xs2, xs3) = mapSplit(xs1)(x => if (x % 2 == 0) Left(x) else Right(x.toString)) + val (xs2, xs3) = partitionWith(xs1)(x => if (x % 2 == 0) Left(x) else Right(x.toString)) val xs4: immutable.List[Int] = xs2 val xs5: immutable.List[String] = xs3 val xs6 = immutable.TreeMap((1, "1"), (2, "2")) - val (xs7, xs8) = mapSplit(xs6) { case (k, v) => Left[(String, Int), (Int, Boolean)]((v, k)) } + val (xs7, xs8) = partitionWith(xs6) { case (k, v) => Left[(String, Int), (Int, Boolean)]((v, k)) } val xs9: immutable.TreeMap[String, Int] = xs7 val xs10: immutable.TreeMap[Int, Boolean] = xs8 } diff --git a/test/junit/scala/collection/IterableTest.scala b/test/junit/scala/collection/IterableTest.scala index 491c7fa370e6..8e28c8a83bf1 100644 --- a/test/junit/scala/collection/IterableTest.scala +++ b/test/junit/scala/collection/IterableTest.scala @@ -212,6 +212,7 @@ class IterableTest { Assert.assertEquals(baselist.reverse, checklist) } + @Test def unzip(): Unit = { val zipped = Seq((1, 'a'), (2, 'b'), (3, 'c')) val (s1, s2) = zipped.unzip @@ -261,4 +262,14 @@ class IterableTest { Assert.assertEquals("Fu()", foo.toString) } + @Test + def partitionWith: Unit = { + val (left, right) = Seq(1, "1", 2, "2", 3, "3", 4, "4", 5, "5").partitionWith { + case i: Int => Left(i) + case s: String => Right(s) + } + Assert.assertEquals(left, Seq(1, 2, 3, 4 ,5)) + Assert.assertEquals(right, Seq("1", "2", "3", "4" ,"5")) + } + } From 03f7bcfea30e0d7f9e8ad48e859ae73158d1abc0 Mon Sep 17 00:00:00 2001 From: pathikrit Date: Mon, 6 Aug 2018 19:54:35 -0400 Subject: [PATCH 126/143] DRY up some common remove utils from mutable.Queue to ArrayDeque Adds removeFirst(predicate), removeAll(predicate) to ArrayDeque Adds dequeWhile(predicate) to mutable.Queue --- .../scala/collection/mutable/ArrayDeque.scala | 39 +++++++++++++- .../scala/collection/mutable/Queue.scala | 54 +++++++------------ 2 files changed, 57 insertions(+), 36 deletions(-) diff --git a/src/library/scala/collection/mutable/ArrayDeque.scala b/src/library/scala/collection/mutable/ArrayDeque.scala index a6fd14b93b57..d1a920f6e47e 100644 --- a/src/library/scala/collection/mutable/ArrayDeque.scala +++ b/src/library/scala/collection/mutable/ArrayDeque.scala @@ -367,6 +367,43 @@ class ArrayDeque[A] protected ( elems.result() } + /** Returns the first element which satisfies the given predicate after or at some start index + * and removes this element from the collections + * + * @param p the predicate used for choosing the first element + * @param from the start index + * @return the first element of the queue for which p yields true + */ + def removeFirst(p: A => Boolean, from: Int = 0): Option[A] = { + val i = indexWhere(p, from) + if (i < 0) None else Some(remove(i)) + } + + /** Returns all elements in this collection which satisfy the given predicate + * and removes those elements from this collections. + * + * @param p the predicate used for choosing elements + * @return a sequence of all elements in the queue for which + * p yields true. + */ + def removeAll(p: A => Boolean): scala.collection.immutable.Seq[A] = { + val res = scala.collection.immutable.Seq.newBuilder[A] + var i, j = 0 + while (i < size) { + if (p(this(i))) { + res += this(i) + } else { + if (i != j) { + this(j) = this(i) + } + j += 1 + } + i += 1 + } + if (i != j) takeInPlace(j) + res.result() + } + override def reverse: IterableCC[A] = { val n = length val arr = ArrayDeque.alloc(n) @@ -399,7 +436,7 @@ class ArrayDeque[A] protected ( } /** - * clears this buffer and shrinks to @param size + * Clears this buffer and shrinks to @param size * * @param size * @return diff --git a/src/library/scala/collection/mutable/Queue.scala b/src/library/scala/collection/mutable/Queue.scala index b8ac22b8af73..c5fc88729d75 100644 --- a/src/library/scala/collection/mutable/Queue.scala +++ b/src/library/scala/collection/mutable/Queue.scala @@ -74,41 +74,25 @@ class Queue[A] protected (array: Array[AnyRef], start: Int, end: Int) * @return the first element of the queue for which p yields true */ def dequeueFirst(p: A => Boolean): Option[A] = - if (isEmpty) None - else if (p(head)) { - val res = Some(head) - removeHead() - res - } else { - val i = indexWhere(p) - if (i < 0) None - else Some(remove(i)) - } - - /** Returns all elements in the queue which satisfy the - * given predicate, and removes those elements from the queue. - * - * @param p the predicate used for choosing elements - * @return a sequence of all elements in the queue for which - * p yields true. - */ - def dequeueAll(p: A => Boolean): scala.collection.immutable.Seq[A] = { - val res = scala.collection.immutable.Seq.newBuilder[A] - var i, j = 0 - while (i < size) { - if (p(apply(i))) { - res += this(i) - } else { - if (i != j) { - this(j) = this(i) - } - j += 1 - } - i += 1 - } - if (i != j) takeInPlace(j) - res.result() - } + removeFirst(p) + + /** Returns all elements in the queue which satisfy the + * given predicate, and removes those elements from the queue. + * + * @param p the predicate used for choosing elements + * @return a sequence of all elements in the queue for which + * p yields true. + */ + def dequeueAll(p: A => Boolean): scala.collection.immutable.Seq[A] = + removeAll(p) + + /** + * Returns and dequeues all elements from the queue which satisfy the given predicate + * + * @param f the predicate used for choosing elements + * @return The removed elements + */ + def dequeueWhile(f: A => Boolean): scala.collection.Seq[A] = removeHeadWhile(f) /** Returns the first element in the queue, or throws an error if there * is no element contained in the queue. From 1f7bf7735b8ad51a33f85d9f234901e90afddda2 Mon Sep 17 00:00:00 2001 From: xuwei-k <6b656e6a69@gmail.com> Date: Mon, 6 Aug 2018 15:07:52 +0900 Subject: [PATCH 127/143] remove some lower bounds in ArrayOps --- src/library/scala/collection/ArrayOps.scala | 8 +++----- .../scala/tools/nsc/interpreter/shell/Reporter.scala | 2 +- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/src/library/scala/collection/ArrayOps.scala b/src/library/scala/collection/ArrayOps.scala index 9d83ec528b16..76cb27322cfe 100644 --- a/src/library/scala/collection/ArrayOps.scala +++ b/src/library/scala/collection/ArrayOps.scala @@ -492,12 +492,11 @@ final class ArrayOps[A](val xs: Array[A]) extends AnyVal { /** Finds index of first occurrence of some value in this array after or at some start index. * * @param elem the element value to search for. - * @tparam B the type of the element `elem`. * @param from the start index * @return the index `>= from` of the first element of this array that is equal (as determined by `==`) * to `elem`, or `-1`, if none exists. */ - def indexOf[B >: A](elem: B, from: Int = 0): Int = { + def indexOf(elem: A, from: Int = 0): Int = { var i = from while(i < xs.length) { if(elem == xs(i)) return i @@ -526,11 +525,10 @@ final class ArrayOps[A](val xs: Array[A]) extends AnyVal { * * @param elem the element value to search for. * @param end the end index. - * @tparam B the type of the element `elem`. * @return the index `<= end` of the last element of this array that is equal (as determined by `==`) * to `elem`, or `-1`, if none exists. */ - def lastIndexOf[B >: A](elem: B, end: Int = xs.length - 1): Int = { + def lastIndexOf(elem: A, end: Int = xs.length - 1): Int = { var i = min(end, xs.length-1) while(i >= 0) { if(elem == xs(i)) return i @@ -1030,7 +1028,7 @@ final class ArrayOps[A](val xs: Array[A]) extends AnyVal { * @return `true` if this array has an element that is equal (as * determined by `==`) to `elem`, `false` otherwise. */ - def contains[A1 >: A](elem: A1): Boolean = exists (_ == elem) + def contains(elem: A): Boolean = exists (_ == elem) /** Returns a copy of this array with patched values. * Patching at negative indices is the same as patching starting at 0. diff --git a/src/repl-frontend/scala/tools/nsc/interpreter/shell/Reporter.scala b/src/repl-frontend/scala/tools/nsc/interpreter/shell/Reporter.scala index 9d68b0fe1fbc..6d77cee50e0c 100644 --- a/src/repl-frontend/scala/tools/nsc/interpreter/shell/Reporter.scala +++ b/src/repl-frontend/scala/tools/nsc/interpreter/shell/Reporter.scala @@ -150,7 +150,7 @@ class ReplReporterImpl(val config: ShellConfig, val settings: Settings = new Set // TODO: the console could be empty due to external changes (also, :reset? -- see unfortunate example in jvm/interpeter (plusOne)) def printMessage(posIn: Position, msg: String): Unit = { if ((posIn eq null) || (posIn.source eq NoSourceFile)) printMessage(msg) - else if (posIn.source.file.name == "" && posIn.line == 1 && posIn.source.content.indexOf("\n") == -1) { + else if (posIn.source.file.name == "" && posIn.line == 1) { // If there's only one line of input, and it's already printed on the console (as indicated by the position's source file name), // reuse that line in our error output, and suppress the line number (since we know it's `1`) // NOTE: see e.g. test/files/run/repl-colon-type.scala, where the error refers to a line that's not on the screen From 23206a2a277926991db9a488b685ef63efcb2f38 Mon Sep 17 00:00:00 2001 From: taku0 Date: Sat, 7 Apr 2018 14:38:59 +0900 Subject: [PATCH 128/143] Support JEP 293 style long command-line options JEP 293 specifies GNU-like styles for command-line options, which is supported from OpenJDK/Oracle JDK 9. This patch adds synonyms with two hyphens for each options. Option names consist with multiple words are separated by hyphens. --- .../tools/nsc/GenericRunnerSettings.scala | 6 +-- .../scala/tools/nsc/fsc/FscSettings.scala | 14 +++---- .../tools/nsc/settings/ScalaSettings.scala | 12 +++--- .../nsc/settings/StandardScalaSettings.scala | 40 +++++++++---------- 4 files changed, 36 insertions(+), 36 deletions(-) diff --git a/src/compiler/scala/tools/nsc/GenericRunnerSettings.scala b/src/compiler/scala/tools/nsc/GenericRunnerSettings.scala index 5912e5d00225..f9a054dfedaf 100644 --- a/src/compiler/scala/tools/nsc/GenericRunnerSettings.scala +++ b/src/compiler/scala/tools/nsc/GenericRunnerSettings.scala @@ -17,7 +17,7 @@ class GenericRunnerSettings(error: String => Unit) extends Settings(error) { "how", "how to run the specified code", List("object", "script", "jar", "repl", "guess"), - "guess") + "guess") withAbbreviation "--how-to-run" val loadfiles = MultiStringSetting( @@ -41,11 +41,11 @@ class GenericRunnerSettings(error: String => Unit) extends Settings(error) { val save = BooleanSetting( "-save", - "save the compiled script (assumes the code is a script)") withAbbreviation "-savecompiled" + "save the compiled script (assumes the code is a script)") withAbbreviation "-savecompiled" withAbbreviation "--save" val nc = BooleanSetting( "-nc", - "do not use the legacy fsc compilation daemon").withAbbreviation("-nocompdaemon") + "do not use the legacy fsc compilation daemon").withAbbreviation("-nocompdaemon").withAbbreviation("--no-compilation-daemon") .withDeprecationMessage("scripts use cold compilation by default; use -Yscriptrunner for custom behavior") .withPostSetHook { x: BooleanSetting => Yscriptrunner.value = if (x) "default" else "resident" } } diff --git a/src/compiler/scala/tools/nsc/fsc/FscSettings.scala b/src/compiler/scala/tools/nsc/fsc/FscSettings.scala index 4560722ba80b..e5dc33b2b1e8 100644 --- a/src/compiler/scala/tools/nsc/fsc/FscSettings.scala +++ b/src/compiler/scala/tools/nsc/fsc/FscSettings.scala @@ -17,15 +17,15 @@ class FscSettings(error: String => Unit) extends Settings(error) { disable(resident) } - val currentDir = StringSetting ("-current-dir", "path", "Base directory for resolving relative paths", "").internalOnly() - val reset = BooleanSetting("-reset", "Reset compile server caches") - val shutdown = BooleanSetting("-shutdown", "Shutdown compile server") - val server = StringSetting ("-server", "hostname:portnumber", "Specify compile server socket", "") + val currentDir = StringSetting ("-current-dir", "path", "Base directory for resolving relative paths", "").internalOnly() withAbbreviation "--current-directory" + val reset = BooleanSetting("-reset", "Reset compile server caches") withAbbreviation "--reset" + val shutdown = BooleanSetting("-shutdown", "Shutdown compile server") withAbbreviation "--shutdown" + val server = StringSetting ("-server", "hostname:portnumber", "Specify compile server socket", "") withAbbreviation "--server" val port = IntSetting ("-port", "Search and start compile server in given port only", - 0, Some((0, Int.MaxValue)), (_: String) => None) - val preferIPv4 = BooleanSetting("-ipv4", "Use IPv4 rather than IPv6 for the server socket") + 0, Some((0, Int.MaxValue)), (_: String) => None) withAbbreviation "--port" + val preferIPv4 = BooleanSetting("-ipv4", "Use IPv4 rather than IPv6 for the server socket") withAbbreviation "--ipv4" val idleMins = IntSetting ("-max-idle", "Set idle timeout in minutes for fsc (use 0 for no timeout)", - 30, Some((0, Int.MaxValue)), (_: String) => None) + 30, Some((0, Int.MaxValue)), (_: String) => None) withAbbreviation "--max-idle" // For improved help output, separating fsc options from the others. def fscSpecific = Set[Settings#Setting]( diff --git a/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala b/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala index 5a4b5984e5ee..13e47547a239 100644 --- a/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala +++ b/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala @@ -44,17 +44,17 @@ trait ScalaSettings extends AbsScalaSettings val jvmargs = PrefixSetting("-J", "-J", "Pass directly to the runtime system.") val defines = PrefixSetting("-Dproperty=value", "-D", "Pass -Dproperty=value directly to the runtime system.") - /*val toolcp =*/ PathSetting("-toolcp", "Add to the runner classpath.", "") - val nobootcp = BooleanSetting("-nobootcp", "Do not use the boot classpath for the scala jars.") + /*val toolcp =*/ PathSetting("-toolcp", "Add to the runner classpath.", "") withAbbreviation "--tool-class-path" + val nobootcp = BooleanSetting("-nobootcp", "Do not use the boot classpath for the scala jars.") withAbbreviation "--no-boot-class-path" /** * Standard settings */ // argfiles is only for the help message /*val argfiles = */ BooleanSetting ("@", "A text file containing compiler arguments (options and source files)") - val classpath = PathSetting ("-classpath", "Specify where to find user class files.", defaultClasspath) withAbbreviation "-cp" + val classpath = PathSetting ("-classpath", "Specify where to find user class files.", defaultClasspath) withAbbreviation "-cp" withAbbreviation "--class-path" val d = OutputSetting (outputDirs, ".") - val nospecialization = BooleanSetting ("-no-specialization", "Ignore @specialize annotations.") + val nospecialization = BooleanSetting ("-no-specialization", "Ignore @specialize annotations.") withAbbreviation "--no-specialization" // Would be nice to build this dynamically from scala.languageFeature. // The two requirements: delay error checking until you have symbols, and let compiler command build option-specific help. @@ -74,7 +74,7 @@ trait ScalaSettings extends AbsScalaSettings helpArg = "feature", descr = description, domain = languageFeatures - ) + ) withAbbreviation "--language" } val release = StringSetting("-release", "release", "Compile for a specific version of the Java platform. Supported targets: 6, 7, 8, 9", "").withPostSetHook { (value: StringSetting) => if (value.value != "" && !scala.util.Properties.isJavaAtLeast("9")) { @@ -83,7 +83,7 @@ trait ScalaSettings extends AbsScalaSettings // TODO validate numeric value // TODO validate release <= java.specification.version } - } + } withAbbreviation "--release" def releaseValue: Option[String] = Option(release.value).filter(_ != "") /* diff --git a/src/compiler/scala/tools/nsc/settings/StandardScalaSettings.scala b/src/compiler/scala/tools/nsc/settings/StandardScalaSettings.scala index f197a4930da5..5c67406cdebd 100644 --- a/src/compiler/scala/tools/nsc/settings/StandardScalaSettings.scala +++ b/src/compiler/scala/tools/nsc/settings/StandardScalaSettings.scala @@ -18,32 +18,32 @@ trait StandardScalaSettings { /** Path related settings. */ - val bootclasspath = PathSetting ("-bootclasspath", "Override location of bootstrap class files.", Defaults.scalaBootClassPath) + val bootclasspath = PathSetting ("-bootclasspath", "Override location of bootstrap class files.", Defaults.scalaBootClassPath) withAbbreviation "--boot-class-path" val classpath: PathSetting // is mutated directly in various places (thus inspiring this very effort) val d: OutputSetting // depends on mutable OutputDirs class - val extdirs = PathSetting ("-extdirs", "Override location of installed extensions.", Defaults.scalaExtDirs) - val javabootclasspath = PathSetting ("-javabootclasspath", "Override java boot classpath.", Defaults.javaBootClassPath) - val javaextdirs = PathSetting ("-javaextdirs", "Override java extdirs classpath.", Defaults.javaExtDirs) - val sourcepath = PathSetting ("-sourcepath", "Specify location(s) of source files.", "") // Defaults.scalaSourcePath + val extdirs = PathSetting ("-extdirs", "Override location of installed extensions.", Defaults.scalaExtDirs) withAbbreviation "--extension-directories" + val javabootclasspath = PathSetting ("-javabootclasspath", "Override java boot classpath.", Defaults.javaBootClassPath) withAbbreviation "--java-boot-class-path" + val javaextdirs = PathSetting ("-javaextdirs", "Override java extdirs classpath.", Defaults.javaExtDirs) withAbbreviation "--java-extension-directories" + val sourcepath = PathSetting ("-sourcepath", "Specify location(s) of source files.", "") withAbbreviation "--source-path" // Defaults.scalaSourcePath /** Other settings. */ - val dependencyfile = StringSetting ("-dependencyfile", "file", "Set dependency tracking file.", ".scala_dependencies") - val deprecation = BooleanSetting ("-deprecation", "Emit warning and location for usages of deprecated APIs.") - val encoding = StringSetting ("-encoding", "encoding", "Specify character encoding used by source files.", Properties.sourceEncoding) - val explaintypes = BooleanSetting ("-explaintypes", "Explain type errors in more detail.") - val feature = BooleanSetting ("-feature", "Emit warning and location for usages of features that should be imported explicitly.") + val dependencyfile = StringSetting ("-dependencyfile", "file", "Set dependency tracking file.", ".scala_dependencies") withAbbreviation "--dependency-file" + val deprecation = BooleanSetting ("-deprecation", "Emit warning and location for usages of deprecated APIs.") withAbbreviation "--deprecation" + val encoding = StringSetting ("-encoding", "encoding", "Specify character encoding used by source files.", Properties.sourceEncoding) withAbbreviation "--encoding" + val explaintypes = BooleanSetting ("-explaintypes", "Explain type errors in more detail.") withAbbreviation "--explain-types" + val feature = BooleanSetting ("-feature", "Emit warning and location for usages of features that should be imported explicitly.") withAbbreviation "--feature" val g = ChoiceSetting ("-g", "level", "Set level of generated debugging info.", List("none", "source", "line", "vars", "notailcalls"), "vars") - val help = BooleanSetting ("-help", "Print a synopsis of standard options") - val nowarn = BooleanSetting ("-nowarn", "Generate no warnings.") + val help = BooleanSetting ("-help", "Print a synopsis of standard options") withAbbreviation "--help" + val nowarn = BooleanSetting ("-nowarn", "Generate no warnings.") withAbbreviation "--no-warnings" val optimise: BooleanSetting // depends on post hook which mutates other settings - val print = BooleanSetting ("-print", "Print program with Scala-specific features removed.") + val print = BooleanSetting ("-print", "Print program with Scala-specific features removed.") withAbbreviation "--print" val target = ChoiceSettingForcedDefault ("-target", "target", "Target platform for object files. All JVM 1.5 - 1.7 targets are deprecated.", - List("jvm-1.5", "jvm-1.6", "jvm-1.7", "jvm-1.8"), "jvm-1.8") - val unchecked = BooleanSetting ("-unchecked", "Enable additional warnings where generated code depends on assumptions.") - val uniqid = BooleanSetting ("-uniqid", "Uniquely tag all identifiers in debugging output.") - val usejavacp = BooleanSetting ("-usejavacp", "Utilize the java.class.path in classpath resolution.") - val usemanifestcp = BooleanSetting ("-usemanifestcp", "Utilize the manifest in classpath resolution.") - val verbose = BooleanSetting ("-verbose", "Output messages about what the compiler is doing.") - val version = BooleanSetting ("-version", "Print product version and exit.") + List("jvm-1.5", "jvm-1.6", "jvm-1.7", "jvm-1.8"), "jvm-1.8") withAbbreviation "--target" + val unchecked = BooleanSetting ("-unchecked", "Enable additional warnings where generated code depends on assumptions.") withAbbreviation "--unchecked" + val uniqid = BooleanSetting ("-uniqid", "Uniquely tag all identifiers in debugging output.") withAbbreviation "--unique-id" + val usejavacp = BooleanSetting ("-usejavacp", "Utilize the java.class.path in classpath resolution.") withAbbreviation "--use-java-class-path" + val usemanifestcp = BooleanSetting ("-usemanifestcp", "Utilize the manifest in classpath resolution.") withAbbreviation "--use-manifest-class-path" + val verbose = BooleanSetting ("-verbose", "Output messages about what the compiler is doing.") withAbbreviation "--verbose" + val version = BooleanSetting ("-version", "Print product version and exit.") withAbbreviation "--version" } From a9812ac2bc13b0becf2df7106b59e36b424119ad Mon Sep 17 00:00:00 2001 From: taku0 Date: Thu, 12 Apr 2018 13:39:17 +0900 Subject: [PATCH 129/143] Support JEP 293 style long command-line options for scaladoc --- src/scaladoc/scala/tools/nsc/doc/Settings.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/scaladoc/scala/tools/nsc/doc/Settings.scala b/src/scaladoc/scala/tools/nsc/doc/Settings.scala index d3585801b446..19f07b55b27b 100644 --- a/src/scaladoc/scala/tools/nsc/doc/Settings.scala +++ b/src/scaladoc/scala/tools/nsc/doc/Settings.scala @@ -223,7 +223,7 @@ class Settings(error: String => Unit, val printMsg: String => Unit = println(_)) docDiagramsMaxNormalClasses, docDiagramsMaxImplicitClasses, docNoPrefixes, docNoLinkWarnings, docRawOutput, docSkipPackages, docExpandAllTypes, docGroups, docNoJavaComments - ) + ).map(s => s.withAbbreviation("-" + s.name)) val isScaladocSpecific: String => Boolean = scaladocSpecific map (_.name) override def isScaladoc = true From 005afb8edaa58e13dba25935e60ce4762a67456a Mon Sep 17 00:00:00 2001 From: Lukas Rytz Date: Tue, 7 Aug 2018 15:38:28 +0200 Subject: [PATCH 130/143] Disable tests for completions in member annotations --- test/junit/scala/tools/nsc/interpreter/CompletionTest.scala | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/test/junit/scala/tools/nsc/interpreter/CompletionTest.scala b/test/junit/scala/tools/nsc/interpreter/CompletionTest.scala index 7bbf06f20304..ef2b892b314d 100644 --- a/test/junit/scala/tools/nsc/interpreter/CompletionTest.scala +++ b/test/junit/scala/tools/nsc/interpreter/CompletionTest.scala @@ -79,8 +79,9 @@ class CompletionTest { val completer = setup() checkExact(completer, "def foo[@specialize", " A]")("specialized") checkExact(completer, "def foo[@specialize")("specialized") - checkExact(completer, """@deprecatedN""", """ class Foo""")("deprecatedName") - checkExact(completer, """@deprecateN""")("deprecatedName") +// TODO: re-enable once scala/bug#11060 is fixed +// checkExact(completer, """@deprecatedN""", """ class Foo""")("deprecatedName") +// checkExact(completer, """@deprecateN""")("deprecatedName") checkExact(completer, """{@deprecateN""")("deprecatedName") } From 0e9417f50e9c7ea4b91e53070188f4634333cf0d Mon Sep 17 00:00:00 2001 From: Stefan Zeiger Date: Mon, 4 Jun 2018 16:48:09 +0200 Subject: [PATCH 131/143] Improve `Growable.+=` and related methods - Deprecate the varargs version of `Growable.+=`. It is confusing when used with tuples (e.g. for `Map` types) and Scala 3.0 will probably drop support for infix operators with multiple parameters. - Add back the specialized two-argument `+=` to `AnyRefMap` which was present in 2.12. - There is no need to deprecate the two-argument versions now. If a future Scala version disallows calling them with operator syntax, these calls should automatically fall back to the tupled versions. - Make the tupled `addOne` methods in `AnyRefMap` and `LongMap` inlinable. When inlining is enabled the optimizer can elide the tupling. Upcoming inliner improvements should also enable this when `addOne` is called via the also inlinable `+=` alias. --- src/library/scala/collection/mutable/AnyRefMap.scala | 7 +++++-- src/library/scala/collection/mutable/Growable.scala | 1 + src/library/scala/collection/mutable/LongMap.scala | 5 ++++- test/files/run/collections.check | 1 + 4 files changed, 11 insertions(+), 3 deletions(-) diff --git a/src/library/scala/collection/mutable/AnyRefMap.scala b/src/library/scala/collection/mutable/AnyRefMap.scala index 736afad073fd..b5d7484eb973 100644 --- a/src/library/scala/collection/mutable/AnyRefMap.scala +++ b/src/library/scala/collection/mutable/AnyRefMap.scala @@ -285,9 +285,12 @@ class AnyRefMap[K <: AnyRef, V] private[collection] (defaultEntry: K => V, initi } /** Adds a new key/value pair to this map and returns the map. */ - def addOne(key: K, value: V): this.type = { update(key, value); this } + def +=(key: K, value: V): this.type = { update(key, value); this } - def addOne(kv: (K, V)): this.type = { update(kv._1, kv._2); this } + /** Adds a new key/value pair to this map and returns the map. */ + @inline final def addOne(key: K, value: V): this.type = { update(key, value); this } + + @inline override final def addOne(kv: (K, V)): this.type = { update(kv._1, kv._2); this } def subtractOne(key: K): this.type = { val i = seekEntry(hashOf(key), key) diff --git a/src/library/scala/collection/mutable/Growable.scala b/src/library/scala/collection/mutable/Growable.scala index aabbee8d787b..3b764f582c95 100644 --- a/src/library/scala/collection/mutable/Growable.scala +++ b/src/library/scala/collection/mutable/Growable.scala @@ -36,6 +36,7 @@ trait Growable[-A] extends Clearable { * @param elems the remaining elements to $add. * @return the $coll itself */ + @deprecated("Use `++=` (addAll) instead of varargs `+=`", "2.13.0") @`inline` final def += (elem1: A, elem2: A, elems: A*): this.type = this += elem1 += elem2 ++= (elems: IterableOnce[A]) /** ${Add}s all elements produced by an IterableOnce to this $coll. diff --git a/src/library/scala/collection/mutable/LongMap.scala b/src/library/scala/collection/mutable/LongMap.scala index 2d01da65bceb..e3345b00af2e 100644 --- a/src/library/scala/collection/mutable/LongMap.scala +++ b/src/library/scala/collection/mutable/LongMap.scala @@ -342,7 +342,10 @@ final class LongMap[V] private[collection] (defaultEntry: Long => V, initialBuff /** Adds a new key/value pair to this map and returns the map. */ def +=(key: Long, value: V): this.type = { update(key, value); this } - override def addOne(kv: (Long, V)): this.type = { update(kv._1, kv._2); this } + /** Adds a new key/value pair to this map and returns the map. */ + @inline final def addOne(key: Long, value: V): this.type = { update(key, value); this } + + @inline override final def addOne(kv: (Long, V)): this.type = { update(kv._1, kv._2); this } def subtractOne(key: Long): this.type = { if (key == -key) { diff --git a/test/files/run/collections.check b/test/files/run/collections.check index c24150b24dc5..08a941824720 100644 --- a/test/files/run/collections.check +++ b/test/files/run/collections.check @@ -1,3 +1,4 @@ +warning: there were two deprecation warnings (since 2.13.0); re-run with -deprecation for details ***** mutable.HashSet: test1: 14005 test2: 25005003, iters = 5000 From 569b00c1a92d5df225067fe66483bc07bcbbb974 Mon Sep 17 00:00:00 2001 From: Lukas Rytz Date: Tue, 7 Aug 2018 16:34:43 +0200 Subject: [PATCH 132/143] Work around a local type inference limitation (fixes the build) This is probably an instance of scala/bug#3528 --- src/library/scala/collection/immutable/SeqMap.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/library/scala/collection/immutable/SeqMap.scala b/src/library/scala/collection/immutable/SeqMap.scala index b0432baa7ca1..9e3962a341a0 100644 --- a/src/library/scala/collection/immutable/SeqMap.scala +++ b/src/library/scala/collection/immutable/SeqMap.scala @@ -171,7 +171,7 @@ object SeqMap extends MapFactory[SeqMap] { else { // Directly create the elements for performance reasons val fields = Vector(key1, key2, key3, key4, key) - val underlying = if (useBaseline) + val underlying: Map[K, (Int, V1)] = if (useBaseline) HashMap( (key1, (0, value1)), (key2, (1, value2)), From efc48213073ce5e68a7fd7dc9820610eccdeb9f7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=93lafur=20P=C3=A1ll=20Geirsson?= Date: Tue, 17 Jul 2018 13:30:20 +0200 Subject: [PATCH 133/143] Revive productElementName to extract case class field names This commit adds two methods to the `scala.Product` trait: ```scala trait Product { /** Returns the field name of element at index n */ def productElementName(n: Int): String /** Returns field names of this product. Must have same length as productIterator */ def productElementNames: Iterator[String] } ``` Both methods have a default implementation which returns the empty string for all field names. This commit then changes the code-generation for case classes to synthesize a `productElementName` method with actual class field names. The benefit of this change is that it becomes possible to pretty-print case classes with field names, for example ```scala case class User(name: String, age: Int) def toPrettyString(p: Product): String = p.productElementNames.zip(p.productIterator) .map { case (name, value) => s"$name=$value" } .mkString(p.productPrefix + "(", ", ", ")") toPrettyString(User("Susan", 42)) // res0: String = User(name=Susan, age=42) ``` The downside of this change is that it produces more bytecode for each case-class definition. Running `:javacp -c` for a case class with three fields yields the following results ```scala > case class A(a: Int, b: Int, c: Int) > :javap -c A public java.lang.String productElementName(int); Code: 0: iload_1 1: istore_2 2: iload_2 3: tableswitch { // 0 to 2 0: 28 1: 33 2: 38 default: 43 } 28: ldc 78 // String a 30: goto 58 33: ldc 79 // String b 35: goto 58 38: ldc 80 // String c 40: goto 58 43: new 67 // class java/lang/IndexOutOfBoundsException 46: dup 47: iload_1 48: invokestatic 65 // Method scala/runtime/BoxesRunTime.boxToInteger:(I)Ljava/lang/Integer; 51: invokevirtual 70 // Method java/lang/Object.toString:()Ljava/lang/String; 54: invokespecial 73 // Method java/lang/IndexOutOfBoundsException."":(Ljava/lang/String;)V 57: athrow 58: areturn ``` Thanks to Adriaan's help, the estimated cost per `productElementName` appears to be fixed 56 bytes and then 10 bytes for each field with the following breakdown: * 3 bytes for the [string info](https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-4.html#jvms-4.4.3) (the actual characters are already in the constant pool) * 4 bytes for the tableswitch entry * 2 bytes for the ldc to load the string * 1 byte for areturn In my opinion, the bytecode cost is acceptably low thanks to the fact that field name literals are already available in the constant pool. --- .../nsc/typechecker/SyntheticMethods.scala | 22 +++--- src/library/scala/Product.scala | 20 +++++ .../scala/reflect/internal/Definitions.scala | 1 + .../scala/reflect/internal/StdNames.scala | 1 + test/files/run/idempotency-case-classes.check | 5 ++ test/files/run/macroPlugins-namerHooks.check | 2 + test/files/run/productElementName.check | 14 ++++ test/files/run/productElementName.scala | 77 +++++++++++++++++++ test/files/scalap/caseClass.check | 1 + test/files/scalap/caseObject.check | 1 + .../scala/SerializationStabilityTest.scala | 42 +++++----- test/scaladoc/run/implicits-chaining.scala | 8 +- 12 files changed, 158 insertions(+), 36 deletions(-) create mode 100644 test/files/run/productElementName.check create mode 100644 test/files/run/productElementName.scala diff --git a/src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala b/src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala index 05caee1973fb..b30c7e38e3d9 100644 --- a/src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala +++ b/src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala @@ -38,7 +38,7 @@ trait SyntheticMethods extends ast.TreeDSL { import definitions._ import CODE._ - private lazy val productSymbols = List(Product_productPrefix, Product_productArity, Product_productElement, Product_iterator, Product_canEqual) + private lazy val productSymbols = List(Product_productPrefix, Product_productArity, Product_productElement, Product_productElementName, Product_iterator, Product_canEqual) private lazy val valueSymbols = List(Any_hashCode, Any_equals) private lazy val caseSymbols = List(Object_hashCode, Object_toString) ::: productSymbols private lazy val caseValueSymbols = Any_toString :: valueSymbols ::: productSymbols @@ -117,11 +117,13 @@ trait SyntheticMethods extends ast.TreeDSL { ) } - /* Common code for productElement and (currently disabled) productElementName */ def perElementMethod(name: Name, returnType: Type)(caseFn: Symbol => Tree): Tree = createSwitchMethod(name, accessors.indices, returnType)(idx => caseFn(accessors(idx))) - // def productElementNameMethod = perElementMethod(nme.productElementName, StringTpe)(x => LIT(x.name.toString)) + def productElementNameMethod = { + val constrParamAccessors = clazz.constrParamAccessors + createSwitchMethod(nme.productElementName, constrParamAccessors.indices, StringTpe)(idx => LIT(constrParamAccessors(idx).name.dropLocal.decode)) + } var syntheticCanEqual = false @@ -248,14 +250,12 @@ trait SyntheticMethods extends ast.TreeDSL { // methods for both classes and objects def productMethods = { List( - Product_productPrefix -> (() => constantNullary(nme.productPrefix, clazz.name.decode)), - Product_productArity -> (() => constantNullary(nme.productArity, arity)), - Product_productElement -> (() => perElementMethod(nme.productElement, AnyTpe)(mkThisSelect)), - Product_iterator -> (() => productIteratorMethod), - Product_canEqual -> (() => canEqualMethod) - // This is disabled pending a reimplementation which doesn't add any - // weight to case classes (i.e. inspects the bytecode.) - // Product_productElementName -> (() => productElementNameMethod(accessors)), + Product_productPrefix -> (() => constantNullary(nme.productPrefix, clazz.name.decode)), + Product_productArity -> (() => constantNullary(nme.productArity, arity)), + Product_productElement -> (() => perElementMethod(nme.productElement, AnyTpe)(mkThisSelect)), + Product_productElementName -> (() => productElementNameMethod), + Product_iterator -> (() => productIteratorMethod), + Product_canEqual -> (() => canEqualMethod) ) } diff --git a/src/library/scala/Product.scala b/src/library/scala/Product.scala index 5877e2128990..83b63628d6af 100644 --- a/src/library/scala/Product.scala +++ b/src/library/scala/Product.scala @@ -48,4 +48,24 @@ trait Product extends Any with Equals { * @return in the default implementation, the empty string */ def productPrefix = "" + + /** The name of the n^th^ element of this product, 0-based. + * In the default implementation, an empty string. + * + * @param n the index of the element name to return + * @throws IndexOutOfBoundsException + * @return the name of the specified element + */ + def productElementName(n: Int): String = + if (n >= 0 && n < productArity) "" + else throw new IndexOutOfBoundsException(n.toString) + + /** An iterator over the names of all the elements of this product. + */ + def productElementNames: Iterator[String] = new scala.collection.AbstractIterator[String] { + private[this] var c: Int = 0 + private[this] val cmax = productArity + def hasNext = c < cmax + def next() = { val result = productElementName(c); c += 1; result } + } } diff --git a/src/reflect/scala/reflect/internal/Definitions.scala b/src/reflect/scala/reflect/internal/Definitions.scala index 88ab28f4d151..0ed84504a7b1 100644 --- a/src/reflect/scala/reflect/internal/Definitions.scala +++ b/src/reflect/scala/reflect/internal/Definitions.scala @@ -749,6 +749,7 @@ trait Definitions extends api.StandardDefinitions { lazy val ProductRootClass: ClassSymbol = requiredClass[scala.Product] def Product_productArity = getMemberMethod(ProductRootClass, nme.productArity) def Product_productElement = getMemberMethod(ProductRootClass, nme.productElement) + def Product_productElementName = getMemberMethod(ProductRootClass, nme.productElementName) def Product_iterator = getMemberMethod(ProductRootClass, nme.productIterator) def Product_productPrefix = getMemberMethod(ProductRootClass, nme.productPrefix) def Product_canEqual = getMemberMethod(ProductRootClass, nme.canEqual_) diff --git a/src/reflect/scala/reflect/internal/StdNames.scala b/src/reflect/scala/reflect/internal/StdNames.scala index ef2c2f89d233..b6c5bcc6a611 100644 --- a/src/reflect/scala/reflect/internal/StdNames.scala +++ b/src/reflect/scala/reflect/internal/StdNames.scala @@ -771,6 +771,7 @@ trait StdNames { val prefix : NameType = "prefix" val productArity: NameType = "productArity" val productElement: NameType = "productElement" + val productElementName: NameType = "productElementName" val productIterator: NameType = "productIterator" val productPrefix: NameType = "productPrefix" val raw_ : NameType = "raw" diff --git a/test/files/run/idempotency-case-classes.check b/test/files/run/idempotency-case-classes.check index 38c2fb932625..b79a2a9927de 100644 --- a/test/files/run/idempotency-case-classes.check +++ b/test/files/run/idempotency-case-classes.check @@ -20,6 +20,11 @@ C(2,3) case 1 => C.this.y case _ => throw new IndexOutOfBoundsException(x$1.toString()) }; + override def productElementName(x$1: Int): String = x$1 match { + case 0 => "x" + case 1 => "y" + case _ => throw new IndexOutOfBoundsException(x$1.toString()) + }; override def productIterator: Iterator[Any] = scala.runtime.ScalaRunTime.typedProductIterator[Any](C.this); def canEqual(x$1: Any): Boolean = x$1.$isInstanceOf[C](); override def hashCode(): Int = { diff --git a/test/files/run/macroPlugins-namerHooks.check b/test/files/run/macroPlugins-namerHooks.check index 4409f196f0bf..63cda19ff6b8 100644 --- a/test/files/run/macroPlugins-namerHooks.check +++ b/test/files/run/macroPlugins-namerHooks.check @@ -37,6 +37,8 @@ enterSym(super.()) enterStat(super.()) enterSym(case val x1: Int = x$1) enterStat(case val x1: Int = x$1) +enterSym(case val x1: Int = x$1) +enterStat(case val x1: Int = x$1) enterSym(case val x1: Any = x$1) enterSym(case5(){ if (x1.isInstanceOf[C]) matchEnd4(true) else case6() }) enterSym(case6(){ matchEnd4(false) }) diff --git a/test/files/run/productElementName.check b/test/files/run/productElementName.check new file mode 100644 index 000000000000..a7499b7c1e5d --- /dev/null +++ b/test/files/run/productElementName.check @@ -0,0 +1,14 @@ +User(name=Susan, age=42) +ユーザ(名前=Susan, 年齢=42) +U$er(na$me=Susan, a$ge=42) +type(for=Susan, if=42) +contains spaces(first param=Susan, second param=42) +Symbols(::=Susan, ||=42) +MultipleParamLists(a=Susan, b=42) +AuxiliaryConstructor(a=Susan, b=42) +OverloadedApply(a=Susan, b=123) +DefinesProductElementName(foo=Susan, foo=42) +InheritsProductElementName(a=Susan, b=42) +InheritsProductElementName_Override(overriden=Susan, overriden=42) +InheritsProductElementName_Override_SelfType(a=Susan, b=42) +PrivateMembers(a=10, b=20, c=30, d=40, e=50, f=60) diff --git a/test/files/run/productElementName.scala b/test/files/run/productElementName.scala new file mode 100644 index 000000000000..05d8ef09ee29 --- /dev/null +++ b/test/files/run/productElementName.scala @@ -0,0 +1,77 @@ + +case class User(name: String, age: Int) + +case class ユーザ(名前: String, 年齢: Int) + +case class U$er(na$me: String, a$ge: Int) + +case class `type`(`for`: String, `if`: Int) + +case class `contains spaces`(`first param`: String, `second param`: Int) + +case class Symbols(:: : String, || : Int) + +case class MultipleParamLists(a: String, b: Int)(c: Boolean) + +case class AuxiliaryConstructor(a: String, b: Int) { + def this(x: String) { + this(x, 123) + } +} + +case class OverloadedApply(a: String, b: Int) +object OverloadedApply { + def apply(x: String): OverloadedApply = + new OverloadedApply(x, 123) +} + +case class DefinesProductElementName(a: String, b: Int) { + override def productElementName(n: Int): String = "foo" +} + +trait A { + def productElementName(n: Int): String = "overriden" +} +case class InheritsProductElementName(a: String, b: Int) extends A + +trait B extends Product { + override def productElementName(n: Int): String = "overriden" +} +case class InheritsProductElementName_Override(a: String, b: Int) extends B + +trait C { self: Product => + override def productElementName(n: Int): String = "overriden" +} +case class InheritsProductElementName_Override_SelfType(a: String, b: Int) extends C + +case class PrivateMembers(a: Int, private val b: Int, c: Int, private val d: Int, e: Int, private val f: Int) + +object Test extends App { + def pretty(p: Product): String = + p.productElementNames.zip(p.productIterator) + .map { case (name, value) => s"$name=$value" } + .mkString(p.productPrefix + "(", ", ", ")") + + println(pretty(User("Susan", 42))) + println(pretty(ユーザ("Susan", 42))) + println(pretty(U$er("Susan", 42))) + println(pretty(`type`("Susan", 42))) + println(pretty(`contains spaces`("Susan", 42))) + println(pretty(Symbols("Susan", 42))) + println(pretty(MultipleParamLists("Susan", 42)(true))) + println(pretty(AuxiliaryConstructor("Susan", 42))) + println(pretty(OverloadedApply("Susan"))) + println(pretty(DefinesProductElementName("Susan", 42))) + + // uses the synthetic, not the one defined in the trait + println(pretty(InheritsProductElementName("Susan", 42))) + + // uses the override defined in the trait + println(pretty(InheritsProductElementName_Override("Susan", 42))) + + // uses the synthetic, not the one defined in the trait + println(pretty(InheritsProductElementName_Override_SelfType("Susan", 42))) + + println(pretty(PrivateMembers(10, 20, 30, 40, 50, 60))) +} + diff --git a/test/files/scalap/caseClass.check b/test/files/scalap/caseClass.check index 51ad90d9b2f9..69b955df71cc 100644 --- a/test/files/scalap/caseClass.check +++ b/test/files/scalap/caseClass.check @@ -6,6 +6,7 @@ case class CaseClass[A <: scala.Seq[scala.Int]](i: A, s: scala.Predef.String) ex override def productPrefix: java.lang.String = { /* compiled code */ } def productArity: scala.Int = { /* compiled code */ } def productElement(x$1: scala.Int): scala.Any = { /* compiled code */ } + override def productElementName(x$1: scala.Int): java.lang.String = { /* compiled code */ } override def productIterator: scala.collection.Iterator[scala.Any] = { /* compiled code */ } def canEqual(x$1: scala.Any): scala.Boolean = { /* compiled code */ } override def hashCode(): scala.Int = { /* compiled code */ } diff --git a/test/files/scalap/caseObject.check b/test/files/scalap/caseObject.check index a342e5ff1afa..6475419cf61b 100644 --- a/test/files/scalap/caseObject.check +++ b/test/files/scalap/caseObject.check @@ -3,6 +3,7 @@ case object CaseObject extends scala.AnyRef with scala.Product with scala.Serial override def productPrefix: java.lang.String = { /* compiled code */ } def productArity: scala.Int = { /* compiled code */ } def productElement(x$1: scala.Int): scala.Any = { /* compiled code */ } + override def productElementName(x$1: scala.Int): java.lang.String = { /* compiled code */ } override def productIterator: scala.collection.Iterator[scala.Any] = { /* compiled code */ } def canEqual(x$1: scala.Any): scala.Boolean = { /* compiled code */ } override def hashCode(): scala.Int = { /* compiled code */ } diff --git a/test/junit/scala/SerializationStabilityTest.scala b/test/junit/scala/SerializationStabilityTest.scala index f431ed906edf..46cf59c508a6 100644 --- a/test/junit/scala/SerializationStabilityTest.scala +++ b/test/junit/scala/SerializationStabilityTest.scala @@ -86,7 +86,7 @@ object SerializationStability { } } - // Generated on 20180801-13:15:01 with Scala version 2.13.0-20180726-010358-627e8cf) + // Generated on 20180807-10:08:10 with Scala version 2.13.0-20180807-090342-b6b6a36) def main(args: Array[String]): Unit = { overwrite.foreach(updateComment) def g = Thread.currentThread.getStackTrace @@ -132,20 +132,20 @@ object SerializationStability { check(g)(new collection.convert.Wrappers.MutableSetWrapper(mutable.Set()))("rO0ABXNyADNzY2FsYS5jb2xsZWN0aW9uLmNvbnZlcnQuV3JhcHBlcnMkTXV0YWJsZVNldFdyYXBwZXIAAAAAAAAAAwIAAUwACnVuZGVybHlpbmd0AB5Mc2NhbGEvY29sbGVjdGlvbi9tdXRhYmxlL1NldDt4cgAsc2NhbGEuY29sbGVjdGlvbi5jb252ZXJ0LldyYXBwZXJzJFNldFdyYXBwZXIAAAAAAAAAAwIAAkwABiRvdXRlcnQAI0xzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnM7TAA4c2NhbGEkY29sbGVjdGlvbiRjb252ZXJ0JFdyYXBwZXJzJFNldFdyYXBwZXIkJHVuZGVybHlpbmd0ABZMc2NhbGEvY29sbGVjdGlvbi9TZXQ7eHBzcgAic2NhbGEuY29sbGVjdGlvbi5jb252ZXJ0LldyYXBwZXJzJAAAAAAAAAADAgARTAAYRGljdGlvbmFyeVdyYXBwZXIkbW9kdWxldAA2THNjYWxhL2NvbGxlY3Rpb24vY29udmVydC9XcmFwcGVycyREaWN0aW9uYXJ5V3JhcHBlciQ7TAAWSXRlcmFibGVXcmFwcGVyJG1vZHVsZXQANExzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkSXRlcmFibGVXcmFwcGVyJDtMABZJdGVyYXRvcldyYXBwZXIkbW9kdWxldAA0THNjYWxhL2NvbGxlY3Rpb24vY29udmVydC9XcmFwcGVycyRJdGVyYXRvcldyYXBwZXIkO0wAGUpDb2xsZWN0aW9uV3JhcHBlciRtb2R1bGV0ADdMc2NhbGEvY29sbGVjdGlvbi9jb252ZXJ0L1dyYXBwZXJzJEpDb2xsZWN0aW9uV3JhcHBlciQ7TAAcSkNvbmN1cnJlbnRNYXBXcmFwcGVyJG1vZHVsZXQAOkxzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkSkNvbmN1cnJlbnRNYXBXcmFwcGVyJDtMABlKRGljdGlvbmFyeVdyYXBwZXIkbW9kdWxldAA3THNjYWxhL2NvbGxlY3Rpb24vY29udmVydC9XcmFwcGVycyRKRGljdGlvbmFyeVdyYXBwZXIkO0wAGkpFbnVtZXJhdGlvbldyYXBwZXIkbW9kdWxldAA4THNjYWxhL2NvbGxlY3Rpb24vY29udmVydC9XcmFwcGVycyRKRW51bWVyYXRpb25XcmFwcGVyJDtMABdKSXRlcmFibGVXcmFwcGVyJG1vZHVsZXQANUxzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkSkl0ZXJhYmxlV3JhcHBlciQ7TAAXSkl0ZXJhdG9yV3JhcHBlciRtb2R1bGV0ADVMc2NhbGEvY29sbGVjdGlvbi9jb252ZXJ0L1dyYXBwZXJzJEpJdGVyYXRvcldyYXBwZXIkO0wAE0pMaXN0V3JhcHBlciRtb2R1bGV0ADFMc2NhbGEvY29sbGVjdGlvbi9jb252ZXJ0L1dyYXBwZXJzJEpMaXN0V3JhcHBlciQ7TAAZSlByb3BlcnRpZXNXcmFwcGVyJG1vZHVsZXQAN0xzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkSlByb3BlcnRpZXNXcmFwcGVyJDtMABJKU2V0V3JhcHBlciRtb2R1bGV0ADBMc2NhbGEvY29sbGVjdGlvbi9jb252ZXJ0L1dyYXBwZXJzJEpTZXRXcmFwcGVyJDtMABtNdXRhYmxlQnVmZmVyV3JhcHBlciRtb2R1bGV0ADlMc2NhbGEvY29sbGVjdGlvbi9jb252ZXJ0L1dyYXBwZXJzJE11dGFibGVCdWZmZXJXcmFwcGVyJDtMABhNdXRhYmxlTWFwV3JhcHBlciRtb2R1bGV0ADZMc2NhbGEvY29sbGVjdGlvbi9jb252ZXJ0L1dyYXBwZXJzJE11dGFibGVNYXBXcmFwcGVyJDtMABhNdXRhYmxlU2VxV3JhcHBlciRtb2R1bGV0ADZMc2NhbGEvY29sbGVjdGlvbi9jb252ZXJ0L1dyYXBwZXJzJE11dGFibGVTZXFXcmFwcGVyJDtMABhNdXRhYmxlU2V0V3JhcHBlciRtb2R1bGV0ADZMc2NhbGEvY29sbGVjdGlvbi9jb252ZXJ0L1dyYXBwZXJzJE11dGFibGVTZXRXcmFwcGVyJDtMABFTZXFXcmFwcGVyJG1vZHVsZXQAL0xzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkU2VxV3JhcHBlciQ7eHBwcHBwcHBwcHBwcHBwcHBwcHNyADJzY2FsYS5jb2xsZWN0aW9uLmdlbmVyaWMuRGVmYXVsdFNlcmlhbGl6YXRpb25Qcm94eQAAAAAAAAADAwABTAAHZmFjdG9yeXQAGkxzY2FsYS9jb2xsZWN0aW9uL0ZhY3Rvcnk7eHBzcgAqc2NhbGEuY29sbGVjdGlvbi5JdGVyYWJsZUZhY3RvcnkkVG9GYWN0b3J5AAAAAAAAAAMCAAFMAAdmYWN0b3J5dAAiTHNjYWxhL2NvbGxlY3Rpb24vSXRlcmFibGVGYWN0b3J5O3hwc3IAIXNjYWxhLmNvbGxlY3Rpb24ubXV0YWJsZS5IYXNoU2V0JAAAAAAAAAADAgAAeHB3BAAAAAB4cQB+ABs=") check(g)(new collection.convert.Wrappers.MutableSetWrapper(mutable.Set(1, 2, 3)))("rO0ABXNyADNzY2FsYS5jb2xsZWN0aW9uLmNvbnZlcnQuV3JhcHBlcnMkTXV0YWJsZVNldFdyYXBwZXIAAAAAAAAAAwIAAUwACnVuZGVybHlpbmd0AB5Mc2NhbGEvY29sbGVjdGlvbi9tdXRhYmxlL1NldDt4cgAsc2NhbGEuY29sbGVjdGlvbi5jb252ZXJ0LldyYXBwZXJzJFNldFdyYXBwZXIAAAAAAAAAAwIAAkwABiRvdXRlcnQAI0xzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnM7TAA4c2NhbGEkY29sbGVjdGlvbiRjb252ZXJ0JFdyYXBwZXJzJFNldFdyYXBwZXIkJHVuZGVybHlpbmd0ABZMc2NhbGEvY29sbGVjdGlvbi9TZXQ7eHBzcgAic2NhbGEuY29sbGVjdGlvbi5jb252ZXJ0LldyYXBwZXJzJAAAAAAAAAADAgARTAAYRGljdGlvbmFyeVdyYXBwZXIkbW9kdWxldAA2THNjYWxhL2NvbGxlY3Rpb24vY29udmVydC9XcmFwcGVycyREaWN0aW9uYXJ5V3JhcHBlciQ7TAAWSXRlcmFibGVXcmFwcGVyJG1vZHVsZXQANExzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkSXRlcmFibGVXcmFwcGVyJDtMABZJdGVyYXRvcldyYXBwZXIkbW9kdWxldAA0THNjYWxhL2NvbGxlY3Rpb24vY29udmVydC9XcmFwcGVycyRJdGVyYXRvcldyYXBwZXIkO0wAGUpDb2xsZWN0aW9uV3JhcHBlciRtb2R1bGV0ADdMc2NhbGEvY29sbGVjdGlvbi9jb252ZXJ0L1dyYXBwZXJzJEpDb2xsZWN0aW9uV3JhcHBlciQ7TAAcSkNvbmN1cnJlbnRNYXBXcmFwcGVyJG1vZHVsZXQAOkxzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkSkNvbmN1cnJlbnRNYXBXcmFwcGVyJDtMABlKRGljdGlvbmFyeVdyYXBwZXIkbW9kdWxldAA3THNjYWxhL2NvbGxlY3Rpb24vY29udmVydC9XcmFwcGVycyRKRGljdGlvbmFyeVdyYXBwZXIkO0wAGkpFbnVtZXJhdGlvbldyYXBwZXIkbW9kdWxldAA4THNjYWxhL2NvbGxlY3Rpb24vY29udmVydC9XcmFwcGVycyRKRW51bWVyYXRpb25XcmFwcGVyJDtMABdKSXRlcmFibGVXcmFwcGVyJG1vZHVsZXQANUxzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkSkl0ZXJhYmxlV3JhcHBlciQ7TAAXSkl0ZXJhdG9yV3JhcHBlciRtb2R1bGV0ADVMc2NhbGEvY29sbGVjdGlvbi9jb252ZXJ0L1dyYXBwZXJzJEpJdGVyYXRvcldyYXBwZXIkO0wAE0pMaXN0V3JhcHBlciRtb2R1bGV0ADFMc2NhbGEvY29sbGVjdGlvbi9jb252ZXJ0L1dyYXBwZXJzJEpMaXN0V3JhcHBlciQ7TAAZSlByb3BlcnRpZXNXcmFwcGVyJG1vZHVsZXQAN0xzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkSlByb3BlcnRpZXNXcmFwcGVyJDtMABJKU2V0V3JhcHBlciRtb2R1bGV0ADBMc2NhbGEvY29sbGVjdGlvbi9jb252ZXJ0L1dyYXBwZXJzJEpTZXRXcmFwcGVyJDtMABtNdXRhYmxlQnVmZmVyV3JhcHBlciRtb2R1bGV0ADlMc2NhbGEvY29sbGVjdGlvbi9jb252ZXJ0L1dyYXBwZXJzJE11dGFibGVCdWZmZXJXcmFwcGVyJDtMABhNdXRhYmxlTWFwV3JhcHBlciRtb2R1bGV0ADZMc2NhbGEvY29sbGVjdGlvbi9jb252ZXJ0L1dyYXBwZXJzJE11dGFibGVNYXBXcmFwcGVyJDtMABhNdXRhYmxlU2VxV3JhcHBlciRtb2R1bGV0ADZMc2NhbGEvY29sbGVjdGlvbi9jb252ZXJ0L1dyYXBwZXJzJE11dGFibGVTZXFXcmFwcGVyJDtMABhNdXRhYmxlU2V0V3JhcHBlciRtb2R1bGV0ADZMc2NhbGEvY29sbGVjdGlvbi9jb252ZXJ0L1dyYXBwZXJzJE11dGFibGVTZXRXcmFwcGVyJDtMABFTZXFXcmFwcGVyJG1vZHVsZXQAL0xzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkU2VxV3JhcHBlciQ7eHBwcHBwcHBwcHBwcHBwcHBwcHNyADJzY2FsYS5jb2xsZWN0aW9uLmdlbmVyaWMuRGVmYXVsdFNlcmlhbGl6YXRpb25Qcm94eQAAAAAAAAADAwABTAAHZmFjdG9yeXQAGkxzY2FsYS9jb2xsZWN0aW9uL0ZhY3Rvcnk7eHBzcgAqc2NhbGEuY29sbGVjdGlvbi5JdGVyYWJsZUZhY3RvcnkkVG9GYWN0b3J5AAAAAAAAAAMCAAFMAAdmYWN0b3J5dAAiTHNjYWxhL2NvbGxlY3Rpb24vSXRlcmFibGVGYWN0b3J5O3hwc3IAIXNjYWxhLmNvbGxlY3Rpb24ubXV0YWJsZS5IYXNoU2V0JAAAAAAAAAADAgAAeHB3BAAAAANzcgARamF2YS5sYW5nLkludGVnZXIS4qCk94GHOAIAAUkABXZhbHVleHIAEGphdmEubGFuZy5OdW1iZXKGrJUdC5TgiwIAAHhwAAAAAXNxAH4AIQAAAAJzcQB+ACEAAAADeHEAfgAb") check(g)(new collection.convert.Wrappers.MapWrapper(immutable.Map()))("rO0ABXNyACxzY2FsYS5jb2xsZWN0aW9uLmNvbnZlcnQuV3JhcHBlcnMkTWFwV3JhcHBlcgAAAAAAAAADAgACTAAGJG91dGVydAAjTHNjYWxhL2NvbGxlY3Rpb24vY29udmVydC9XcmFwcGVycztMADhzY2FsYSRjb2xsZWN0aW9uJGNvbnZlcnQkV3JhcHBlcnMkTWFwV3JhcHBlciQkdW5kZXJseWluZ3QAFkxzY2FsYS9jb2xsZWN0aW9uL01hcDt4cHNyACJzY2FsYS5jb2xsZWN0aW9uLmNvbnZlcnQuV3JhcHBlcnMkAAAAAAAAAAMCABFMABhEaWN0aW9uYXJ5V3JhcHBlciRtb2R1bGV0ADZMc2NhbGEvY29sbGVjdGlvbi9jb252ZXJ0L1dyYXBwZXJzJERpY3Rpb25hcnlXcmFwcGVyJDtMABZJdGVyYWJsZVdyYXBwZXIkbW9kdWxldAA0THNjYWxhL2NvbGxlY3Rpb24vY29udmVydC9XcmFwcGVycyRJdGVyYWJsZVdyYXBwZXIkO0wAFkl0ZXJhdG9yV3JhcHBlciRtb2R1bGV0ADRMc2NhbGEvY29sbGVjdGlvbi9jb252ZXJ0L1dyYXBwZXJzJEl0ZXJhdG9yV3JhcHBlciQ7TAAZSkNvbGxlY3Rpb25XcmFwcGVyJG1vZHVsZXQAN0xzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkSkNvbGxlY3Rpb25XcmFwcGVyJDtMABxKQ29uY3VycmVudE1hcFdyYXBwZXIkbW9kdWxldAA6THNjYWxhL2NvbGxlY3Rpb24vY29udmVydC9XcmFwcGVycyRKQ29uY3VycmVudE1hcFdyYXBwZXIkO0wAGUpEaWN0aW9uYXJ5V3JhcHBlciRtb2R1bGV0ADdMc2NhbGEvY29sbGVjdGlvbi9jb252ZXJ0L1dyYXBwZXJzJEpEaWN0aW9uYXJ5V3JhcHBlciQ7TAAaSkVudW1lcmF0aW9uV3JhcHBlciRtb2R1bGV0ADhMc2NhbGEvY29sbGVjdGlvbi9jb252ZXJ0L1dyYXBwZXJzJEpFbnVtZXJhdGlvbldyYXBwZXIkO0wAF0pJdGVyYWJsZVdyYXBwZXIkbW9kdWxldAA1THNjYWxhL2NvbGxlY3Rpb24vY29udmVydC9XcmFwcGVycyRKSXRlcmFibGVXcmFwcGVyJDtMABdKSXRlcmF0b3JXcmFwcGVyJG1vZHVsZXQANUxzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkSkl0ZXJhdG9yV3JhcHBlciQ7TAATSkxpc3RXcmFwcGVyJG1vZHVsZXQAMUxzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkSkxpc3RXcmFwcGVyJDtMABlKUHJvcGVydGllc1dyYXBwZXIkbW9kdWxldAA3THNjYWxhL2NvbGxlY3Rpb24vY29udmVydC9XcmFwcGVycyRKUHJvcGVydGllc1dyYXBwZXIkO0wAEkpTZXRXcmFwcGVyJG1vZHVsZXQAMExzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkSlNldFdyYXBwZXIkO0wAG011dGFibGVCdWZmZXJXcmFwcGVyJG1vZHVsZXQAOUxzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkTXV0YWJsZUJ1ZmZlcldyYXBwZXIkO0wAGE11dGFibGVNYXBXcmFwcGVyJG1vZHVsZXQANkxzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkTXV0YWJsZU1hcFdyYXBwZXIkO0wAGE11dGFibGVTZXFXcmFwcGVyJG1vZHVsZXQANkxzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkTXV0YWJsZVNlcVdyYXBwZXIkO0wAGE11dGFibGVTZXRXcmFwcGVyJG1vZHVsZXQANkxzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkTXV0YWJsZVNldFdyYXBwZXIkO0wAEVNlcVdyYXBwZXIkbW9kdWxldAAvTHNjYWxhL2NvbGxlY3Rpb24vY29udmVydC9XcmFwcGVycyRTZXFXcmFwcGVyJDt4cHBwcHBwcHBwcHBwcHBwcHBwc3IAMnNjYWxhLmNvbGxlY3Rpb24uZ2VuZXJpYy5EZWZhdWx0U2VyaWFsaXphdGlvblByb3h5AAAAAAAAAAMDAAFMAAdmYWN0b3J5dAAaTHNjYWxhL2NvbGxlY3Rpb24vRmFjdG9yeTt4cHNyACVzY2FsYS5jb2xsZWN0aW9uLk1hcEZhY3RvcnkkVG9GYWN0b3J5AAAAAAAAAAMCAAFMAAdmYWN0b3J5dAAdTHNjYWxhL2NvbGxlY3Rpb24vTWFwRmFjdG9yeTt4cHNyAB9zY2FsYS5jb2xsZWN0aW9uLmltbXV0YWJsZS5NYXAkAAAAAAAAAAMDAAFaACtzY2FsYSRjb2xsZWN0aW9uJGltbXV0YWJsZSRNYXAkJHVzZUJhc2VsaW5leHB4dwQAAAAAeA==") - check(g)(new collection.convert.Wrappers.MapWrapper(immutable.Map[Int, Int](1 -> 2)))("rO0ABXNyACxzY2FsYS5jb2xsZWN0aW9uLmNvbnZlcnQuV3JhcHBlcnMkTWFwV3JhcHBlcgAAAAAAAAADAgACTAAGJG91dGVydAAjTHNjYWxhL2NvbGxlY3Rpb24vY29udmVydC9XcmFwcGVycztMADhzY2FsYSRjb2xsZWN0aW9uJGNvbnZlcnQkV3JhcHBlcnMkTWFwV3JhcHBlciQkdW5kZXJseWluZ3QAFkxzY2FsYS9jb2xsZWN0aW9uL01hcDt4cHNyACJzY2FsYS5jb2xsZWN0aW9uLmNvbnZlcnQuV3JhcHBlcnMkAAAAAAAAAAMCABFMABhEaWN0aW9uYXJ5V3JhcHBlciRtb2R1bGV0ADZMc2NhbGEvY29sbGVjdGlvbi9jb252ZXJ0L1dyYXBwZXJzJERpY3Rpb25hcnlXcmFwcGVyJDtMABZJdGVyYWJsZVdyYXBwZXIkbW9kdWxldAA0THNjYWxhL2NvbGxlY3Rpb24vY29udmVydC9XcmFwcGVycyRJdGVyYWJsZVdyYXBwZXIkO0wAFkl0ZXJhdG9yV3JhcHBlciRtb2R1bGV0ADRMc2NhbGEvY29sbGVjdGlvbi9jb252ZXJ0L1dyYXBwZXJzJEl0ZXJhdG9yV3JhcHBlciQ7TAAZSkNvbGxlY3Rpb25XcmFwcGVyJG1vZHVsZXQAN0xzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkSkNvbGxlY3Rpb25XcmFwcGVyJDtMABxKQ29uY3VycmVudE1hcFdyYXBwZXIkbW9kdWxldAA6THNjYWxhL2NvbGxlY3Rpb24vY29udmVydC9XcmFwcGVycyRKQ29uY3VycmVudE1hcFdyYXBwZXIkO0wAGUpEaWN0aW9uYXJ5V3JhcHBlciRtb2R1bGV0ADdMc2NhbGEvY29sbGVjdGlvbi9jb252ZXJ0L1dyYXBwZXJzJEpEaWN0aW9uYXJ5V3JhcHBlciQ7TAAaSkVudW1lcmF0aW9uV3JhcHBlciRtb2R1bGV0ADhMc2NhbGEvY29sbGVjdGlvbi9jb252ZXJ0L1dyYXBwZXJzJEpFbnVtZXJhdGlvbldyYXBwZXIkO0wAF0pJdGVyYWJsZVdyYXBwZXIkbW9kdWxldAA1THNjYWxhL2NvbGxlY3Rpb24vY29udmVydC9XcmFwcGVycyRKSXRlcmFibGVXcmFwcGVyJDtMABdKSXRlcmF0b3JXcmFwcGVyJG1vZHVsZXQANUxzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkSkl0ZXJhdG9yV3JhcHBlciQ7TAATSkxpc3RXcmFwcGVyJG1vZHVsZXQAMUxzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkSkxpc3RXcmFwcGVyJDtMABlKUHJvcGVydGllc1dyYXBwZXIkbW9kdWxldAA3THNjYWxhL2NvbGxlY3Rpb24vY29udmVydC9XcmFwcGVycyRKUHJvcGVydGllc1dyYXBwZXIkO0wAEkpTZXRXcmFwcGVyJG1vZHVsZXQAMExzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkSlNldFdyYXBwZXIkO0wAG011dGFibGVCdWZmZXJXcmFwcGVyJG1vZHVsZXQAOUxzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkTXV0YWJsZUJ1ZmZlcldyYXBwZXIkO0wAGE11dGFibGVNYXBXcmFwcGVyJG1vZHVsZXQANkxzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkTXV0YWJsZU1hcFdyYXBwZXIkO0wAGE11dGFibGVTZXFXcmFwcGVyJG1vZHVsZXQANkxzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkTXV0YWJsZVNlcVdyYXBwZXIkO0wAGE11dGFibGVTZXRXcmFwcGVyJG1vZHVsZXQANkxzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkTXV0YWJsZVNldFdyYXBwZXIkO0wAEVNlcVdyYXBwZXIkbW9kdWxldAAvTHNjYWxhL2NvbGxlY3Rpb24vY29udmVydC9XcmFwcGVycyRTZXFXcmFwcGVyJDt4cHBwcHBwcHBwcHBwcHBwcHBwc3IAMnNjYWxhLmNvbGxlY3Rpb24uZ2VuZXJpYy5EZWZhdWx0U2VyaWFsaXphdGlvblByb3h5AAAAAAAAAAMDAAFMAAdmYWN0b3J5dAAaTHNjYWxhL2NvbGxlY3Rpb24vRmFjdG9yeTt4cHNyACVzY2FsYS5jb2xsZWN0aW9uLk1hcEZhY3RvcnkkVG9GYWN0b3J5AAAAAAAAAAMCAAFMAAdmYWN0b3J5dAAdTHNjYWxhL2NvbGxlY3Rpb24vTWFwRmFjdG9yeTt4cHNyAB9zY2FsYS5jb2xsZWN0aW9uLmltbXV0YWJsZS5NYXAkAAAAAAAAAAMDAAFaACtzY2FsYSRjb2xsZWN0aW9uJGltbXV0YWJsZSRNYXAkJHVzZUJhc2VsaW5leHB4dwQAAAABc3IADHNjYWxhLlR1cGxlMi6UZn1bkvn1AgACTAACXzF0ABJMamF2YS9sYW5nL09iamVjdDtMAAJfMnEAfgAgeHBzcgARamF2YS5sYW5nLkludGVnZXIS4qCk94GHOAIAAUkABXZhbHVleHIAEGphdmEubGFuZy5OdW1iZXKGrJUdC5TgiwIAAHhwAAAAAXNxAH4AIgAAAAJ4") - check(g)(new collection.convert.Wrappers.MapWrapper(immutable.Map[Int, Int](1 -> 2, 2 -> 3)))("rO0ABXNyACxzY2FsYS5jb2xsZWN0aW9uLmNvbnZlcnQuV3JhcHBlcnMkTWFwV3JhcHBlcgAAAAAAAAADAgACTAAGJG91dGVydAAjTHNjYWxhL2NvbGxlY3Rpb24vY29udmVydC9XcmFwcGVycztMADhzY2FsYSRjb2xsZWN0aW9uJGNvbnZlcnQkV3JhcHBlcnMkTWFwV3JhcHBlciQkdW5kZXJseWluZ3QAFkxzY2FsYS9jb2xsZWN0aW9uL01hcDt4cHNyACJzY2FsYS5jb2xsZWN0aW9uLmNvbnZlcnQuV3JhcHBlcnMkAAAAAAAAAAMCABFMABhEaWN0aW9uYXJ5V3JhcHBlciRtb2R1bGV0ADZMc2NhbGEvY29sbGVjdGlvbi9jb252ZXJ0L1dyYXBwZXJzJERpY3Rpb25hcnlXcmFwcGVyJDtMABZJdGVyYWJsZVdyYXBwZXIkbW9kdWxldAA0THNjYWxhL2NvbGxlY3Rpb24vY29udmVydC9XcmFwcGVycyRJdGVyYWJsZVdyYXBwZXIkO0wAFkl0ZXJhdG9yV3JhcHBlciRtb2R1bGV0ADRMc2NhbGEvY29sbGVjdGlvbi9jb252ZXJ0L1dyYXBwZXJzJEl0ZXJhdG9yV3JhcHBlciQ7TAAZSkNvbGxlY3Rpb25XcmFwcGVyJG1vZHVsZXQAN0xzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkSkNvbGxlY3Rpb25XcmFwcGVyJDtMABxKQ29uY3VycmVudE1hcFdyYXBwZXIkbW9kdWxldAA6THNjYWxhL2NvbGxlY3Rpb24vY29udmVydC9XcmFwcGVycyRKQ29uY3VycmVudE1hcFdyYXBwZXIkO0wAGUpEaWN0aW9uYXJ5V3JhcHBlciRtb2R1bGV0ADdMc2NhbGEvY29sbGVjdGlvbi9jb252ZXJ0L1dyYXBwZXJzJEpEaWN0aW9uYXJ5V3JhcHBlciQ7TAAaSkVudW1lcmF0aW9uV3JhcHBlciRtb2R1bGV0ADhMc2NhbGEvY29sbGVjdGlvbi9jb252ZXJ0L1dyYXBwZXJzJEpFbnVtZXJhdGlvbldyYXBwZXIkO0wAF0pJdGVyYWJsZVdyYXBwZXIkbW9kdWxldAA1THNjYWxhL2NvbGxlY3Rpb24vY29udmVydC9XcmFwcGVycyRKSXRlcmFibGVXcmFwcGVyJDtMABdKSXRlcmF0b3JXcmFwcGVyJG1vZHVsZXQANUxzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkSkl0ZXJhdG9yV3JhcHBlciQ7TAATSkxpc3RXcmFwcGVyJG1vZHVsZXQAMUxzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkSkxpc3RXcmFwcGVyJDtMABlKUHJvcGVydGllc1dyYXBwZXIkbW9kdWxldAA3THNjYWxhL2NvbGxlY3Rpb24vY29udmVydC9XcmFwcGVycyRKUHJvcGVydGllc1dyYXBwZXIkO0wAEkpTZXRXcmFwcGVyJG1vZHVsZXQAMExzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkSlNldFdyYXBwZXIkO0wAG011dGFibGVCdWZmZXJXcmFwcGVyJG1vZHVsZXQAOUxzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkTXV0YWJsZUJ1ZmZlcldyYXBwZXIkO0wAGE11dGFibGVNYXBXcmFwcGVyJG1vZHVsZXQANkxzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkTXV0YWJsZU1hcFdyYXBwZXIkO0wAGE11dGFibGVTZXFXcmFwcGVyJG1vZHVsZXQANkxzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkTXV0YWJsZVNlcVdyYXBwZXIkO0wAGE11dGFibGVTZXRXcmFwcGVyJG1vZHVsZXQANkxzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkTXV0YWJsZVNldFdyYXBwZXIkO0wAEVNlcVdyYXBwZXIkbW9kdWxldAAvTHNjYWxhL2NvbGxlY3Rpb24vY29udmVydC9XcmFwcGVycyRTZXFXcmFwcGVyJDt4cHBwcHBwcHBwcHBwcHBwcHBwc3IAMnNjYWxhLmNvbGxlY3Rpb24uZ2VuZXJpYy5EZWZhdWx0U2VyaWFsaXphdGlvblByb3h5AAAAAAAAAAMDAAFMAAdmYWN0b3J5dAAaTHNjYWxhL2NvbGxlY3Rpb24vRmFjdG9yeTt4cHNyACVzY2FsYS5jb2xsZWN0aW9uLk1hcEZhY3RvcnkkVG9GYWN0b3J5AAAAAAAAAAMCAAFMAAdmYWN0b3J5dAAdTHNjYWxhL2NvbGxlY3Rpb24vTWFwRmFjdG9yeTt4cHNyAB9zY2FsYS5jb2xsZWN0aW9uLmltbXV0YWJsZS5NYXAkAAAAAAAAAAMDAAFaACtzY2FsYSRjb2xsZWN0aW9uJGltbXV0YWJsZSRNYXAkJHVzZUJhc2VsaW5leHB4dwQAAAACc3IADHNjYWxhLlR1cGxlMi6UZn1bkvn1AgACTAACXzF0ABJMamF2YS9sYW5nL09iamVjdDtMAAJfMnEAfgAgeHBzcgARamF2YS5sYW5nLkludGVnZXIS4qCk94GHOAIAAUkABXZhbHVleHIAEGphdmEubGFuZy5OdW1iZXKGrJUdC5TgiwIAAHhwAAAAAXNxAH4AIgAAAAJzcQB+AB9xAH4AJXNxAH4AIgAAAAN4") - check(g)(new collection.convert.Wrappers.MapWrapper(immutable.Map[Int, Int](1 -> 2, 2 -> 3, 3 -> 4)))("rO0ABXNyACxzY2FsYS5jb2xsZWN0aW9uLmNvbnZlcnQuV3JhcHBlcnMkTWFwV3JhcHBlcgAAAAAAAAADAgACTAAGJG91dGVydAAjTHNjYWxhL2NvbGxlY3Rpb24vY29udmVydC9XcmFwcGVycztMADhzY2FsYSRjb2xsZWN0aW9uJGNvbnZlcnQkV3JhcHBlcnMkTWFwV3JhcHBlciQkdW5kZXJseWluZ3QAFkxzY2FsYS9jb2xsZWN0aW9uL01hcDt4cHNyACJzY2FsYS5jb2xsZWN0aW9uLmNvbnZlcnQuV3JhcHBlcnMkAAAAAAAAAAMCABFMABhEaWN0aW9uYXJ5V3JhcHBlciRtb2R1bGV0ADZMc2NhbGEvY29sbGVjdGlvbi9jb252ZXJ0L1dyYXBwZXJzJERpY3Rpb25hcnlXcmFwcGVyJDtMABZJdGVyYWJsZVdyYXBwZXIkbW9kdWxldAA0THNjYWxhL2NvbGxlY3Rpb24vY29udmVydC9XcmFwcGVycyRJdGVyYWJsZVdyYXBwZXIkO0wAFkl0ZXJhdG9yV3JhcHBlciRtb2R1bGV0ADRMc2NhbGEvY29sbGVjdGlvbi9jb252ZXJ0L1dyYXBwZXJzJEl0ZXJhdG9yV3JhcHBlciQ7TAAZSkNvbGxlY3Rpb25XcmFwcGVyJG1vZHVsZXQAN0xzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkSkNvbGxlY3Rpb25XcmFwcGVyJDtMABxKQ29uY3VycmVudE1hcFdyYXBwZXIkbW9kdWxldAA6THNjYWxhL2NvbGxlY3Rpb24vY29udmVydC9XcmFwcGVycyRKQ29uY3VycmVudE1hcFdyYXBwZXIkO0wAGUpEaWN0aW9uYXJ5V3JhcHBlciRtb2R1bGV0ADdMc2NhbGEvY29sbGVjdGlvbi9jb252ZXJ0L1dyYXBwZXJzJEpEaWN0aW9uYXJ5V3JhcHBlciQ7TAAaSkVudW1lcmF0aW9uV3JhcHBlciRtb2R1bGV0ADhMc2NhbGEvY29sbGVjdGlvbi9jb252ZXJ0L1dyYXBwZXJzJEpFbnVtZXJhdGlvbldyYXBwZXIkO0wAF0pJdGVyYWJsZVdyYXBwZXIkbW9kdWxldAA1THNjYWxhL2NvbGxlY3Rpb24vY29udmVydC9XcmFwcGVycyRKSXRlcmFibGVXcmFwcGVyJDtMABdKSXRlcmF0b3JXcmFwcGVyJG1vZHVsZXQANUxzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkSkl0ZXJhdG9yV3JhcHBlciQ7TAATSkxpc3RXcmFwcGVyJG1vZHVsZXQAMUxzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkSkxpc3RXcmFwcGVyJDtMABlKUHJvcGVydGllc1dyYXBwZXIkbW9kdWxldAA3THNjYWxhL2NvbGxlY3Rpb24vY29udmVydC9XcmFwcGVycyRKUHJvcGVydGllc1dyYXBwZXIkO0wAEkpTZXRXcmFwcGVyJG1vZHVsZXQAMExzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkSlNldFdyYXBwZXIkO0wAG011dGFibGVCdWZmZXJXcmFwcGVyJG1vZHVsZXQAOUxzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkTXV0YWJsZUJ1ZmZlcldyYXBwZXIkO0wAGE11dGFibGVNYXBXcmFwcGVyJG1vZHVsZXQANkxzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkTXV0YWJsZU1hcFdyYXBwZXIkO0wAGE11dGFibGVTZXFXcmFwcGVyJG1vZHVsZXQANkxzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkTXV0YWJsZVNlcVdyYXBwZXIkO0wAGE11dGFibGVTZXRXcmFwcGVyJG1vZHVsZXQANkxzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkTXV0YWJsZVNldFdyYXBwZXIkO0wAEVNlcVdyYXBwZXIkbW9kdWxldAAvTHNjYWxhL2NvbGxlY3Rpb24vY29udmVydC9XcmFwcGVycyRTZXFXcmFwcGVyJDt4cHBwcHBwcHBwcHBwcHBwcHBwc3IAMnNjYWxhLmNvbGxlY3Rpb24uZ2VuZXJpYy5EZWZhdWx0U2VyaWFsaXphdGlvblByb3h5AAAAAAAAAAMDAAFMAAdmYWN0b3J5dAAaTHNjYWxhL2NvbGxlY3Rpb24vRmFjdG9yeTt4cHNyACVzY2FsYS5jb2xsZWN0aW9uLk1hcEZhY3RvcnkkVG9GYWN0b3J5AAAAAAAAAAMCAAFMAAdmYWN0b3J5dAAdTHNjYWxhL2NvbGxlY3Rpb24vTWFwRmFjdG9yeTt4cHNyAB9zY2FsYS5jb2xsZWN0aW9uLmltbXV0YWJsZS5NYXAkAAAAAAAAAAMDAAFaACtzY2FsYSRjb2xsZWN0aW9uJGltbXV0YWJsZSRNYXAkJHVzZUJhc2VsaW5leHB4dwQAAAADc3IADHNjYWxhLlR1cGxlMi6UZn1bkvn1AgACTAACXzF0ABJMamF2YS9sYW5nL09iamVjdDtMAAJfMnEAfgAgeHBzcgARamF2YS5sYW5nLkludGVnZXIS4qCk94GHOAIAAUkABXZhbHVleHIAEGphdmEubGFuZy5OdW1iZXKGrJUdC5TgiwIAAHhwAAAAAXNxAH4AIgAAAAJzcQB+AB9xAH4AJXNxAH4AIgAAAANzcQB+AB9xAH4AJ3NxAH4AIgAAAAR4") - check(g)(new collection.convert.Wrappers.MapWrapper(immutable.Map[Int, Int](1 -> 2, 2 -> 3, 3 -> 4, 4 -> 5)))("rO0ABXNyACxzY2FsYS5jb2xsZWN0aW9uLmNvbnZlcnQuV3JhcHBlcnMkTWFwV3JhcHBlcgAAAAAAAAADAgACTAAGJG91dGVydAAjTHNjYWxhL2NvbGxlY3Rpb24vY29udmVydC9XcmFwcGVycztMADhzY2FsYSRjb2xsZWN0aW9uJGNvbnZlcnQkV3JhcHBlcnMkTWFwV3JhcHBlciQkdW5kZXJseWluZ3QAFkxzY2FsYS9jb2xsZWN0aW9uL01hcDt4cHNyACJzY2FsYS5jb2xsZWN0aW9uLmNvbnZlcnQuV3JhcHBlcnMkAAAAAAAAAAMCABFMABhEaWN0aW9uYXJ5V3JhcHBlciRtb2R1bGV0ADZMc2NhbGEvY29sbGVjdGlvbi9jb252ZXJ0L1dyYXBwZXJzJERpY3Rpb25hcnlXcmFwcGVyJDtMABZJdGVyYWJsZVdyYXBwZXIkbW9kdWxldAA0THNjYWxhL2NvbGxlY3Rpb24vY29udmVydC9XcmFwcGVycyRJdGVyYWJsZVdyYXBwZXIkO0wAFkl0ZXJhdG9yV3JhcHBlciRtb2R1bGV0ADRMc2NhbGEvY29sbGVjdGlvbi9jb252ZXJ0L1dyYXBwZXJzJEl0ZXJhdG9yV3JhcHBlciQ7TAAZSkNvbGxlY3Rpb25XcmFwcGVyJG1vZHVsZXQAN0xzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkSkNvbGxlY3Rpb25XcmFwcGVyJDtMABxKQ29uY3VycmVudE1hcFdyYXBwZXIkbW9kdWxldAA6THNjYWxhL2NvbGxlY3Rpb24vY29udmVydC9XcmFwcGVycyRKQ29uY3VycmVudE1hcFdyYXBwZXIkO0wAGUpEaWN0aW9uYXJ5V3JhcHBlciRtb2R1bGV0ADdMc2NhbGEvY29sbGVjdGlvbi9jb252ZXJ0L1dyYXBwZXJzJEpEaWN0aW9uYXJ5V3JhcHBlciQ7TAAaSkVudW1lcmF0aW9uV3JhcHBlciRtb2R1bGV0ADhMc2NhbGEvY29sbGVjdGlvbi9jb252ZXJ0L1dyYXBwZXJzJEpFbnVtZXJhdGlvbldyYXBwZXIkO0wAF0pJdGVyYWJsZVdyYXBwZXIkbW9kdWxldAA1THNjYWxhL2NvbGxlY3Rpb24vY29udmVydC9XcmFwcGVycyRKSXRlcmFibGVXcmFwcGVyJDtMABdKSXRlcmF0b3JXcmFwcGVyJG1vZHVsZXQANUxzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkSkl0ZXJhdG9yV3JhcHBlciQ7TAATSkxpc3RXcmFwcGVyJG1vZHVsZXQAMUxzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkSkxpc3RXcmFwcGVyJDtMABlKUHJvcGVydGllc1dyYXBwZXIkbW9kdWxldAA3THNjYWxhL2NvbGxlY3Rpb24vY29udmVydC9XcmFwcGVycyRKUHJvcGVydGllc1dyYXBwZXIkO0wAEkpTZXRXcmFwcGVyJG1vZHVsZXQAMExzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkSlNldFdyYXBwZXIkO0wAG011dGFibGVCdWZmZXJXcmFwcGVyJG1vZHVsZXQAOUxzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkTXV0YWJsZUJ1ZmZlcldyYXBwZXIkO0wAGE11dGFibGVNYXBXcmFwcGVyJG1vZHVsZXQANkxzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkTXV0YWJsZU1hcFdyYXBwZXIkO0wAGE11dGFibGVTZXFXcmFwcGVyJG1vZHVsZXQANkxzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkTXV0YWJsZVNlcVdyYXBwZXIkO0wAGE11dGFibGVTZXRXcmFwcGVyJG1vZHVsZXQANkxzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkTXV0YWJsZVNldFdyYXBwZXIkO0wAEVNlcVdyYXBwZXIkbW9kdWxldAAvTHNjYWxhL2NvbGxlY3Rpb24vY29udmVydC9XcmFwcGVycyRTZXFXcmFwcGVyJDt4cHBwcHBwcHBwcHBwcHBwcHBwc3IAMnNjYWxhLmNvbGxlY3Rpb24uZ2VuZXJpYy5EZWZhdWx0U2VyaWFsaXphdGlvblByb3h5AAAAAAAAAAMDAAFMAAdmYWN0b3J5dAAaTHNjYWxhL2NvbGxlY3Rpb24vRmFjdG9yeTt4cHNyACVzY2FsYS5jb2xsZWN0aW9uLk1hcEZhY3RvcnkkVG9GYWN0b3J5AAAAAAAAAAMCAAFMAAdmYWN0b3J5dAAdTHNjYWxhL2NvbGxlY3Rpb24vTWFwRmFjdG9yeTt4cHNyAB9zY2FsYS5jb2xsZWN0aW9uLmltbXV0YWJsZS5NYXAkAAAAAAAAAAMDAAFaACtzY2FsYSRjb2xsZWN0aW9uJGltbXV0YWJsZSRNYXAkJHVzZUJhc2VsaW5leHB4dwQAAAAEc3IADHNjYWxhLlR1cGxlMi6UZn1bkvn1AgACTAACXzF0ABJMamF2YS9sYW5nL09iamVjdDtMAAJfMnEAfgAgeHBzcgARamF2YS5sYW5nLkludGVnZXIS4qCk94GHOAIAAUkABXZhbHVleHIAEGphdmEubGFuZy5OdW1iZXKGrJUdC5TgiwIAAHhwAAAAAXNxAH4AIgAAAAJzcQB+AB9xAH4AJXNxAH4AIgAAAANzcQB+AB9xAH4AJ3NxAH4AIgAAAARzcQB+AB9xAH4AKXNxAH4AIgAAAAV4") - check(g)(new collection.convert.Wrappers.MapWrapper(immutable.Map[Int, Int](1 -> 2, 2 -> 3, 3 -> 4, 4 -> 5, 5 -> 6)))("rO0ABXNyACxzY2FsYS5jb2xsZWN0aW9uLmNvbnZlcnQuV3JhcHBlcnMkTWFwV3JhcHBlcgAAAAAAAAADAgACTAAGJG91dGVydAAjTHNjYWxhL2NvbGxlY3Rpb24vY29udmVydC9XcmFwcGVycztMADhzY2FsYSRjb2xsZWN0aW9uJGNvbnZlcnQkV3JhcHBlcnMkTWFwV3JhcHBlciQkdW5kZXJseWluZ3QAFkxzY2FsYS9jb2xsZWN0aW9uL01hcDt4cHNyACJzY2FsYS5jb2xsZWN0aW9uLmNvbnZlcnQuV3JhcHBlcnMkAAAAAAAAAAMCABFMABhEaWN0aW9uYXJ5V3JhcHBlciRtb2R1bGV0ADZMc2NhbGEvY29sbGVjdGlvbi9jb252ZXJ0L1dyYXBwZXJzJERpY3Rpb25hcnlXcmFwcGVyJDtMABZJdGVyYWJsZVdyYXBwZXIkbW9kdWxldAA0THNjYWxhL2NvbGxlY3Rpb24vY29udmVydC9XcmFwcGVycyRJdGVyYWJsZVdyYXBwZXIkO0wAFkl0ZXJhdG9yV3JhcHBlciRtb2R1bGV0ADRMc2NhbGEvY29sbGVjdGlvbi9jb252ZXJ0L1dyYXBwZXJzJEl0ZXJhdG9yV3JhcHBlciQ7TAAZSkNvbGxlY3Rpb25XcmFwcGVyJG1vZHVsZXQAN0xzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkSkNvbGxlY3Rpb25XcmFwcGVyJDtMABxKQ29uY3VycmVudE1hcFdyYXBwZXIkbW9kdWxldAA6THNjYWxhL2NvbGxlY3Rpb24vY29udmVydC9XcmFwcGVycyRKQ29uY3VycmVudE1hcFdyYXBwZXIkO0wAGUpEaWN0aW9uYXJ5V3JhcHBlciRtb2R1bGV0ADdMc2NhbGEvY29sbGVjdGlvbi9jb252ZXJ0L1dyYXBwZXJzJEpEaWN0aW9uYXJ5V3JhcHBlciQ7TAAaSkVudW1lcmF0aW9uV3JhcHBlciRtb2R1bGV0ADhMc2NhbGEvY29sbGVjdGlvbi9jb252ZXJ0L1dyYXBwZXJzJEpFbnVtZXJhdGlvbldyYXBwZXIkO0wAF0pJdGVyYWJsZVdyYXBwZXIkbW9kdWxldAA1THNjYWxhL2NvbGxlY3Rpb24vY29udmVydC9XcmFwcGVycyRKSXRlcmFibGVXcmFwcGVyJDtMABdKSXRlcmF0b3JXcmFwcGVyJG1vZHVsZXQANUxzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkSkl0ZXJhdG9yV3JhcHBlciQ7TAATSkxpc3RXcmFwcGVyJG1vZHVsZXQAMUxzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkSkxpc3RXcmFwcGVyJDtMABlKUHJvcGVydGllc1dyYXBwZXIkbW9kdWxldAA3THNjYWxhL2NvbGxlY3Rpb24vY29udmVydC9XcmFwcGVycyRKUHJvcGVydGllc1dyYXBwZXIkO0wAEkpTZXRXcmFwcGVyJG1vZHVsZXQAMExzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkSlNldFdyYXBwZXIkO0wAG011dGFibGVCdWZmZXJXcmFwcGVyJG1vZHVsZXQAOUxzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkTXV0YWJsZUJ1ZmZlcldyYXBwZXIkO0wAGE11dGFibGVNYXBXcmFwcGVyJG1vZHVsZXQANkxzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkTXV0YWJsZU1hcFdyYXBwZXIkO0wAGE11dGFibGVTZXFXcmFwcGVyJG1vZHVsZXQANkxzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkTXV0YWJsZVNlcVdyYXBwZXIkO0wAGE11dGFibGVTZXRXcmFwcGVyJG1vZHVsZXQANkxzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkTXV0YWJsZVNldFdyYXBwZXIkO0wAEVNlcVdyYXBwZXIkbW9kdWxldAAvTHNjYWxhL2NvbGxlY3Rpb24vY29udmVydC9XcmFwcGVycyRTZXFXcmFwcGVyJDt4cHBwcHBwcHBwcHBwcHBwcHBwc3IAMnNjYWxhLmNvbGxlY3Rpb24uZ2VuZXJpYy5EZWZhdWx0U2VyaWFsaXphdGlvblByb3h5AAAAAAAAAAMDAAFMAAdmYWN0b3J5dAAaTHNjYWxhL2NvbGxlY3Rpb24vRmFjdG9yeTt4cHNyACVzY2FsYS5jb2xsZWN0aW9uLk1hcEZhY3RvcnkkVG9GYWN0b3J5AAAAAAAAAAMCAAFMAAdmYWN0b3J5dAAdTHNjYWxhL2NvbGxlY3Rpb24vTWFwRmFjdG9yeTt4cHNyAChzY2FsYS5jb2xsZWN0aW9uLmltbXV0YWJsZS5DaGFtcEhhc2hNYXAkAAAAAAAAAAMDAAFMAAhFbXB0eU1hcHQAKUxzY2FsYS9jb2xsZWN0aW9uL2ltbXV0YWJsZS9DaGFtcEhhc2hNYXA7eHB4dwQAAAAFc3IADHNjYWxhLlR1cGxlMi6UZn1bkvn1AgACTAACXzF0ABJMamF2YS9sYW5nL09iamVjdDtMAAJfMnEAfgAheHBzcgARamF2YS5sYW5nLkludGVnZXIS4qCk94GHOAIAAUkABXZhbHVleHIAEGphdmEubGFuZy5OdW1iZXKGrJUdC5TgiwIAAHhwAAAABXNxAH4AIwAAAAZzcQB+ACBzcQB+ACMAAAABc3EAfgAjAAAAAnNxAH4AIHEAfgApc3EAfgAjAAAAA3NxAH4AIHEAfgArc3EAfgAjAAAABHNxAH4AIHEAfgAtcQB+ACV4") + check(g)(new collection.convert.Wrappers.MapWrapper(immutable.Map[Int, Int](1 -> 2)))("rO0ABXNyACxzY2FsYS5jb2xsZWN0aW9uLmNvbnZlcnQuV3JhcHBlcnMkTWFwV3JhcHBlcgAAAAAAAAADAgACTAAGJG91dGVydAAjTHNjYWxhL2NvbGxlY3Rpb24vY29udmVydC9XcmFwcGVycztMADhzY2FsYSRjb2xsZWN0aW9uJGNvbnZlcnQkV3JhcHBlcnMkTWFwV3JhcHBlciQkdW5kZXJseWluZ3QAFkxzY2FsYS9jb2xsZWN0aW9uL01hcDt4cHNyACJzY2FsYS5jb2xsZWN0aW9uLmNvbnZlcnQuV3JhcHBlcnMkAAAAAAAAAAMCABFMABhEaWN0aW9uYXJ5V3JhcHBlciRtb2R1bGV0ADZMc2NhbGEvY29sbGVjdGlvbi9jb252ZXJ0L1dyYXBwZXJzJERpY3Rpb25hcnlXcmFwcGVyJDtMABZJdGVyYWJsZVdyYXBwZXIkbW9kdWxldAA0THNjYWxhL2NvbGxlY3Rpb24vY29udmVydC9XcmFwcGVycyRJdGVyYWJsZVdyYXBwZXIkO0wAFkl0ZXJhdG9yV3JhcHBlciRtb2R1bGV0ADRMc2NhbGEvY29sbGVjdGlvbi9jb252ZXJ0L1dyYXBwZXJzJEl0ZXJhdG9yV3JhcHBlciQ7TAAZSkNvbGxlY3Rpb25XcmFwcGVyJG1vZHVsZXQAN0xzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkSkNvbGxlY3Rpb25XcmFwcGVyJDtMABxKQ29uY3VycmVudE1hcFdyYXBwZXIkbW9kdWxldAA6THNjYWxhL2NvbGxlY3Rpb24vY29udmVydC9XcmFwcGVycyRKQ29uY3VycmVudE1hcFdyYXBwZXIkO0wAGUpEaWN0aW9uYXJ5V3JhcHBlciRtb2R1bGV0ADdMc2NhbGEvY29sbGVjdGlvbi9jb252ZXJ0L1dyYXBwZXJzJEpEaWN0aW9uYXJ5V3JhcHBlciQ7TAAaSkVudW1lcmF0aW9uV3JhcHBlciRtb2R1bGV0ADhMc2NhbGEvY29sbGVjdGlvbi9jb252ZXJ0L1dyYXBwZXJzJEpFbnVtZXJhdGlvbldyYXBwZXIkO0wAF0pJdGVyYWJsZVdyYXBwZXIkbW9kdWxldAA1THNjYWxhL2NvbGxlY3Rpb24vY29udmVydC9XcmFwcGVycyRKSXRlcmFibGVXcmFwcGVyJDtMABdKSXRlcmF0b3JXcmFwcGVyJG1vZHVsZXQANUxzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkSkl0ZXJhdG9yV3JhcHBlciQ7TAATSkxpc3RXcmFwcGVyJG1vZHVsZXQAMUxzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkSkxpc3RXcmFwcGVyJDtMABlKUHJvcGVydGllc1dyYXBwZXIkbW9kdWxldAA3THNjYWxhL2NvbGxlY3Rpb24vY29udmVydC9XcmFwcGVycyRKUHJvcGVydGllc1dyYXBwZXIkO0wAEkpTZXRXcmFwcGVyJG1vZHVsZXQAMExzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkSlNldFdyYXBwZXIkO0wAG011dGFibGVCdWZmZXJXcmFwcGVyJG1vZHVsZXQAOUxzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkTXV0YWJsZUJ1ZmZlcldyYXBwZXIkO0wAGE11dGFibGVNYXBXcmFwcGVyJG1vZHVsZXQANkxzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkTXV0YWJsZU1hcFdyYXBwZXIkO0wAGE11dGFibGVTZXFXcmFwcGVyJG1vZHVsZXQANkxzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkTXV0YWJsZVNlcVdyYXBwZXIkO0wAGE11dGFibGVTZXRXcmFwcGVyJG1vZHVsZXQANkxzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkTXV0YWJsZVNldFdyYXBwZXIkO0wAEVNlcVdyYXBwZXIkbW9kdWxldAAvTHNjYWxhL2NvbGxlY3Rpb24vY29udmVydC9XcmFwcGVycyRTZXFXcmFwcGVyJDt4cHBwcHBwcHBwcHBwcHBwcHBwc3IAMnNjYWxhLmNvbGxlY3Rpb24uZ2VuZXJpYy5EZWZhdWx0U2VyaWFsaXphdGlvblByb3h5AAAAAAAAAAMDAAFMAAdmYWN0b3J5dAAaTHNjYWxhL2NvbGxlY3Rpb24vRmFjdG9yeTt4cHNyACVzY2FsYS5jb2xsZWN0aW9uLk1hcEZhY3RvcnkkVG9GYWN0b3J5AAAAAAAAAAMCAAFMAAdmYWN0b3J5dAAdTHNjYWxhL2NvbGxlY3Rpb24vTWFwRmFjdG9yeTt4cHNyAB9zY2FsYS5jb2xsZWN0aW9uLmltbXV0YWJsZS5NYXAkAAAAAAAAAAMDAAFaACtzY2FsYSRjb2xsZWN0aW9uJGltbXV0YWJsZSRNYXAkJHVzZUJhc2VsaW5leHB4dwQAAAABc3IADHNjYWxhLlR1cGxlMhDcBtcOREuEAgACTAACXzF0ABJMamF2YS9sYW5nL09iamVjdDtMAAJfMnEAfgAgeHBzcgARamF2YS5sYW5nLkludGVnZXIS4qCk94GHOAIAAUkABXZhbHVleHIAEGphdmEubGFuZy5OdW1iZXKGrJUdC5TgiwIAAHhwAAAAAXNxAH4AIgAAAAJ4") + check(g)(new collection.convert.Wrappers.MapWrapper(immutable.Map[Int, Int](1 -> 2, 2 -> 3)))("rO0ABXNyACxzY2FsYS5jb2xsZWN0aW9uLmNvbnZlcnQuV3JhcHBlcnMkTWFwV3JhcHBlcgAAAAAAAAADAgACTAAGJG91dGVydAAjTHNjYWxhL2NvbGxlY3Rpb24vY29udmVydC9XcmFwcGVycztMADhzY2FsYSRjb2xsZWN0aW9uJGNvbnZlcnQkV3JhcHBlcnMkTWFwV3JhcHBlciQkdW5kZXJseWluZ3QAFkxzY2FsYS9jb2xsZWN0aW9uL01hcDt4cHNyACJzY2FsYS5jb2xsZWN0aW9uLmNvbnZlcnQuV3JhcHBlcnMkAAAAAAAAAAMCABFMABhEaWN0aW9uYXJ5V3JhcHBlciRtb2R1bGV0ADZMc2NhbGEvY29sbGVjdGlvbi9jb252ZXJ0L1dyYXBwZXJzJERpY3Rpb25hcnlXcmFwcGVyJDtMABZJdGVyYWJsZVdyYXBwZXIkbW9kdWxldAA0THNjYWxhL2NvbGxlY3Rpb24vY29udmVydC9XcmFwcGVycyRJdGVyYWJsZVdyYXBwZXIkO0wAFkl0ZXJhdG9yV3JhcHBlciRtb2R1bGV0ADRMc2NhbGEvY29sbGVjdGlvbi9jb252ZXJ0L1dyYXBwZXJzJEl0ZXJhdG9yV3JhcHBlciQ7TAAZSkNvbGxlY3Rpb25XcmFwcGVyJG1vZHVsZXQAN0xzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkSkNvbGxlY3Rpb25XcmFwcGVyJDtMABxKQ29uY3VycmVudE1hcFdyYXBwZXIkbW9kdWxldAA6THNjYWxhL2NvbGxlY3Rpb24vY29udmVydC9XcmFwcGVycyRKQ29uY3VycmVudE1hcFdyYXBwZXIkO0wAGUpEaWN0aW9uYXJ5V3JhcHBlciRtb2R1bGV0ADdMc2NhbGEvY29sbGVjdGlvbi9jb252ZXJ0L1dyYXBwZXJzJEpEaWN0aW9uYXJ5V3JhcHBlciQ7TAAaSkVudW1lcmF0aW9uV3JhcHBlciRtb2R1bGV0ADhMc2NhbGEvY29sbGVjdGlvbi9jb252ZXJ0L1dyYXBwZXJzJEpFbnVtZXJhdGlvbldyYXBwZXIkO0wAF0pJdGVyYWJsZVdyYXBwZXIkbW9kdWxldAA1THNjYWxhL2NvbGxlY3Rpb24vY29udmVydC9XcmFwcGVycyRKSXRlcmFibGVXcmFwcGVyJDtMABdKSXRlcmF0b3JXcmFwcGVyJG1vZHVsZXQANUxzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkSkl0ZXJhdG9yV3JhcHBlciQ7TAATSkxpc3RXcmFwcGVyJG1vZHVsZXQAMUxzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkSkxpc3RXcmFwcGVyJDtMABlKUHJvcGVydGllc1dyYXBwZXIkbW9kdWxldAA3THNjYWxhL2NvbGxlY3Rpb24vY29udmVydC9XcmFwcGVycyRKUHJvcGVydGllc1dyYXBwZXIkO0wAEkpTZXRXcmFwcGVyJG1vZHVsZXQAMExzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkSlNldFdyYXBwZXIkO0wAG011dGFibGVCdWZmZXJXcmFwcGVyJG1vZHVsZXQAOUxzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkTXV0YWJsZUJ1ZmZlcldyYXBwZXIkO0wAGE11dGFibGVNYXBXcmFwcGVyJG1vZHVsZXQANkxzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkTXV0YWJsZU1hcFdyYXBwZXIkO0wAGE11dGFibGVTZXFXcmFwcGVyJG1vZHVsZXQANkxzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkTXV0YWJsZVNlcVdyYXBwZXIkO0wAGE11dGFibGVTZXRXcmFwcGVyJG1vZHVsZXQANkxzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkTXV0YWJsZVNldFdyYXBwZXIkO0wAEVNlcVdyYXBwZXIkbW9kdWxldAAvTHNjYWxhL2NvbGxlY3Rpb24vY29udmVydC9XcmFwcGVycyRTZXFXcmFwcGVyJDt4cHBwcHBwcHBwcHBwcHBwcHBwc3IAMnNjYWxhLmNvbGxlY3Rpb24uZ2VuZXJpYy5EZWZhdWx0U2VyaWFsaXphdGlvblByb3h5AAAAAAAAAAMDAAFMAAdmYWN0b3J5dAAaTHNjYWxhL2NvbGxlY3Rpb24vRmFjdG9yeTt4cHNyACVzY2FsYS5jb2xsZWN0aW9uLk1hcEZhY3RvcnkkVG9GYWN0b3J5AAAAAAAAAAMCAAFMAAdmYWN0b3J5dAAdTHNjYWxhL2NvbGxlY3Rpb24vTWFwRmFjdG9yeTt4cHNyAB9zY2FsYS5jb2xsZWN0aW9uLmltbXV0YWJsZS5NYXAkAAAAAAAAAAMDAAFaACtzY2FsYSRjb2xsZWN0aW9uJGltbXV0YWJsZSRNYXAkJHVzZUJhc2VsaW5leHB4dwQAAAACc3IADHNjYWxhLlR1cGxlMhDcBtcOREuEAgACTAACXzF0ABJMamF2YS9sYW5nL09iamVjdDtMAAJfMnEAfgAgeHBzcgARamF2YS5sYW5nLkludGVnZXIS4qCk94GHOAIAAUkABXZhbHVleHIAEGphdmEubGFuZy5OdW1iZXKGrJUdC5TgiwIAAHhwAAAAAXNxAH4AIgAAAAJzcQB+AB9xAH4AJXNxAH4AIgAAAAN4") + check(g)(new collection.convert.Wrappers.MapWrapper(immutable.Map[Int, Int](1 -> 2, 2 -> 3, 3 -> 4)))("rO0ABXNyACxzY2FsYS5jb2xsZWN0aW9uLmNvbnZlcnQuV3JhcHBlcnMkTWFwV3JhcHBlcgAAAAAAAAADAgACTAAGJG91dGVydAAjTHNjYWxhL2NvbGxlY3Rpb24vY29udmVydC9XcmFwcGVycztMADhzY2FsYSRjb2xsZWN0aW9uJGNvbnZlcnQkV3JhcHBlcnMkTWFwV3JhcHBlciQkdW5kZXJseWluZ3QAFkxzY2FsYS9jb2xsZWN0aW9uL01hcDt4cHNyACJzY2FsYS5jb2xsZWN0aW9uLmNvbnZlcnQuV3JhcHBlcnMkAAAAAAAAAAMCABFMABhEaWN0aW9uYXJ5V3JhcHBlciRtb2R1bGV0ADZMc2NhbGEvY29sbGVjdGlvbi9jb252ZXJ0L1dyYXBwZXJzJERpY3Rpb25hcnlXcmFwcGVyJDtMABZJdGVyYWJsZVdyYXBwZXIkbW9kdWxldAA0THNjYWxhL2NvbGxlY3Rpb24vY29udmVydC9XcmFwcGVycyRJdGVyYWJsZVdyYXBwZXIkO0wAFkl0ZXJhdG9yV3JhcHBlciRtb2R1bGV0ADRMc2NhbGEvY29sbGVjdGlvbi9jb252ZXJ0L1dyYXBwZXJzJEl0ZXJhdG9yV3JhcHBlciQ7TAAZSkNvbGxlY3Rpb25XcmFwcGVyJG1vZHVsZXQAN0xzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkSkNvbGxlY3Rpb25XcmFwcGVyJDtMABxKQ29uY3VycmVudE1hcFdyYXBwZXIkbW9kdWxldAA6THNjYWxhL2NvbGxlY3Rpb24vY29udmVydC9XcmFwcGVycyRKQ29uY3VycmVudE1hcFdyYXBwZXIkO0wAGUpEaWN0aW9uYXJ5V3JhcHBlciRtb2R1bGV0ADdMc2NhbGEvY29sbGVjdGlvbi9jb252ZXJ0L1dyYXBwZXJzJEpEaWN0aW9uYXJ5V3JhcHBlciQ7TAAaSkVudW1lcmF0aW9uV3JhcHBlciRtb2R1bGV0ADhMc2NhbGEvY29sbGVjdGlvbi9jb252ZXJ0L1dyYXBwZXJzJEpFbnVtZXJhdGlvbldyYXBwZXIkO0wAF0pJdGVyYWJsZVdyYXBwZXIkbW9kdWxldAA1THNjYWxhL2NvbGxlY3Rpb24vY29udmVydC9XcmFwcGVycyRKSXRlcmFibGVXcmFwcGVyJDtMABdKSXRlcmF0b3JXcmFwcGVyJG1vZHVsZXQANUxzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkSkl0ZXJhdG9yV3JhcHBlciQ7TAATSkxpc3RXcmFwcGVyJG1vZHVsZXQAMUxzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkSkxpc3RXcmFwcGVyJDtMABlKUHJvcGVydGllc1dyYXBwZXIkbW9kdWxldAA3THNjYWxhL2NvbGxlY3Rpb24vY29udmVydC9XcmFwcGVycyRKUHJvcGVydGllc1dyYXBwZXIkO0wAEkpTZXRXcmFwcGVyJG1vZHVsZXQAMExzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkSlNldFdyYXBwZXIkO0wAG011dGFibGVCdWZmZXJXcmFwcGVyJG1vZHVsZXQAOUxzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkTXV0YWJsZUJ1ZmZlcldyYXBwZXIkO0wAGE11dGFibGVNYXBXcmFwcGVyJG1vZHVsZXQANkxzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkTXV0YWJsZU1hcFdyYXBwZXIkO0wAGE11dGFibGVTZXFXcmFwcGVyJG1vZHVsZXQANkxzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkTXV0YWJsZVNlcVdyYXBwZXIkO0wAGE11dGFibGVTZXRXcmFwcGVyJG1vZHVsZXQANkxzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkTXV0YWJsZVNldFdyYXBwZXIkO0wAEVNlcVdyYXBwZXIkbW9kdWxldAAvTHNjYWxhL2NvbGxlY3Rpb24vY29udmVydC9XcmFwcGVycyRTZXFXcmFwcGVyJDt4cHBwcHBwcHBwcHBwcHBwcHBwc3IAMnNjYWxhLmNvbGxlY3Rpb24uZ2VuZXJpYy5EZWZhdWx0U2VyaWFsaXphdGlvblByb3h5AAAAAAAAAAMDAAFMAAdmYWN0b3J5dAAaTHNjYWxhL2NvbGxlY3Rpb24vRmFjdG9yeTt4cHNyACVzY2FsYS5jb2xsZWN0aW9uLk1hcEZhY3RvcnkkVG9GYWN0b3J5AAAAAAAAAAMCAAFMAAdmYWN0b3J5dAAdTHNjYWxhL2NvbGxlY3Rpb24vTWFwRmFjdG9yeTt4cHNyAB9zY2FsYS5jb2xsZWN0aW9uLmltbXV0YWJsZS5NYXAkAAAAAAAAAAMDAAFaACtzY2FsYSRjb2xsZWN0aW9uJGltbXV0YWJsZSRNYXAkJHVzZUJhc2VsaW5leHB4dwQAAAADc3IADHNjYWxhLlR1cGxlMhDcBtcOREuEAgACTAACXzF0ABJMamF2YS9sYW5nL09iamVjdDtMAAJfMnEAfgAgeHBzcgARamF2YS5sYW5nLkludGVnZXIS4qCk94GHOAIAAUkABXZhbHVleHIAEGphdmEubGFuZy5OdW1iZXKGrJUdC5TgiwIAAHhwAAAAAXNxAH4AIgAAAAJzcQB+AB9xAH4AJXNxAH4AIgAAAANzcQB+AB9xAH4AJ3NxAH4AIgAAAAR4") + check(g)(new collection.convert.Wrappers.MapWrapper(immutable.Map[Int, Int](1 -> 2, 2 -> 3, 3 -> 4, 4 -> 5)))("rO0ABXNyACxzY2FsYS5jb2xsZWN0aW9uLmNvbnZlcnQuV3JhcHBlcnMkTWFwV3JhcHBlcgAAAAAAAAADAgACTAAGJG91dGVydAAjTHNjYWxhL2NvbGxlY3Rpb24vY29udmVydC9XcmFwcGVycztMADhzY2FsYSRjb2xsZWN0aW9uJGNvbnZlcnQkV3JhcHBlcnMkTWFwV3JhcHBlciQkdW5kZXJseWluZ3QAFkxzY2FsYS9jb2xsZWN0aW9uL01hcDt4cHNyACJzY2FsYS5jb2xsZWN0aW9uLmNvbnZlcnQuV3JhcHBlcnMkAAAAAAAAAAMCABFMABhEaWN0aW9uYXJ5V3JhcHBlciRtb2R1bGV0ADZMc2NhbGEvY29sbGVjdGlvbi9jb252ZXJ0L1dyYXBwZXJzJERpY3Rpb25hcnlXcmFwcGVyJDtMABZJdGVyYWJsZVdyYXBwZXIkbW9kdWxldAA0THNjYWxhL2NvbGxlY3Rpb24vY29udmVydC9XcmFwcGVycyRJdGVyYWJsZVdyYXBwZXIkO0wAFkl0ZXJhdG9yV3JhcHBlciRtb2R1bGV0ADRMc2NhbGEvY29sbGVjdGlvbi9jb252ZXJ0L1dyYXBwZXJzJEl0ZXJhdG9yV3JhcHBlciQ7TAAZSkNvbGxlY3Rpb25XcmFwcGVyJG1vZHVsZXQAN0xzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkSkNvbGxlY3Rpb25XcmFwcGVyJDtMABxKQ29uY3VycmVudE1hcFdyYXBwZXIkbW9kdWxldAA6THNjYWxhL2NvbGxlY3Rpb24vY29udmVydC9XcmFwcGVycyRKQ29uY3VycmVudE1hcFdyYXBwZXIkO0wAGUpEaWN0aW9uYXJ5V3JhcHBlciRtb2R1bGV0ADdMc2NhbGEvY29sbGVjdGlvbi9jb252ZXJ0L1dyYXBwZXJzJEpEaWN0aW9uYXJ5V3JhcHBlciQ7TAAaSkVudW1lcmF0aW9uV3JhcHBlciRtb2R1bGV0ADhMc2NhbGEvY29sbGVjdGlvbi9jb252ZXJ0L1dyYXBwZXJzJEpFbnVtZXJhdGlvbldyYXBwZXIkO0wAF0pJdGVyYWJsZVdyYXBwZXIkbW9kdWxldAA1THNjYWxhL2NvbGxlY3Rpb24vY29udmVydC9XcmFwcGVycyRKSXRlcmFibGVXcmFwcGVyJDtMABdKSXRlcmF0b3JXcmFwcGVyJG1vZHVsZXQANUxzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkSkl0ZXJhdG9yV3JhcHBlciQ7TAATSkxpc3RXcmFwcGVyJG1vZHVsZXQAMUxzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkSkxpc3RXcmFwcGVyJDtMABlKUHJvcGVydGllc1dyYXBwZXIkbW9kdWxldAA3THNjYWxhL2NvbGxlY3Rpb24vY29udmVydC9XcmFwcGVycyRKUHJvcGVydGllc1dyYXBwZXIkO0wAEkpTZXRXcmFwcGVyJG1vZHVsZXQAMExzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkSlNldFdyYXBwZXIkO0wAG011dGFibGVCdWZmZXJXcmFwcGVyJG1vZHVsZXQAOUxzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkTXV0YWJsZUJ1ZmZlcldyYXBwZXIkO0wAGE11dGFibGVNYXBXcmFwcGVyJG1vZHVsZXQANkxzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkTXV0YWJsZU1hcFdyYXBwZXIkO0wAGE11dGFibGVTZXFXcmFwcGVyJG1vZHVsZXQANkxzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkTXV0YWJsZVNlcVdyYXBwZXIkO0wAGE11dGFibGVTZXRXcmFwcGVyJG1vZHVsZXQANkxzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkTXV0YWJsZVNldFdyYXBwZXIkO0wAEVNlcVdyYXBwZXIkbW9kdWxldAAvTHNjYWxhL2NvbGxlY3Rpb24vY29udmVydC9XcmFwcGVycyRTZXFXcmFwcGVyJDt4cHBwcHBwcHBwcHBwcHBwcHBwc3IAMnNjYWxhLmNvbGxlY3Rpb24uZ2VuZXJpYy5EZWZhdWx0U2VyaWFsaXphdGlvblByb3h5AAAAAAAAAAMDAAFMAAdmYWN0b3J5dAAaTHNjYWxhL2NvbGxlY3Rpb24vRmFjdG9yeTt4cHNyACVzY2FsYS5jb2xsZWN0aW9uLk1hcEZhY3RvcnkkVG9GYWN0b3J5AAAAAAAAAAMCAAFMAAdmYWN0b3J5dAAdTHNjYWxhL2NvbGxlY3Rpb24vTWFwRmFjdG9yeTt4cHNyAB9zY2FsYS5jb2xsZWN0aW9uLmltbXV0YWJsZS5NYXAkAAAAAAAAAAMDAAFaACtzY2FsYSRjb2xsZWN0aW9uJGltbXV0YWJsZSRNYXAkJHVzZUJhc2VsaW5leHB4dwQAAAAEc3IADHNjYWxhLlR1cGxlMhDcBtcOREuEAgACTAACXzF0ABJMamF2YS9sYW5nL09iamVjdDtMAAJfMnEAfgAgeHBzcgARamF2YS5sYW5nLkludGVnZXIS4qCk94GHOAIAAUkABXZhbHVleHIAEGphdmEubGFuZy5OdW1iZXKGrJUdC5TgiwIAAHhwAAAAAXNxAH4AIgAAAAJzcQB+AB9xAH4AJXNxAH4AIgAAAANzcQB+AB9xAH4AJ3NxAH4AIgAAAARzcQB+AB9xAH4AKXNxAH4AIgAAAAV4") + check(g)(new collection.convert.Wrappers.MapWrapper(immutable.Map[Int, Int](1 -> 2, 2 -> 3, 3 -> 4, 4 -> 5, 5 -> 6)))("rO0ABXNyACxzY2FsYS5jb2xsZWN0aW9uLmNvbnZlcnQuV3JhcHBlcnMkTWFwV3JhcHBlcgAAAAAAAAADAgACTAAGJG91dGVydAAjTHNjYWxhL2NvbGxlY3Rpb24vY29udmVydC9XcmFwcGVycztMADhzY2FsYSRjb2xsZWN0aW9uJGNvbnZlcnQkV3JhcHBlcnMkTWFwV3JhcHBlciQkdW5kZXJseWluZ3QAFkxzY2FsYS9jb2xsZWN0aW9uL01hcDt4cHNyACJzY2FsYS5jb2xsZWN0aW9uLmNvbnZlcnQuV3JhcHBlcnMkAAAAAAAAAAMCABFMABhEaWN0aW9uYXJ5V3JhcHBlciRtb2R1bGV0ADZMc2NhbGEvY29sbGVjdGlvbi9jb252ZXJ0L1dyYXBwZXJzJERpY3Rpb25hcnlXcmFwcGVyJDtMABZJdGVyYWJsZVdyYXBwZXIkbW9kdWxldAA0THNjYWxhL2NvbGxlY3Rpb24vY29udmVydC9XcmFwcGVycyRJdGVyYWJsZVdyYXBwZXIkO0wAFkl0ZXJhdG9yV3JhcHBlciRtb2R1bGV0ADRMc2NhbGEvY29sbGVjdGlvbi9jb252ZXJ0L1dyYXBwZXJzJEl0ZXJhdG9yV3JhcHBlciQ7TAAZSkNvbGxlY3Rpb25XcmFwcGVyJG1vZHVsZXQAN0xzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkSkNvbGxlY3Rpb25XcmFwcGVyJDtMABxKQ29uY3VycmVudE1hcFdyYXBwZXIkbW9kdWxldAA6THNjYWxhL2NvbGxlY3Rpb24vY29udmVydC9XcmFwcGVycyRKQ29uY3VycmVudE1hcFdyYXBwZXIkO0wAGUpEaWN0aW9uYXJ5V3JhcHBlciRtb2R1bGV0ADdMc2NhbGEvY29sbGVjdGlvbi9jb252ZXJ0L1dyYXBwZXJzJEpEaWN0aW9uYXJ5V3JhcHBlciQ7TAAaSkVudW1lcmF0aW9uV3JhcHBlciRtb2R1bGV0ADhMc2NhbGEvY29sbGVjdGlvbi9jb252ZXJ0L1dyYXBwZXJzJEpFbnVtZXJhdGlvbldyYXBwZXIkO0wAF0pJdGVyYWJsZVdyYXBwZXIkbW9kdWxldAA1THNjYWxhL2NvbGxlY3Rpb24vY29udmVydC9XcmFwcGVycyRKSXRlcmFibGVXcmFwcGVyJDtMABdKSXRlcmF0b3JXcmFwcGVyJG1vZHVsZXQANUxzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkSkl0ZXJhdG9yV3JhcHBlciQ7TAATSkxpc3RXcmFwcGVyJG1vZHVsZXQAMUxzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkSkxpc3RXcmFwcGVyJDtMABlKUHJvcGVydGllc1dyYXBwZXIkbW9kdWxldAA3THNjYWxhL2NvbGxlY3Rpb24vY29udmVydC9XcmFwcGVycyRKUHJvcGVydGllc1dyYXBwZXIkO0wAEkpTZXRXcmFwcGVyJG1vZHVsZXQAMExzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkSlNldFdyYXBwZXIkO0wAG011dGFibGVCdWZmZXJXcmFwcGVyJG1vZHVsZXQAOUxzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkTXV0YWJsZUJ1ZmZlcldyYXBwZXIkO0wAGE11dGFibGVNYXBXcmFwcGVyJG1vZHVsZXQANkxzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkTXV0YWJsZU1hcFdyYXBwZXIkO0wAGE11dGFibGVTZXFXcmFwcGVyJG1vZHVsZXQANkxzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkTXV0YWJsZVNlcVdyYXBwZXIkO0wAGE11dGFibGVTZXRXcmFwcGVyJG1vZHVsZXQANkxzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkTXV0YWJsZVNldFdyYXBwZXIkO0wAEVNlcVdyYXBwZXIkbW9kdWxldAAvTHNjYWxhL2NvbGxlY3Rpb24vY29udmVydC9XcmFwcGVycyRTZXFXcmFwcGVyJDt4cHBwcHBwcHBwcHBwcHBwcHBwc3IAMnNjYWxhLmNvbGxlY3Rpb24uZ2VuZXJpYy5EZWZhdWx0U2VyaWFsaXphdGlvblByb3h5AAAAAAAAAAMDAAFMAAdmYWN0b3J5dAAaTHNjYWxhL2NvbGxlY3Rpb24vRmFjdG9yeTt4cHNyACVzY2FsYS5jb2xsZWN0aW9uLk1hcEZhY3RvcnkkVG9GYWN0b3J5AAAAAAAAAAMCAAFMAAdmYWN0b3J5dAAdTHNjYWxhL2NvbGxlY3Rpb24vTWFwRmFjdG9yeTt4cHNyAChzY2FsYS5jb2xsZWN0aW9uLmltbXV0YWJsZS5DaGFtcEhhc2hNYXAkAAAAAAAAAAMDAAFMAAhFbXB0eU1hcHQAKUxzY2FsYS9jb2xsZWN0aW9uL2ltbXV0YWJsZS9DaGFtcEhhc2hNYXA7eHB4dwQAAAAFc3IADHNjYWxhLlR1cGxlMhDcBtcOREuEAgACTAACXzF0ABJMamF2YS9sYW5nL09iamVjdDtMAAJfMnEAfgAheHBzcgARamF2YS5sYW5nLkludGVnZXIS4qCk94GHOAIAAUkABXZhbHVleHIAEGphdmEubGFuZy5OdW1iZXKGrJUdC5TgiwIAAHhwAAAABXNxAH4AIwAAAAZzcQB+ACBzcQB+ACMAAAABc3EAfgAjAAAAAnNxAH4AIHEAfgApc3EAfgAjAAAAA3NxAH4AIHEAfgArc3EAfgAjAAAABHNxAH4AIHEAfgAtcQB+ACV4") check(g)(new collection.convert.Wrappers.MapWrapper(mutable.Map()))("rO0ABXNyACxzY2FsYS5jb2xsZWN0aW9uLmNvbnZlcnQuV3JhcHBlcnMkTWFwV3JhcHBlcgAAAAAAAAADAgACTAAGJG91dGVydAAjTHNjYWxhL2NvbGxlY3Rpb24vY29udmVydC9XcmFwcGVycztMADhzY2FsYSRjb2xsZWN0aW9uJGNvbnZlcnQkV3JhcHBlcnMkTWFwV3JhcHBlciQkdW5kZXJseWluZ3QAFkxzY2FsYS9jb2xsZWN0aW9uL01hcDt4cHNyACJzY2FsYS5jb2xsZWN0aW9uLmNvbnZlcnQuV3JhcHBlcnMkAAAAAAAAAAMCABFMABhEaWN0aW9uYXJ5V3JhcHBlciRtb2R1bGV0ADZMc2NhbGEvY29sbGVjdGlvbi9jb252ZXJ0L1dyYXBwZXJzJERpY3Rpb25hcnlXcmFwcGVyJDtMABZJdGVyYWJsZVdyYXBwZXIkbW9kdWxldAA0THNjYWxhL2NvbGxlY3Rpb24vY29udmVydC9XcmFwcGVycyRJdGVyYWJsZVdyYXBwZXIkO0wAFkl0ZXJhdG9yV3JhcHBlciRtb2R1bGV0ADRMc2NhbGEvY29sbGVjdGlvbi9jb252ZXJ0L1dyYXBwZXJzJEl0ZXJhdG9yV3JhcHBlciQ7TAAZSkNvbGxlY3Rpb25XcmFwcGVyJG1vZHVsZXQAN0xzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkSkNvbGxlY3Rpb25XcmFwcGVyJDtMABxKQ29uY3VycmVudE1hcFdyYXBwZXIkbW9kdWxldAA6THNjYWxhL2NvbGxlY3Rpb24vY29udmVydC9XcmFwcGVycyRKQ29uY3VycmVudE1hcFdyYXBwZXIkO0wAGUpEaWN0aW9uYXJ5V3JhcHBlciRtb2R1bGV0ADdMc2NhbGEvY29sbGVjdGlvbi9jb252ZXJ0L1dyYXBwZXJzJEpEaWN0aW9uYXJ5V3JhcHBlciQ7TAAaSkVudW1lcmF0aW9uV3JhcHBlciRtb2R1bGV0ADhMc2NhbGEvY29sbGVjdGlvbi9jb252ZXJ0L1dyYXBwZXJzJEpFbnVtZXJhdGlvbldyYXBwZXIkO0wAF0pJdGVyYWJsZVdyYXBwZXIkbW9kdWxldAA1THNjYWxhL2NvbGxlY3Rpb24vY29udmVydC9XcmFwcGVycyRKSXRlcmFibGVXcmFwcGVyJDtMABdKSXRlcmF0b3JXcmFwcGVyJG1vZHVsZXQANUxzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkSkl0ZXJhdG9yV3JhcHBlciQ7TAATSkxpc3RXcmFwcGVyJG1vZHVsZXQAMUxzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkSkxpc3RXcmFwcGVyJDtMABlKUHJvcGVydGllc1dyYXBwZXIkbW9kdWxldAA3THNjYWxhL2NvbGxlY3Rpb24vY29udmVydC9XcmFwcGVycyRKUHJvcGVydGllc1dyYXBwZXIkO0wAEkpTZXRXcmFwcGVyJG1vZHVsZXQAMExzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkSlNldFdyYXBwZXIkO0wAG011dGFibGVCdWZmZXJXcmFwcGVyJG1vZHVsZXQAOUxzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkTXV0YWJsZUJ1ZmZlcldyYXBwZXIkO0wAGE11dGFibGVNYXBXcmFwcGVyJG1vZHVsZXQANkxzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkTXV0YWJsZU1hcFdyYXBwZXIkO0wAGE11dGFibGVTZXFXcmFwcGVyJG1vZHVsZXQANkxzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkTXV0YWJsZVNlcVdyYXBwZXIkO0wAGE11dGFibGVTZXRXcmFwcGVyJG1vZHVsZXQANkxzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkTXV0YWJsZVNldFdyYXBwZXIkO0wAEVNlcVdyYXBwZXIkbW9kdWxldAAvTHNjYWxhL2NvbGxlY3Rpb24vY29udmVydC9XcmFwcGVycyRTZXFXcmFwcGVyJDt4cHBwcHBwcHBwcHBwcHBwcHBwc3IAMnNjYWxhLmNvbGxlY3Rpb24uZ2VuZXJpYy5EZWZhdWx0U2VyaWFsaXphdGlvblByb3h5AAAAAAAAAAMDAAFMAAdmYWN0b3J5dAAaTHNjYWxhL2NvbGxlY3Rpb24vRmFjdG9yeTt4cHNyACVzY2FsYS5jb2xsZWN0aW9uLk1hcEZhY3RvcnkkVG9GYWN0b3J5AAAAAAAAAAMCAAFMAAdmYWN0b3J5dAAdTHNjYWxhL2NvbGxlY3Rpb24vTWFwRmFjdG9yeTt4cHNyACFzY2FsYS5jb2xsZWN0aW9uLm11dGFibGUuSGFzaE1hcCQAAAAAAAAAAwIAAHhwdwQAAAAAeA==") - check(g)(new collection.convert.Wrappers.MapWrapper(mutable.Map[Int, Int](1 -> 2, 2 -> 3, 3 -> 4)))("rO0ABXNyACxzY2FsYS5jb2xsZWN0aW9uLmNvbnZlcnQuV3JhcHBlcnMkTWFwV3JhcHBlcgAAAAAAAAADAgACTAAGJG91dGVydAAjTHNjYWxhL2NvbGxlY3Rpb24vY29udmVydC9XcmFwcGVycztMADhzY2FsYSRjb2xsZWN0aW9uJGNvbnZlcnQkV3JhcHBlcnMkTWFwV3JhcHBlciQkdW5kZXJseWluZ3QAFkxzY2FsYS9jb2xsZWN0aW9uL01hcDt4cHNyACJzY2FsYS5jb2xsZWN0aW9uLmNvbnZlcnQuV3JhcHBlcnMkAAAAAAAAAAMCABFMABhEaWN0aW9uYXJ5V3JhcHBlciRtb2R1bGV0ADZMc2NhbGEvY29sbGVjdGlvbi9jb252ZXJ0L1dyYXBwZXJzJERpY3Rpb25hcnlXcmFwcGVyJDtMABZJdGVyYWJsZVdyYXBwZXIkbW9kdWxldAA0THNjYWxhL2NvbGxlY3Rpb24vY29udmVydC9XcmFwcGVycyRJdGVyYWJsZVdyYXBwZXIkO0wAFkl0ZXJhdG9yV3JhcHBlciRtb2R1bGV0ADRMc2NhbGEvY29sbGVjdGlvbi9jb252ZXJ0L1dyYXBwZXJzJEl0ZXJhdG9yV3JhcHBlciQ7TAAZSkNvbGxlY3Rpb25XcmFwcGVyJG1vZHVsZXQAN0xzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkSkNvbGxlY3Rpb25XcmFwcGVyJDtMABxKQ29uY3VycmVudE1hcFdyYXBwZXIkbW9kdWxldAA6THNjYWxhL2NvbGxlY3Rpb24vY29udmVydC9XcmFwcGVycyRKQ29uY3VycmVudE1hcFdyYXBwZXIkO0wAGUpEaWN0aW9uYXJ5V3JhcHBlciRtb2R1bGV0ADdMc2NhbGEvY29sbGVjdGlvbi9jb252ZXJ0L1dyYXBwZXJzJEpEaWN0aW9uYXJ5V3JhcHBlciQ7TAAaSkVudW1lcmF0aW9uV3JhcHBlciRtb2R1bGV0ADhMc2NhbGEvY29sbGVjdGlvbi9jb252ZXJ0L1dyYXBwZXJzJEpFbnVtZXJhdGlvbldyYXBwZXIkO0wAF0pJdGVyYWJsZVdyYXBwZXIkbW9kdWxldAA1THNjYWxhL2NvbGxlY3Rpb24vY29udmVydC9XcmFwcGVycyRKSXRlcmFibGVXcmFwcGVyJDtMABdKSXRlcmF0b3JXcmFwcGVyJG1vZHVsZXQANUxzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkSkl0ZXJhdG9yV3JhcHBlciQ7TAATSkxpc3RXcmFwcGVyJG1vZHVsZXQAMUxzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkSkxpc3RXcmFwcGVyJDtMABlKUHJvcGVydGllc1dyYXBwZXIkbW9kdWxldAA3THNjYWxhL2NvbGxlY3Rpb24vY29udmVydC9XcmFwcGVycyRKUHJvcGVydGllc1dyYXBwZXIkO0wAEkpTZXRXcmFwcGVyJG1vZHVsZXQAMExzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkSlNldFdyYXBwZXIkO0wAG011dGFibGVCdWZmZXJXcmFwcGVyJG1vZHVsZXQAOUxzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkTXV0YWJsZUJ1ZmZlcldyYXBwZXIkO0wAGE11dGFibGVNYXBXcmFwcGVyJG1vZHVsZXQANkxzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkTXV0YWJsZU1hcFdyYXBwZXIkO0wAGE11dGFibGVTZXFXcmFwcGVyJG1vZHVsZXQANkxzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkTXV0YWJsZVNlcVdyYXBwZXIkO0wAGE11dGFibGVTZXRXcmFwcGVyJG1vZHVsZXQANkxzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkTXV0YWJsZVNldFdyYXBwZXIkO0wAEVNlcVdyYXBwZXIkbW9kdWxldAAvTHNjYWxhL2NvbGxlY3Rpb24vY29udmVydC9XcmFwcGVycyRTZXFXcmFwcGVyJDt4cHBwcHBwcHBwcHBwcHBwcHBwc3IAMnNjYWxhLmNvbGxlY3Rpb24uZ2VuZXJpYy5EZWZhdWx0U2VyaWFsaXphdGlvblByb3h5AAAAAAAAAAMDAAFMAAdmYWN0b3J5dAAaTHNjYWxhL2NvbGxlY3Rpb24vRmFjdG9yeTt4cHNyACVzY2FsYS5jb2xsZWN0aW9uLk1hcEZhY3RvcnkkVG9GYWN0b3J5AAAAAAAAAAMCAAFMAAdmYWN0b3J5dAAdTHNjYWxhL2NvbGxlY3Rpb24vTWFwRmFjdG9yeTt4cHNyACFzY2FsYS5jb2xsZWN0aW9uLm11dGFibGUuSGFzaE1hcCQAAAAAAAAAAwIAAHhwdwQAAAADc3IADHNjYWxhLlR1cGxlMi6UZn1bkvn1AgACTAACXzF0ABJMamF2YS9sYW5nL09iamVjdDtMAAJfMnEAfgAgeHBzcgARamF2YS5sYW5nLkludGVnZXIS4qCk94GHOAIAAUkABXZhbHVleHIAEGphdmEubGFuZy5OdW1iZXKGrJUdC5TgiwIAAHhwAAAAAnNxAH4AIgAAAANzcQB+AB9zcQB+ACIAAAABcQB+ACRzcQB+AB9xAH4AJXNxAH4AIgAAAAR4") + check(g)(new collection.convert.Wrappers.MapWrapper(mutable.Map[Int, Int](1 -> 2, 2 -> 3, 3 -> 4)))("rO0ABXNyACxzY2FsYS5jb2xsZWN0aW9uLmNvbnZlcnQuV3JhcHBlcnMkTWFwV3JhcHBlcgAAAAAAAAADAgACTAAGJG91dGVydAAjTHNjYWxhL2NvbGxlY3Rpb24vY29udmVydC9XcmFwcGVycztMADhzY2FsYSRjb2xsZWN0aW9uJGNvbnZlcnQkV3JhcHBlcnMkTWFwV3JhcHBlciQkdW5kZXJseWluZ3QAFkxzY2FsYS9jb2xsZWN0aW9uL01hcDt4cHNyACJzY2FsYS5jb2xsZWN0aW9uLmNvbnZlcnQuV3JhcHBlcnMkAAAAAAAAAAMCABFMABhEaWN0aW9uYXJ5V3JhcHBlciRtb2R1bGV0ADZMc2NhbGEvY29sbGVjdGlvbi9jb252ZXJ0L1dyYXBwZXJzJERpY3Rpb25hcnlXcmFwcGVyJDtMABZJdGVyYWJsZVdyYXBwZXIkbW9kdWxldAA0THNjYWxhL2NvbGxlY3Rpb24vY29udmVydC9XcmFwcGVycyRJdGVyYWJsZVdyYXBwZXIkO0wAFkl0ZXJhdG9yV3JhcHBlciRtb2R1bGV0ADRMc2NhbGEvY29sbGVjdGlvbi9jb252ZXJ0L1dyYXBwZXJzJEl0ZXJhdG9yV3JhcHBlciQ7TAAZSkNvbGxlY3Rpb25XcmFwcGVyJG1vZHVsZXQAN0xzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkSkNvbGxlY3Rpb25XcmFwcGVyJDtMABxKQ29uY3VycmVudE1hcFdyYXBwZXIkbW9kdWxldAA6THNjYWxhL2NvbGxlY3Rpb24vY29udmVydC9XcmFwcGVycyRKQ29uY3VycmVudE1hcFdyYXBwZXIkO0wAGUpEaWN0aW9uYXJ5V3JhcHBlciRtb2R1bGV0ADdMc2NhbGEvY29sbGVjdGlvbi9jb252ZXJ0L1dyYXBwZXJzJEpEaWN0aW9uYXJ5V3JhcHBlciQ7TAAaSkVudW1lcmF0aW9uV3JhcHBlciRtb2R1bGV0ADhMc2NhbGEvY29sbGVjdGlvbi9jb252ZXJ0L1dyYXBwZXJzJEpFbnVtZXJhdGlvbldyYXBwZXIkO0wAF0pJdGVyYWJsZVdyYXBwZXIkbW9kdWxldAA1THNjYWxhL2NvbGxlY3Rpb24vY29udmVydC9XcmFwcGVycyRKSXRlcmFibGVXcmFwcGVyJDtMABdKSXRlcmF0b3JXcmFwcGVyJG1vZHVsZXQANUxzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkSkl0ZXJhdG9yV3JhcHBlciQ7TAATSkxpc3RXcmFwcGVyJG1vZHVsZXQAMUxzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkSkxpc3RXcmFwcGVyJDtMABlKUHJvcGVydGllc1dyYXBwZXIkbW9kdWxldAA3THNjYWxhL2NvbGxlY3Rpb24vY29udmVydC9XcmFwcGVycyRKUHJvcGVydGllc1dyYXBwZXIkO0wAEkpTZXRXcmFwcGVyJG1vZHVsZXQAMExzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkSlNldFdyYXBwZXIkO0wAG011dGFibGVCdWZmZXJXcmFwcGVyJG1vZHVsZXQAOUxzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkTXV0YWJsZUJ1ZmZlcldyYXBwZXIkO0wAGE11dGFibGVNYXBXcmFwcGVyJG1vZHVsZXQANkxzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkTXV0YWJsZU1hcFdyYXBwZXIkO0wAGE11dGFibGVTZXFXcmFwcGVyJG1vZHVsZXQANkxzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkTXV0YWJsZVNlcVdyYXBwZXIkO0wAGE11dGFibGVTZXRXcmFwcGVyJG1vZHVsZXQANkxzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkTXV0YWJsZVNldFdyYXBwZXIkO0wAEVNlcVdyYXBwZXIkbW9kdWxldAAvTHNjYWxhL2NvbGxlY3Rpb24vY29udmVydC9XcmFwcGVycyRTZXFXcmFwcGVyJDt4cHBwcHBwcHBwcHBwcHBwcHBwc3IAMnNjYWxhLmNvbGxlY3Rpb24uZ2VuZXJpYy5EZWZhdWx0U2VyaWFsaXphdGlvblByb3h5AAAAAAAAAAMDAAFMAAdmYWN0b3J5dAAaTHNjYWxhL2NvbGxlY3Rpb24vRmFjdG9yeTt4cHNyACVzY2FsYS5jb2xsZWN0aW9uLk1hcEZhY3RvcnkkVG9GYWN0b3J5AAAAAAAAAAMCAAFMAAdmYWN0b3J5dAAdTHNjYWxhL2NvbGxlY3Rpb24vTWFwRmFjdG9yeTt4cHNyACFzY2FsYS5jb2xsZWN0aW9uLm11dGFibGUuSGFzaE1hcCQAAAAAAAAAAwIAAHhwdwQAAAADc3IADHNjYWxhLlR1cGxlMhDcBtcOREuEAgACTAACXzF0ABJMamF2YS9sYW5nL09iamVjdDtMAAJfMnEAfgAgeHBzcgARamF2YS5sYW5nLkludGVnZXIS4qCk94GHOAIAAUkABXZhbHVleHIAEGphdmEubGFuZy5OdW1iZXKGrJUdC5TgiwIAAHhwAAAAAnNxAH4AIgAAAANzcQB+AB9zcQB+ACIAAAABcQB+ACRzcQB+AB9xAH4AJXNxAH4AIgAAAAR4") check(g)(new collection.convert.Wrappers.MutableMapWrapper(mutable.Map()))("rO0ABXNyADNzY2FsYS5jb2xsZWN0aW9uLmNvbnZlcnQuV3JhcHBlcnMkTXV0YWJsZU1hcFdyYXBwZXIAAAAAAAAAAwIAAUwACnVuZGVybHlpbmd0AB5Mc2NhbGEvY29sbGVjdGlvbi9tdXRhYmxlL01hcDt4cgAsc2NhbGEuY29sbGVjdGlvbi5jb252ZXJ0LldyYXBwZXJzJE1hcFdyYXBwZXIAAAAAAAAAAwIAAkwABiRvdXRlcnQAI0xzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnM7TAA4c2NhbGEkY29sbGVjdGlvbiRjb252ZXJ0JFdyYXBwZXJzJE1hcFdyYXBwZXIkJHVuZGVybHlpbmd0ABZMc2NhbGEvY29sbGVjdGlvbi9NYXA7eHBzcgAic2NhbGEuY29sbGVjdGlvbi5jb252ZXJ0LldyYXBwZXJzJAAAAAAAAAADAgARTAAYRGljdGlvbmFyeVdyYXBwZXIkbW9kdWxldAA2THNjYWxhL2NvbGxlY3Rpb24vY29udmVydC9XcmFwcGVycyREaWN0aW9uYXJ5V3JhcHBlciQ7TAAWSXRlcmFibGVXcmFwcGVyJG1vZHVsZXQANExzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkSXRlcmFibGVXcmFwcGVyJDtMABZJdGVyYXRvcldyYXBwZXIkbW9kdWxldAA0THNjYWxhL2NvbGxlY3Rpb24vY29udmVydC9XcmFwcGVycyRJdGVyYXRvcldyYXBwZXIkO0wAGUpDb2xsZWN0aW9uV3JhcHBlciRtb2R1bGV0ADdMc2NhbGEvY29sbGVjdGlvbi9jb252ZXJ0L1dyYXBwZXJzJEpDb2xsZWN0aW9uV3JhcHBlciQ7TAAcSkNvbmN1cnJlbnRNYXBXcmFwcGVyJG1vZHVsZXQAOkxzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkSkNvbmN1cnJlbnRNYXBXcmFwcGVyJDtMABlKRGljdGlvbmFyeVdyYXBwZXIkbW9kdWxldAA3THNjYWxhL2NvbGxlY3Rpb24vY29udmVydC9XcmFwcGVycyRKRGljdGlvbmFyeVdyYXBwZXIkO0wAGkpFbnVtZXJhdGlvbldyYXBwZXIkbW9kdWxldAA4THNjYWxhL2NvbGxlY3Rpb24vY29udmVydC9XcmFwcGVycyRKRW51bWVyYXRpb25XcmFwcGVyJDtMABdKSXRlcmFibGVXcmFwcGVyJG1vZHVsZXQANUxzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkSkl0ZXJhYmxlV3JhcHBlciQ7TAAXSkl0ZXJhdG9yV3JhcHBlciRtb2R1bGV0ADVMc2NhbGEvY29sbGVjdGlvbi9jb252ZXJ0L1dyYXBwZXJzJEpJdGVyYXRvcldyYXBwZXIkO0wAE0pMaXN0V3JhcHBlciRtb2R1bGV0ADFMc2NhbGEvY29sbGVjdGlvbi9jb252ZXJ0L1dyYXBwZXJzJEpMaXN0V3JhcHBlciQ7TAAZSlByb3BlcnRpZXNXcmFwcGVyJG1vZHVsZXQAN0xzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkSlByb3BlcnRpZXNXcmFwcGVyJDtMABJKU2V0V3JhcHBlciRtb2R1bGV0ADBMc2NhbGEvY29sbGVjdGlvbi9jb252ZXJ0L1dyYXBwZXJzJEpTZXRXcmFwcGVyJDtMABtNdXRhYmxlQnVmZmVyV3JhcHBlciRtb2R1bGV0ADlMc2NhbGEvY29sbGVjdGlvbi9jb252ZXJ0L1dyYXBwZXJzJE11dGFibGVCdWZmZXJXcmFwcGVyJDtMABhNdXRhYmxlTWFwV3JhcHBlciRtb2R1bGV0ADZMc2NhbGEvY29sbGVjdGlvbi9jb252ZXJ0L1dyYXBwZXJzJE11dGFibGVNYXBXcmFwcGVyJDtMABhNdXRhYmxlU2VxV3JhcHBlciRtb2R1bGV0ADZMc2NhbGEvY29sbGVjdGlvbi9jb252ZXJ0L1dyYXBwZXJzJE11dGFibGVTZXFXcmFwcGVyJDtMABhNdXRhYmxlU2V0V3JhcHBlciRtb2R1bGV0ADZMc2NhbGEvY29sbGVjdGlvbi9jb252ZXJ0L1dyYXBwZXJzJE11dGFibGVTZXRXcmFwcGVyJDtMABFTZXFXcmFwcGVyJG1vZHVsZXQAL0xzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkU2VxV3JhcHBlciQ7eHBwcHBwcHBwcHBwcHBwcHBwcHNyADJzY2FsYS5jb2xsZWN0aW9uLmdlbmVyaWMuRGVmYXVsdFNlcmlhbGl6YXRpb25Qcm94eQAAAAAAAAADAwABTAAHZmFjdG9yeXQAGkxzY2FsYS9jb2xsZWN0aW9uL0ZhY3Rvcnk7eHBzcgAlc2NhbGEuY29sbGVjdGlvbi5NYXBGYWN0b3J5JFRvRmFjdG9yeQAAAAAAAAADAgABTAAHZmFjdG9yeXQAHUxzY2FsYS9jb2xsZWN0aW9uL01hcEZhY3Rvcnk7eHBzcgAhc2NhbGEuY29sbGVjdGlvbi5tdXRhYmxlLkhhc2hNYXAkAAAAAAAAAAMCAAB4cHcEAAAAAHhxAH4AGw==") - check(g)(new collection.convert.Wrappers.MutableMapWrapper(mutable.Map[Int, Int](1 -> 2, 2 -> 3, 3 -> 4)))("rO0ABXNyADNzY2FsYS5jb2xsZWN0aW9uLmNvbnZlcnQuV3JhcHBlcnMkTXV0YWJsZU1hcFdyYXBwZXIAAAAAAAAAAwIAAUwACnVuZGVybHlpbmd0AB5Mc2NhbGEvY29sbGVjdGlvbi9tdXRhYmxlL01hcDt4cgAsc2NhbGEuY29sbGVjdGlvbi5jb252ZXJ0LldyYXBwZXJzJE1hcFdyYXBwZXIAAAAAAAAAAwIAAkwABiRvdXRlcnQAI0xzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnM7TAA4c2NhbGEkY29sbGVjdGlvbiRjb252ZXJ0JFdyYXBwZXJzJE1hcFdyYXBwZXIkJHVuZGVybHlpbmd0ABZMc2NhbGEvY29sbGVjdGlvbi9NYXA7eHBzcgAic2NhbGEuY29sbGVjdGlvbi5jb252ZXJ0LldyYXBwZXJzJAAAAAAAAAADAgARTAAYRGljdGlvbmFyeVdyYXBwZXIkbW9kdWxldAA2THNjYWxhL2NvbGxlY3Rpb24vY29udmVydC9XcmFwcGVycyREaWN0aW9uYXJ5V3JhcHBlciQ7TAAWSXRlcmFibGVXcmFwcGVyJG1vZHVsZXQANExzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkSXRlcmFibGVXcmFwcGVyJDtMABZJdGVyYXRvcldyYXBwZXIkbW9kdWxldAA0THNjYWxhL2NvbGxlY3Rpb24vY29udmVydC9XcmFwcGVycyRJdGVyYXRvcldyYXBwZXIkO0wAGUpDb2xsZWN0aW9uV3JhcHBlciRtb2R1bGV0ADdMc2NhbGEvY29sbGVjdGlvbi9jb252ZXJ0L1dyYXBwZXJzJEpDb2xsZWN0aW9uV3JhcHBlciQ7TAAcSkNvbmN1cnJlbnRNYXBXcmFwcGVyJG1vZHVsZXQAOkxzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkSkNvbmN1cnJlbnRNYXBXcmFwcGVyJDtMABlKRGljdGlvbmFyeVdyYXBwZXIkbW9kdWxldAA3THNjYWxhL2NvbGxlY3Rpb24vY29udmVydC9XcmFwcGVycyRKRGljdGlvbmFyeVdyYXBwZXIkO0wAGkpFbnVtZXJhdGlvbldyYXBwZXIkbW9kdWxldAA4THNjYWxhL2NvbGxlY3Rpb24vY29udmVydC9XcmFwcGVycyRKRW51bWVyYXRpb25XcmFwcGVyJDtMABdKSXRlcmFibGVXcmFwcGVyJG1vZHVsZXQANUxzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkSkl0ZXJhYmxlV3JhcHBlciQ7TAAXSkl0ZXJhdG9yV3JhcHBlciRtb2R1bGV0ADVMc2NhbGEvY29sbGVjdGlvbi9jb252ZXJ0L1dyYXBwZXJzJEpJdGVyYXRvcldyYXBwZXIkO0wAE0pMaXN0V3JhcHBlciRtb2R1bGV0ADFMc2NhbGEvY29sbGVjdGlvbi9jb252ZXJ0L1dyYXBwZXJzJEpMaXN0V3JhcHBlciQ7TAAZSlByb3BlcnRpZXNXcmFwcGVyJG1vZHVsZXQAN0xzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkSlByb3BlcnRpZXNXcmFwcGVyJDtMABJKU2V0V3JhcHBlciRtb2R1bGV0ADBMc2NhbGEvY29sbGVjdGlvbi9jb252ZXJ0L1dyYXBwZXJzJEpTZXRXcmFwcGVyJDtMABtNdXRhYmxlQnVmZmVyV3JhcHBlciRtb2R1bGV0ADlMc2NhbGEvY29sbGVjdGlvbi9jb252ZXJ0L1dyYXBwZXJzJE11dGFibGVCdWZmZXJXcmFwcGVyJDtMABhNdXRhYmxlTWFwV3JhcHBlciRtb2R1bGV0ADZMc2NhbGEvY29sbGVjdGlvbi9jb252ZXJ0L1dyYXBwZXJzJE11dGFibGVNYXBXcmFwcGVyJDtMABhNdXRhYmxlU2VxV3JhcHBlciRtb2R1bGV0ADZMc2NhbGEvY29sbGVjdGlvbi9jb252ZXJ0L1dyYXBwZXJzJE11dGFibGVTZXFXcmFwcGVyJDtMABhNdXRhYmxlU2V0V3JhcHBlciRtb2R1bGV0ADZMc2NhbGEvY29sbGVjdGlvbi9jb252ZXJ0L1dyYXBwZXJzJE11dGFibGVTZXRXcmFwcGVyJDtMABFTZXFXcmFwcGVyJG1vZHVsZXQAL0xzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkU2VxV3JhcHBlciQ7eHBwcHBwcHBwcHBwcHBwcHBwcHNyADJzY2FsYS5jb2xsZWN0aW9uLmdlbmVyaWMuRGVmYXVsdFNlcmlhbGl6YXRpb25Qcm94eQAAAAAAAAADAwABTAAHZmFjdG9yeXQAGkxzY2FsYS9jb2xsZWN0aW9uL0ZhY3Rvcnk7eHBzcgAlc2NhbGEuY29sbGVjdGlvbi5NYXBGYWN0b3J5JFRvRmFjdG9yeQAAAAAAAAADAgABTAAHZmFjdG9yeXQAHUxzY2FsYS9jb2xsZWN0aW9uL01hcEZhY3Rvcnk7eHBzcgAhc2NhbGEuY29sbGVjdGlvbi5tdXRhYmxlLkhhc2hNYXAkAAAAAAAAAAMCAAB4cHcEAAAAA3NyAAxzY2FsYS5UdXBsZTIulGZ9W5L59QIAAkwAAl8xdAASTGphdmEvbGFuZy9PYmplY3Q7TAACXzJxAH4AInhwc3IAEWphdmEubGFuZy5JbnRlZ2VyEuKgpPeBhzgCAAFJAAV2YWx1ZXhyABBqYXZhLmxhbmcuTnVtYmVyhqyVHQuU4IsCAAB4cAAAAAJzcQB+ACQAAAADc3EAfgAhc3EAfgAkAAAAAXEAfgAmc3EAfgAhcQB+ACdzcQB+ACQAAAAEeHEAfgAb") + check(g)(new collection.convert.Wrappers.MutableMapWrapper(mutable.Map[Int, Int](1 -> 2, 2 -> 3, 3 -> 4)))("rO0ABXNyADNzY2FsYS5jb2xsZWN0aW9uLmNvbnZlcnQuV3JhcHBlcnMkTXV0YWJsZU1hcFdyYXBwZXIAAAAAAAAAAwIAAUwACnVuZGVybHlpbmd0AB5Mc2NhbGEvY29sbGVjdGlvbi9tdXRhYmxlL01hcDt4cgAsc2NhbGEuY29sbGVjdGlvbi5jb252ZXJ0LldyYXBwZXJzJE1hcFdyYXBwZXIAAAAAAAAAAwIAAkwABiRvdXRlcnQAI0xzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnM7TAA4c2NhbGEkY29sbGVjdGlvbiRjb252ZXJ0JFdyYXBwZXJzJE1hcFdyYXBwZXIkJHVuZGVybHlpbmd0ABZMc2NhbGEvY29sbGVjdGlvbi9NYXA7eHBzcgAic2NhbGEuY29sbGVjdGlvbi5jb252ZXJ0LldyYXBwZXJzJAAAAAAAAAADAgARTAAYRGljdGlvbmFyeVdyYXBwZXIkbW9kdWxldAA2THNjYWxhL2NvbGxlY3Rpb24vY29udmVydC9XcmFwcGVycyREaWN0aW9uYXJ5V3JhcHBlciQ7TAAWSXRlcmFibGVXcmFwcGVyJG1vZHVsZXQANExzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkSXRlcmFibGVXcmFwcGVyJDtMABZJdGVyYXRvcldyYXBwZXIkbW9kdWxldAA0THNjYWxhL2NvbGxlY3Rpb24vY29udmVydC9XcmFwcGVycyRJdGVyYXRvcldyYXBwZXIkO0wAGUpDb2xsZWN0aW9uV3JhcHBlciRtb2R1bGV0ADdMc2NhbGEvY29sbGVjdGlvbi9jb252ZXJ0L1dyYXBwZXJzJEpDb2xsZWN0aW9uV3JhcHBlciQ7TAAcSkNvbmN1cnJlbnRNYXBXcmFwcGVyJG1vZHVsZXQAOkxzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkSkNvbmN1cnJlbnRNYXBXcmFwcGVyJDtMABlKRGljdGlvbmFyeVdyYXBwZXIkbW9kdWxldAA3THNjYWxhL2NvbGxlY3Rpb24vY29udmVydC9XcmFwcGVycyRKRGljdGlvbmFyeVdyYXBwZXIkO0wAGkpFbnVtZXJhdGlvbldyYXBwZXIkbW9kdWxldAA4THNjYWxhL2NvbGxlY3Rpb24vY29udmVydC9XcmFwcGVycyRKRW51bWVyYXRpb25XcmFwcGVyJDtMABdKSXRlcmFibGVXcmFwcGVyJG1vZHVsZXQANUxzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkSkl0ZXJhYmxlV3JhcHBlciQ7TAAXSkl0ZXJhdG9yV3JhcHBlciRtb2R1bGV0ADVMc2NhbGEvY29sbGVjdGlvbi9jb252ZXJ0L1dyYXBwZXJzJEpJdGVyYXRvcldyYXBwZXIkO0wAE0pMaXN0V3JhcHBlciRtb2R1bGV0ADFMc2NhbGEvY29sbGVjdGlvbi9jb252ZXJ0L1dyYXBwZXJzJEpMaXN0V3JhcHBlciQ7TAAZSlByb3BlcnRpZXNXcmFwcGVyJG1vZHVsZXQAN0xzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkSlByb3BlcnRpZXNXcmFwcGVyJDtMABJKU2V0V3JhcHBlciRtb2R1bGV0ADBMc2NhbGEvY29sbGVjdGlvbi9jb252ZXJ0L1dyYXBwZXJzJEpTZXRXcmFwcGVyJDtMABtNdXRhYmxlQnVmZmVyV3JhcHBlciRtb2R1bGV0ADlMc2NhbGEvY29sbGVjdGlvbi9jb252ZXJ0L1dyYXBwZXJzJE11dGFibGVCdWZmZXJXcmFwcGVyJDtMABhNdXRhYmxlTWFwV3JhcHBlciRtb2R1bGV0ADZMc2NhbGEvY29sbGVjdGlvbi9jb252ZXJ0L1dyYXBwZXJzJE11dGFibGVNYXBXcmFwcGVyJDtMABhNdXRhYmxlU2VxV3JhcHBlciRtb2R1bGV0ADZMc2NhbGEvY29sbGVjdGlvbi9jb252ZXJ0L1dyYXBwZXJzJE11dGFibGVTZXFXcmFwcGVyJDtMABhNdXRhYmxlU2V0V3JhcHBlciRtb2R1bGV0ADZMc2NhbGEvY29sbGVjdGlvbi9jb252ZXJ0L1dyYXBwZXJzJE11dGFibGVTZXRXcmFwcGVyJDtMABFTZXFXcmFwcGVyJG1vZHVsZXQAL0xzY2FsYS9jb2xsZWN0aW9uL2NvbnZlcnQvV3JhcHBlcnMkU2VxV3JhcHBlciQ7eHBwcHBwcHBwcHBwcHBwcHBwcHNyADJzY2FsYS5jb2xsZWN0aW9uLmdlbmVyaWMuRGVmYXVsdFNlcmlhbGl6YXRpb25Qcm94eQAAAAAAAAADAwABTAAHZmFjdG9yeXQAGkxzY2FsYS9jb2xsZWN0aW9uL0ZhY3Rvcnk7eHBzcgAlc2NhbGEuY29sbGVjdGlvbi5NYXBGYWN0b3J5JFRvRmFjdG9yeQAAAAAAAAADAgABTAAHZmFjdG9yeXQAHUxzY2FsYS9jb2xsZWN0aW9uL01hcEZhY3Rvcnk7eHBzcgAhc2NhbGEuY29sbGVjdGlvbi5tdXRhYmxlLkhhc2hNYXAkAAAAAAAAAAMCAAB4cHcEAAAAA3NyAAxzY2FsYS5UdXBsZTIQ3AbXDkRLhAIAAkwAAl8xdAASTGphdmEvbGFuZy9PYmplY3Q7TAACXzJxAH4AInhwc3IAEWphdmEubGFuZy5JbnRlZ2VyEuKgpPeBhzgCAAFJAAV2YWx1ZXhyABBqYXZhLmxhbmcuTnVtYmVyhqyVHQuU4IsCAAB4cAAAAAJzcQB+ACQAAAADc3EAfgAhc3EAfgAkAAAAAXEAfgAmc3EAfgAhcQB+ACdzcQB+ACQAAAAEeHEAfgAb") check(g)(immutable.BitSet(1, 2, 3))( "rO0ABXNyADRzY2FsYS5jb2xsZWN0aW9uLmltbXV0YWJsZS5CaXRTZXQkU2VyaWFsaXphdGlvblByb3h5AAAAAAAAAAMCAAB4cgAqc2NhbGEuY29sbGVjdGlvbi5CaXRTZXQkU2VyaWFsaXphdGlvblByb3h5AAAAAAAAAAMDAAB4cHcMAAAAAQAAAAAAAAAOeA==") check(g)(immutable.HashMap())( "rO0ABXNyADJzY2FsYS5jb2xsZWN0aW9uLmdlbmVyaWMuRGVmYXVsdFNlcmlhbGl6YXRpb25Qcm94eQAAAAAAAAADAwABTAAHZmFjdG9yeXQAGkxzY2FsYS9jb2xsZWN0aW9uL0ZhY3Rvcnk7eHBzcgAlc2NhbGEuY29sbGVjdGlvbi5NYXBGYWN0b3J5JFRvRmFjdG9yeQAAAAAAAAADAgABTAAHZmFjdG9yeXQAHUxzY2FsYS9jb2xsZWN0aW9uL01hcEZhY3Rvcnk7eHBzcgAjc2NhbGEuY29sbGVjdGlvbi5pbW11dGFibGUuSGFzaE1hcCQAAAAAAAAAAwMAAUwADWRlZmF1bHRNZXJnZXJ0ACtMc2NhbGEvY29sbGVjdGlvbi9pbW11dGFibGUvSGFzaE1hcCRNZXJnZXI7eHB4dwQAAAAAeA==") - check(g)(immutable.HashMap(1 -> 2))( "rO0ABXNyADJzY2FsYS5jb2xsZWN0aW9uLmdlbmVyaWMuRGVmYXVsdFNlcmlhbGl6YXRpb25Qcm94eQAAAAAAAAADAwABTAAHZmFjdG9yeXQAGkxzY2FsYS9jb2xsZWN0aW9uL0ZhY3Rvcnk7eHBzcgAlc2NhbGEuY29sbGVjdGlvbi5NYXBGYWN0b3J5JFRvRmFjdG9yeQAAAAAAAAADAgABTAAHZmFjdG9yeXQAHUxzY2FsYS9jb2xsZWN0aW9uL01hcEZhY3Rvcnk7eHBzcgAjc2NhbGEuY29sbGVjdGlvbi5pbW11dGFibGUuSGFzaE1hcCQAAAAAAAAAAwMAAUwADWRlZmF1bHRNZXJnZXJ0ACtMc2NhbGEvY29sbGVjdGlvbi9pbW11dGFibGUvSGFzaE1hcCRNZXJnZXI7eHB4dwQAAAABc3IADHNjYWxhLlR1cGxlMi6UZn1bkvn1AgACTAACXzF0ABJMamF2YS9sYW5nL09iamVjdDtMAAJfMnEAfgAKeHBzcgARamF2YS5sYW5nLkludGVnZXIS4qCk94GHOAIAAUkABXZhbHVleHIAEGphdmEubGFuZy5OdW1iZXKGrJUdC5TgiwIAAHhwAAAAAXNxAH4ADAAAAAJ4") - check(g)(immutable.HashMap(1 -> 2, 3 -> 4))( "rO0ABXNyADJzY2FsYS5jb2xsZWN0aW9uLmdlbmVyaWMuRGVmYXVsdFNlcmlhbGl6YXRpb25Qcm94eQAAAAAAAAADAwABTAAHZmFjdG9yeXQAGkxzY2FsYS9jb2xsZWN0aW9uL0ZhY3Rvcnk7eHBzcgAlc2NhbGEuY29sbGVjdGlvbi5NYXBGYWN0b3J5JFRvRmFjdG9yeQAAAAAAAAADAgABTAAHZmFjdG9yeXQAHUxzY2FsYS9jb2xsZWN0aW9uL01hcEZhY3Rvcnk7eHBzcgAjc2NhbGEuY29sbGVjdGlvbi5pbW11dGFibGUuSGFzaE1hcCQAAAAAAAAAAwMAAUwADWRlZmF1bHRNZXJnZXJ0ACtMc2NhbGEvY29sbGVjdGlvbi9pbW11dGFibGUvSGFzaE1hcCRNZXJnZXI7eHB4dwQAAAACc3IADHNjYWxhLlR1cGxlMi6UZn1bkvn1AgACTAACXzF0ABJMamF2YS9sYW5nL09iamVjdDtMAAJfMnEAfgAKeHBzcgARamF2YS5sYW5nLkludGVnZXIS4qCk94GHOAIAAUkABXZhbHVleHIAEGphdmEubGFuZy5OdW1iZXKGrJUdC5TgiwIAAHhwAAAAAXNxAH4ADAAAAAJzcQB+AAlzcQB+AAwAAAADc3EAfgAMAAAABHg=") + check(g)(immutable.HashMap(1 -> 2))( "rO0ABXNyADJzY2FsYS5jb2xsZWN0aW9uLmdlbmVyaWMuRGVmYXVsdFNlcmlhbGl6YXRpb25Qcm94eQAAAAAAAAADAwABTAAHZmFjdG9yeXQAGkxzY2FsYS9jb2xsZWN0aW9uL0ZhY3Rvcnk7eHBzcgAlc2NhbGEuY29sbGVjdGlvbi5NYXBGYWN0b3J5JFRvRmFjdG9yeQAAAAAAAAADAgABTAAHZmFjdG9yeXQAHUxzY2FsYS9jb2xsZWN0aW9uL01hcEZhY3Rvcnk7eHBzcgAjc2NhbGEuY29sbGVjdGlvbi5pbW11dGFibGUuSGFzaE1hcCQAAAAAAAAAAwMAAUwADWRlZmF1bHRNZXJnZXJ0ACtMc2NhbGEvY29sbGVjdGlvbi9pbW11dGFibGUvSGFzaE1hcCRNZXJnZXI7eHB4dwQAAAABc3IADHNjYWxhLlR1cGxlMhDcBtcOREuEAgACTAACXzF0ABJMamF2YS9sYW5nL09iamVjdDtMAAJfMnEAfgAKeHBzcgARamF2YS5sYW5nLkludGVnZXIS4qCk94GHOAIAAUkABXZhbHVleHIAEGphdmEubGFuZy5OdW1iZXKGrJUdC5TgiwIAAHhwAAAAAXNxAH4ADAAAAAJ4") + check(g)(immutable.HashMap(1 -> 2, 3 -> 4))( "rO0ABXNyADJzY2FsYS5jb2xsZWN0aW9uLmdlbmVyaWMuRGVmYXVsdFNlcmlhbGl6YXRpb25Qcm94eQAAAAAAAAADAwABTAAHZmFjdG9yeXQAGkxzY2FsYS9jb2xsZWN0aW9uL0ZhY3Rvcnk7eHBzcgAlc2NhbGEuY29sbGVjdGlvbi5NYXBGYWN0b3J5JFRvRmFjdG9yeQAAAAAAAAADAgABTAAHZmFjdG9yeXQAHUxzY2FsYS9jb2xsZWN0aW9uL01hcEZhY3Rvcnk7eHBzcgAjc2NhbGEuY29sbGVjdGlvbi5pbW11dGFibGUuSGFzaE1hcCQAAAAAAAAAAwMAAUwADWRlZmF1bHRNZXJnZXJ0ACtMc2NhbGEvY29sbGVjdGlvbi9pbW11dGFibGUvSGFzaE1hcCRNZXJnZXI7eHB4dwQAAAACc3IADHNjYWxhLlR1cGxlMhDcBtcOREuEAgACTAACXzF0ABJMamF2YS9sYW5nL09iamVjdDtMAAJfMnEAfgAKeHBzcgARamF2YS5sYW5nLkludGVnZXIS4qCk94GHOAIAAUkABXZhbHVleHIAEGphdmEubGFuZy5OdW1iZXKGrJUdC5TgiwIAAHhwAAAAAXNxAH4ADAAAAAJzcQB+AAlzcQB+AAwAAAADc3EAfgAMAAAABHg=") // TODO provoke HashMapCollision1 check(g)(immutable.HashSet())( "rO0ABXNyADJzY2FsYS5jb2xsZWN0aW9uLmdlbmVyaWMuRGVmYXVsdFNlcmlhbGl6YXRpb25Qcm94eQAAAAAAAAADAwABTAAHZmFjdG9yeXQAGkxzY2FsYS9jb2xsZWN0aW9uL0ZhY3Rvcnk7eHBzcgAqc2NhbGEuY29sbGVjdGlvbi5JdGVyYWJsZUZhY3RvcnkkVG9GYWN0b3J5AAAAAAAAAAMCAAFMAAdmYWN0b3J5dAAiTHNjYWxhL2NvbGxlY3Rpb24vSXRlcmFibGVGYWN0b3J5O3hwc3IAI3NjYWxhLmNvbGxlY3Rpb24uaW1tdXRhYmxlLkhhc2hTZXQkAAAAAAAAAAMDAAB4cHh3BAAAAAB4") @@ -157,7 +157,7 @@ object SerializationStability { check(g)(immutable.ListSet())( "rO0ABXNyADJzY2FsYS5jb2xsZWN0aW9uLmdlbmVyaWMuRGVmYXVsdFNlcmlhbGl6YXRpb25Qcm94eQAAAAAAAAADAwABTAAHZmFjdG9yeXQAGkxzY2FsYS9jb2xsZWN0aW9uL0ZhY3Rvcnk7eHBzcgAqc2NhbGEuY29sbGVjdGlvbi5JdGVyYWJsZUZhY3RvcnkkVG9GYWN0b3J5AAAAAAAAAAMCAAFMAAdmYWN0b3J5dAAiTHNjYWxhL2NvbGxlY3Rpb24vSXRlcmFibGVGYWN0b3J5O3hwc3IAI3NjYWxhLmNvbGxlY3Rpb24uaW1tdXRhYmxlLkxpc3RTZXQkAAAAAAAAAAMDAAB4cHh3BAAAAAB4") check(g)(immutable.ListSet(1))( "rO0ABXNyADJzY2FsYS5jb2xsZWN0aW9uLmdlbmVyaWMuRGVmYXVsdFNlcmlhbGl6YXRpb25Qcm94eQAAAAAAAAADAwABTAAHZmFjdG9yeXQAGkxzY2FsYS9jb2xsZWN0aW9uL0ZhY3Rvcnk7eHBzcgAqc2NhbGEuY29sbGVjdGlvbi5JdGVyYWJsZUZhY3RvcnkkVG9GYWN0b3J5AAAAAAAAAAMCAAFMAAdmYWN0b3J5dAAiTHNjYWxhL2NvbGxlY3Rpb24vSXRlcmFibGVGYWN0b3J5O3hwc3IAI3NjYWxhLmNvbGxlY3Rpb24uaW1tdXRhYmxlLkxpc3RTZXQkAAAAAAAAAAMDAAB4cHh3BP////9zcgARamF2YS5sYW5nLkludGVnZXIS4qCk94GHOAIAAUkABXZhbHVleHIAEGphdmEubGFuZy5OdW1iZXKGrJUdC5TgiwIAAHhwAAAAAXNyACZzY2FsYS5jb2xsZWN0aW9uLmdlbmVyaWMuU2VyaWFsaXplRW5kJAAAAAAAAAADAgAAeHB4") check(g)(immutable.ListMap())( "rO0ABXNyADJzY2FsYS5jb2xsZWN0aW9uLmdlbmVyaWMuRGVmYXVsdFNlcmlhbGl6YXRpb25Qcm94eQAAAAAAAAADAwABTAAHZmFjdG9yeXQAGkxzY2FsYS9jb2xsZWN0aW9uL0ZhY3Rvcnk7eHBzcgAlc2NhbGEuY29sbGVjdGlvbi5NYXBGYWN0b3J5JFRvRmFjdG9yeQAAAAAAAAADAgABTAAHZmFjdG9yeXQAHUxzY2FsYS9jb2xsZWN0aW9uL01hcEZhY3Rvcnk7eHBzcgAjc2NhbGEuY29sbGVjdGlvbi5pbW11dGFibGUuTGlzdE1hcCQAAAAAAAAAAwMAAHhweHcEAAAAAHg=") - check(g)(immutable.ListMap(1 -> 2))( "rO0ABXNyADJzY2FsYS5jb2xsZWN0aW9uLmdlbmVyaWMuRGVmYXVsdFNlcmlhbGl6YXRpb25Qcm94eQAAAAAAAAADAwABTAAHZmFjdG9yeXQAGkxzY2FsYS9jb2xsZWN0aW9uL0ZhY3Rvcnk7eHBzcgAlc2NhbGEuY29sbGVjdGlvbi5NYXBGYWN0b3J5JFRvRmFjdG9yeQAAAAAAAAADAgABTAAHZmFjdG9yeXQAHUxzY2FsYS9jb2xsZWN0aW9uL01hcEZhY3Rvcnk7eHBzcgAjc2NhbGEuY29sbGVjdGlvbi5pbW11dGFibGUuTGlzdE1hcCQAAAAAAAAAAwMAAHhweHcE/////3NyAAxzY2FsYS5UdXBsZTIulGZ9W5L59QIAAkwAAl8xdAASTGphdmEvbGFuZy9PYmplY3Q7TAACXzJxAH4ACXhwc3IAEWphdmEubGFuZy5JbnRlZ2VyEuKgpPeBhzgCAAFJAAV2YWx1ZXhyABBqYXZhLmxhbmcuTnVtYmVyhqyVHQuU4IsCAAB4cAAAAAFzcQB+AAsAAAACc3IAJnNjYWxhLmNvbGxlY3Rpb24uZ2VuZXJpYy5TZXJpYWxpemVFbmQkAAAAAAAAAAMCAAB4cHg=") + check(g)(immutable.ListMap(1 -> 2))( "rO0ABXNyADJzY2FsYS5jb2xsZWN0aW9uLmdlbmVyaWMuRGVmYXVsdFNlcmlhbGl6YXRpb25Qcm94eQAAAAAAAAADAwABTAAHZmFjdG9yeXQAGkxzY2FsYS9jb2xsZWN0aW9uL0ZhY3Rvcnk7eHBzcgAlc2NhbGEuY29sbGVjdGlvbi5NYXBGYWN0b3J5JFRvRmFjdG9yeQAAAAAAAAADAgABTAAHZmFjdG9yeXQAHUxzY2FsYS9jb2xsZWN0aW9uL01hcEZhY3Rvcnk7eHBzcgAjc2NhbGEuY29sbGVjdGlvbi5pbW11dGFibGUuTGlzdE1hcCQAAAAAAAAAAwMAAHhweHcE/////3NyAAxzY2FsYS5UdXBsZTIQ3AbXDkRLhAIAAkwAAl8xdAASTGphdmEvbGFuZy9PYmplY3Q7TAACXzJxAH4ACXhwc3IAEWphdmEubGFuZy5JbnRlZ2VyEuKgpPeBhzgCAAFJAAV2YWx1ZXhyABBqYXZhLmxhbmcuTnVtYmVyhqyVHQuU4IsCAAB4cAAAAAFzcQB+AAsAAAACc3IAJnNjYWxhLmNvbGxlY3Rpb24uZ2VuZXJpYy5TZXJpYWxpemVFbmQkAAAAAAAAAAMCAAB4cHg=") //check(g)(immutable.Queue())( "rO0ABXNyACBzY2FsYS5jb2xsZWN0aW9uLmltbXV0YWJsZS5RdWV1ZZY146W3qSuhAgACTAACaW50ACFMc2NhbGEvY29sbGVjdGlvbi9pbW11dGFibGUvTGlzdDtMAANvdXRxAH4AAXhwc3IAMnNjYWxhLmNvbGxlY3Rpb24uaW1tdXRhYmxlLkxpc3QkU2VyaWFsaXphdGlvblByb3h5AAAAAAAAAAEDAAB4cHNyACxzY2FsYS5jb2xsZWN0aW9uLmltbXV0YWJsZS5MaXN0U2VyaWFsaXplRW5kJIpcY1v3UwttAgAAeHB4cQB+AAQ=") //check(g)(immutable.Queue(1, 2, 3))( "rO0ABXNyACBzY2FsYS5jb2xsZWN0aW9uLmltbXV0YWJsZS5RdWV1ZZY146W3qSuhAgACTAACaW50ACFMc2NhbGEvY29sbGVjdGlvbi9pbW11dGFibGUvTGlzdDtMAANvdXRxAH4AAXhwc3IAMnNjYWxhLmNvbGxlY3Rpb24uaW1tdXRhYmxlLkxpc3QkU2VyaWFsaXphdGlvblByb3h5AAAAAAAAAAEDAAB4cHNyACxzY2FsYS5jb2xsZWN0aW9uLmltbXV0YWJsZS5MaXN0U2VyaWFsaXplRW5kJIpcY1v3UwttAgAAeHB4c3EAfgADc3IAEWphdmEubGFuZy5JbnRlZ2VyEuKgpPeBhzgCAAFJAAV2YWx1ZXhyABBqYXZhLmxhbmcuTnVtYmVyhqyVHQuU4IsCAAB4cAAAAAFzcQB+AAgAAAACc3EAfgAIAAAAA3EAfgAGeA==") @@ -172,11 +172,11 @@ object SerializationStability { check(g)(immutable.Set(1, 2, 3, 4, 5))( "rO0ABXNyADJzY2FsYS5jb2xsZWN0aW9uLmdlbmVyaWMuRGVmYXVsdFNlcmlhbGl6YXRpb25Qcm94eQAAAAAAAAADAwABTAAHZmFjdG9yeXQAGkxzY2FsYS9jb2xsZWN0aW9uL0ZhY3Rvcnk7eHBzcgAqc2NhbGEuY29sbGVjdGlvbi5JdGVyYWJsZUZhY3RvcnkkVG9GYWN0b3J5AAAAAAAAAAMCAAFMAAdmYWN0b3J5dAAiTHNjYWxhL2NvbGxlY3Rpb24vSXRlcmFibGVGYWN0b3J5O3hwc3IAKHNjYWxhLmNvbGxlY3Rpb24uaW1tdXRhYmxlLkNoYW1wSGFzaFNldCQAAAAAAAAAAwMAAUwACEVtcHR5U2V0dAApTHNjYWxhL2NvbGxlY3Rpb24vaW1tdXRhYmxlL0NoYW1wSGFzaFNldDt4cHh3BAAAAAVzcgARamF2YS5sYW5nLkludGVnZXIS4qCk94GHOAIAAUkABXZhbHVleHIAEGphdmEubGFuZy5OdW1iZXKGrJUdC5TgiwIAAHhwAAAABXNxAH4ACQAAAAFzcQB+AAkAAAACc3EAfgAJAAAAA3NxAH4ACQAAAAR4") check(g)(immutable.Map())( "rO0ABXNyADJzY2FsYS5jb2xsZWN0aW9uLmdlbmVyaWMuRGVmYXVsdFNlcmlhbGl6YXRpb25Qcm94eQAAAAAAAAADAwABTAAHZmFjdG9yeXQAGkxzY2FsYS9jb2xsZWN0aW9uL0ZhY3Rvcnk7eHBzcgAlc2NhbGEuY29sbGVjdGlvbi5NYXBGYWN0b3J5JFRvRmFjdG9yeQAAAAAAAAADAgABTAAHZmFjdG9yeXQAHUxzY2FsYS9jb2xsZWN0aW9uL01hcEZhY3Rvcnk7eHBzcgAfc2NhbGEuY29sbGVjdGlvbi5pbW11dGFibGUuTWFwJAAAAAAAAAADAwABWgArc2NhbGEkY29sbGVjdGlvbiRpbW11dGFibGUkTWFwJCR1c2VCYXNlbGluZXhweHcEAAAAAHg=") - check(g)(immutable.Map(1 -> 2))( "rO0ABXNyADJzY2FsYS5jb2xsZWN0aW9uLmdlbmVyaWMuRGVmYXVsdFNlcmlhbGl6YXRpb25Qcm94eQAAAAAAAAADAwABTAAHZmFjdG9yeXQAGkxzY2FsYS9jb2xsZWN0aW9uL0ZhY3Rvcnk7eHBzcgAlc2NhbGEuY29sbGVjdGlvbi5NYXBGYWN0b3J5JFRvRmFjdG9yeQAAAAAAAAADAgABTAAHZmFjdG9yeXQAHUxzY2FsYS9jb2xsZWN0aW9uL01hcEZhY3Rvcnk7eHBzcgAfc2NhbGEuY29sbGVjdGlvbi5pbW11dGFibGUuTWFwJAAAAAAAAAADAwABWgArc2NhbGEkY29sbGVjdGlvbiRpbW11dGFibGUkTWFwJCR1c2VCYXNlbGluZXhweHcEAAAAAXNyAAxzY2FsYS5UdXBsZTIulGZ9W5L59QIAAkwAAl8xdAASTGphdmEvbGFuZy9PYmplY3Q7TAACXzJxAH4ACXhwc3IAEWphdmEubGFuZy5JbnRlZ2VyEuKgpPeBhzgCAAFJAAV2YWx1ZXhyABBqYXZhLmxhbmcuTnVtYmVyhqyVHQuU4IsCAAB4cAAAAAFzcQB+AAsAAAACeA==") - check(g)(immutable.Map(1 -> 2, 2 -> 3))( "rO0ABXNyADJzY2FsYS5jb2xsZWN0aW9uLmdlbmVyaWMuRGVmYXVsdFNlcmlhbGl6YXRpb25Qcm94eQAAAAAAAAADAwABTAAHZmFjdG9yeXQAGkxzY2FsYS9jb2xsZWN0aW9uL0ZhY3Rvcnk7eHBzcgAlc2NhbGEuY29sbGVjdGlvbi5NYXBGYWN0b3J5JFRvRmFjdG9yeQAAAAAAAAADAgABTAAHZmFjdG9yeXQAHUxzY2FsYS9jb2xsZWN0aW9uL01hcEZhY3Rvcnk7eHBzcgAfc2NhbGEuY29sbGVjdGlvbi5pbW11dGFibGUuTWFwJAAAAAAAAAADAwABWgArc2NhbGEkY29sbGVjdGlvbiRpbW11dGFibGUkTWFwJCR1c2VCYXNlbGluZXhweHcEAAAAAnNyAAxzY2FsYS5UdXBsZTIulGZ9W5L59QIAAkwAAl8xdAASTGphdmEvbGFuZy9PYmplY3Q7TAACXzJxAH4ACXhwc3IAEWphdmEubGFuZy5JbnRlZ2VyEuKgpPeBhzgCAAFJAAV2YWx1ZXhyABBqYXZhLmxhbmcuTnVtYmVyhqyVHQuU4IsCAAB4cAAAAAFzcQB+AAsAAAACc3EAfgAIcQB+AA5zcQB+AAsAAAADeA==") - check(g)(immutable.Map(1 -> 2, 2 -> 3, 3 -> 4))( "rO0ABXNyADJzY2FsYS5jb2xsZWN0aW9uLmdlbmVyaWMuRGVmYXVsdFNlcmlhbGl6YXRpb25Qcm94eQAAAAAAAAADAwABTAAHZmFjdG9yeXQAGkxzY2FsYS9jb2xsZWN0aW9uL0ZhY3Rvcnk7eHBzcgAlc2NhbGEuY29sbGVjdGlvbi5NYXBGYWN0b3J5JFRvRmFjdG9yeQAAAAAAAAADAgABTAAHZmFjdG9yeXQAHUxzY2FsYS9jb2xsZWN0aW9uL01hcEZhY3Rvcnk7eHBzcgAfc2NhbGEuY29sbGVjdGlvbi5pbW11dGFibGUuTWFwJAAAAAAAAAADAwABWgArc2NhbGEkY29sbGVjdGlvbiRpbW11dGFibGUkTWFwJCR1c2VCYXNlbGluZXhweHcEAAAAA3NyAAxzY2FsYS5UdXBsZTIulGZ9W5L59QIAAkwAAl8xdAASTGphdmEvbGFuZy9PYmplY3Q7TAACXzJxAH4ACXhwc3IAEWphdmEubGFuZy5JbnRlZ2VyEuKgpPeBhzgCAAFJAAV2YWx1ZXhyABBqYXZhLmxhbmcuTnVtYmVyhqyVHQuU4IsCAAB4cAAAAAFzcQB+AAsAAAACc3EAfgAIcQB+AA5zcQB+AAsAAAADc3EAfgAIcQB+ABBzcQB+AAsAAAAEeA==") - check(g)(immutable.Map(1 -> 2, 2 -> 3, 3 -> 4, 4 -> 5))( "rO0ABXNyADJzY2FsYS5jb2xsZWN0aW9uLmdlbmVyaWMuRGVmYXVsdFNlcmlhbGl6YXRpb25Qcm94eQAAAAAAAAADAwABTAAHZmFjdG9yeXQAGkxzY2FsYS9jb2xsZWN0aW9uL0ZhY3Rvcnk7eHBzcgAlc2NhbGEuY29sbGVjdGlvbi5NYXBGYWN0b3J5JFRvRmFjdG9yeQAAAAAAAAADAgABTAAHZmFjdG9yeXQAHUxzY2FsYS9jb2xsZWN0aW9uL01hcEZhY3Rvcnk7eHBzcgAfc2NhbGEuY29sbGVjdGlvbi5pbW11dGFibGUuTWFwJAAAAAAAAAADAwABWgArc2NhbGEkY29sbGVjdGlvbiRpbW11dGFibGUkTWFwJCR1c2VCYXNlbGluZXhweHcEAAAABHNyAAxzY2FsYS5UdXBsZTIulGZ9W5L59QIAAkwAAl8xdAASTGphdmEvbGFuZy9PYmplY3Q7TAACXzJxAH4ACXhwc3IAEWphdmEubGFuZy5JbnRlZ2VyEuKgpPeBhzgCAAFJAAV2YWx1ZXhyABBqYXZhLmxhbmcuTnVtYmVyhqyVHQuU4IsCAAB4cAAAAAFzcQB+AAsAAAACc3EAfgAIcQB+AA5zcQB+AAsAAAADc3EAfgAIcQB+ABBzcQB+AAsAAAAEc3EAfgAIcQB+ABJzcQB+AAsAAAAFeA==") - check(g)(immutable.Map(1 -> 2, 2 -> 3, 3 -> 4, 4 -> 5, 5 -> 6))( "rO0ABXNyADJzY2FsYS5jb2xsZWN0aW9uLmdlbmVyaWMuRGVmYXVsdFNlcmlhbGl6YXRpb25Qcm94eQAAAAAAAAADAwABTAAHZmFjdG9yeXQAGkxzY2FsYS9jb2xsZWN0aW9uL0ZhY3Rvcnk7eHBzcgAlc2NhbGEuY29sbGVjdGlvbi5NYXBGYWN0b3J5JFRvRmFjdG9yeQAAAAAAAAADAgABTAAHZmFjdG9yeXQAHUxzY2FsYS9jb2xsZWN0aW9uL01hcEZhY3Rvcnk7eHBzcgAoc2NhbGEuY29sbGVjdGlvbi5pbW11dGFibGUuQ2hhbXBIYXNoTWFwJAAAAAAAAAADAwABTAAIRW1wdHlNYXB0AClMc2NhbGEvY29sbGVjdGlvbi9pbW11dGFibGUvQ2hhbXBIYXNoTWFwO3hweHcEAAAABXNyAAxzY2FsYS5UdXBsZTIulGZ9W5L59QIAAkwAAl8xdAASTGphdmEvbGFuZy9PYmplY3Q7TAACXzJxAH4ACnhwc3IAEWphdmEubGFuZy5JbnRlZ2VyEuKgpPeBhzgCAAFJAAV2YWx1ZXhyABBqYXZhLmxhbmcuTnVtYmVyhqyVHQuU4IsCAAB4cAAAAAVzcQB+AAwAAAAGc3EAfgAJc3EAfgAMAAAAAXNxAH4ADAAAAAJzcQB+AAlxAH4AEnNxAH4ADAAAAANzcQB+AAlxAH4AFHNxAH4ADAAAAARzcQB+AAlxAH4AFnEAfgAOeA==") + check(g)(immutable.Map(1 -> 2))( "rO0ABXNyADJzY2FsYS5jb2xsZWN0aW9uLmdlbmVyaWMuRGVmYXVsdFNlcmlhbGl6YXRpb25Qcm94eQAAAAAAAAADAwABTAAHZmFjdG9yeXQAGkxzY2FsYS9jb2xsZWN0aW9uL0ZhY3Rvcnk7eHBzcgAlc2NhbGEuY29sbGVjdGlvbi5NYXBGYWN0b3J5JFRvRmFjdG9yeQAAAAAAAAADAgABTAAHZmFjdG9yeXQAHUxzY2FsYS9jb2xsZWN0aW9uL01hcEZhY3Rvcnk7eHBzcgAfc2NhbGEuY29sbGVjdGlvbi5pbW11dGFibGUuTWFwJAAAAAAAAAADAwABWgArc2NhbGEkY29sbGVjdGlvbiRpbW11dGFibGUkTWFwJCR1c2VCYXNlbGluZXhweHcEAAAAAXNyAAxzY2FsYS5UdXBsZTIQ3AbXDkRLhAIAAkwAAl8xdAASTGphdmEvbGFuZy9PYmplY3Q7TAACXzJxAH4ACXhwc3IAEWphdmEubGFuZy5JbnRlZ2VyEuKgpPeBhzgCAAFJAAV2YWx1ZXhyABBqYXZhLmxhbmcuTnVtYmVyhqyVHQuU4IsCAAB4cAAAAAFzcQB+AAsAAAACeA==") + check(g)(immutable.Map(1 -> 2, 2 -> 3))( "rO0ABXNyADJzY2FsYS5jb2xsZWN0aW9uLmdlbmVyaWMuRGVmYXVsdFNlcmlhbGl6YXRpb25Qcm94eQAAAAAAAAADAwABTAAHZmFjdG9yeXQAGkxzY2FsYS9jb2xsZWN0aW9uL0ZhY3Rvcnk7eHBzcgAlc2NhbGEuY29sbGVjdGlvbi5NYXBGYWN0b3J5JFRvRmFjdG9yeQAAAAAAAAADAgABTAAHZmFjdG9yeXQAHUxzY2FsYS9jb2xsZWN0aW9uL01hcEZhY3Rvcnk7eHBzcgAfc2NhbGEuY29sbGVjdGlvbi5pbW11dGFibGUuTWFwJAAAAAAAAAADAwABWgArc2NhbGEkY29sbGVjdGlvbiRpbW11dGFibGUkTWFwJCR1c2VCYXNlbGluZXhweHcEAAAAAnNyAAxzY2FsYS5UdXBsZTIQ3AbXDkRLhAIAAkwAAl8xdAASTGphdmEvbGFuZy9PYmplY3Q7TAACXzJxAH4ACXhwc3IAEWphdmEubGFuZy5JbnRlZ2VyEuKgpPeBhzgCAAFJAAV2YWx1ZXhyABBqYXZhLmxhbmcuTnVtYmVyhqyVHQuU4IsCAAB4cAAAAAFzcQB+AAsAAAACc3EAfgAIcQB+AA5zcQB+AAsAAAADeA==") + check(g)(immutable.Map(1 -> 2, 2 -> 3, 3 -> 4))( "rO0ABXNyADJzY2FsYS5jb2xsZWN0aW9uLmdlbmVyaWMuRGVmYXVsdFNlcmlhbGl6YXRpb25Qcm94eQAAAAAAAAADAwABTAAHZmFjdG9yeXQAGkxzY2FsYS9jb2xsZWN0aW9uL0ZhY3Rvcnk7eHBzcgAlc2NhbGEuY29sbGVjdGlvbi5NYXBGYWN0b3J5JFRvRmFjdG9yeQAAAAAAAAADAgABTAAHZmFjdG9yeXQAHUxzY2FsYS9jb2xsZWN0aW9uL01hcEZhY3Rvcnk7eHBzcgAfc2NhbGEuY29sbGVjdGlvbi5pbW11dGFibGUuTWFwJAAAAAAAAAADAwABWgArc2NhbGEkY29sbGVjdGlvbiRpbW11dGFibGUkTWFwJCR1c2VCYXNlbGluZXhweHcEAAAAA3NyAAxzY2FsYS5UdXBsZTIQ3AbXDkRLhAIAAkwAAl8xdAASTGphdmEvbGFuZy9PYmplY3Q7TAACXzJxAH4ACXhwc3IAEWphdmEubGFuZy5JbnRlZ2VyEuKgpPeBhzgCAAFJAAV2YWx1ZXhyABBqYXZhLmxhbmcuTnVtYmVyhqyVHQuU4IsCAAB4cAAAAAFzcQB+AAsAAAACc3EAfgAIcQB+AA5zcQB+AAsAAAADc3EAfgAIcQB+ABBzcQB+AAsAAAAEeA==") + check(g)(immutable.Map(1 -> 2, 2 -> 3, 3 -> 4, 4 -> 5))( "rO0ABXNyADJzY2FsYS5jb2xsZWN0aW9uLmdlbmVyaWMuRGVmYXVsdFNlcmlhbGl6YXRpb25Qcm94eQAAAAAAAAADAwABTAAHZmFjdG9yeXQAGkxzY2FsYS9jb2xsZWN0aW9uL0ZhY3Rvcnk7eHBzcgAlc2NhbGEuY29sbGVjdGlvbi5NYXBGYWN0b3J5JFRvRmFjdG9yeQAAAAAAAAADAgABTAAHZmFjdG9yeXQAHUxzY2FsYS9jb2xsZWN0aW9uL01hcEZhY3Rvcnk7eHBzcgAfc2NhbGEuY29sbGVjdGlvbi5pbW11dGFibGUuTWFwJAAAAAAAAAADAwABWgArc2NhbGEkY29sbGVjdGlvbiRpbW11dGFibGUkTWFwJCR1c2VCYXNlbGluZXhweHcEAAAABHNyAAxzY2FsYS5UdXBsZTIQ3AbXDkRLhAIAAkwAAl8xdAASTGphdmEvbGFuZy9PYmplY3Q7TAACXzJxAH4ACXhwc3IAEWphdmEubGFuZy5JbnRlZ2VyEuKgpPeBhzgCAAFJAAV2YWx1ZXhyABBqYXZhLmxhbmcuTnVtYmVyhqyVHQuU4IsCAAB4cAAAAAFzcQB+AAsAAAACc3EAfgAIcQB+AA5zcQB+AAsAAAADc3EAfgAIcQB+ABBzcQB+AAsAAAAEc3EAfgAIcQB+ABJzcQB+AAsAAAAFeA==") + check(g)(immutable.Map(1 -> 2, 2 -> 3, 3 -> 4, 4 -> 5, 5 -> 6))( "rO0ABXNyADJzY2FsYS5jb2xsZWN0aW9uLmdlbmVyaWMuRGVmYXVsdFNlcmlhbGl6YXRpb25Qcm94eQAAAAAAAAADAwABTAAHZmFjdG9yeXQAGkxzY2FsYS9jb2xsZWN0aW9uL0ZhY3Rvcnk7eHBzcgAlc2NhbGEuY29sbGVjdGlvbi5NYXBGYWN0b3J5JFRvRmFjdG9yeQAAAAAAAAADAgABTAAHZmFjdG9yeXQAHUxzY2FsYS9jb2xsZWN0aW9uL01hcEZhY3Rvcnk7eHBzcgAoc2NhbGEuY29sbGVjdGlvbi5pbW11dGFibGUuQ2hhbXBIYXNoTWFwJAAAAAAAAAADAwABTAAIRW1wdHlNYXB0AClMc2NhbGEvY29sbGVjdGlvbi9pbW11dGFibGUvQ2hhbXBIYXNoTWFwO3hweHcEAAAABXNyAAxzY2FsYS5UdXBsZTIQ3AbXDkRLhAIAAkwAAl8xdAASTGphdmEvbGFuZy9PYmplY3Q7TAACXzJxAH4ACnhwc3IAEWphdmEubGFuZy5JbnRlZ2VyEuKgpPeBhzgCAAFJAAV2YWx1ZXhyABBqYXZhLmxhbmcuTnVtYmVyhqyVHQuU4IsCAAB4cAAAAAVzcQB+AAwAAAAGc3EAfgAJc3EAfgAMAAAAAXNxAH4ADAAAAAJzcQB+AAlxAH4AEnNxAH4ADAAAAANzcQB+AAlxAH4AFHNxAH4ADAAAAARzcQB+AAlxAH4AFnEAfgAOeA==") //check(g)(immutable.Stack(1, 2, 3))( "rO0ABXNyACBzY2FsYS5jb2xsZWN0aW9uLmltbXV0YWJsZS5TdGFjaxtt3qEbMvq+AgABTAAFZWxlbXN0ACFMc2NhbGEvY29sbGVjdGlvbi9pbW11dGFibGUvTGlzdDt4cHNyADJzY2FsYS5jb2xsZWN0aW9uLmltbXV0YWJsZS5MaXN0JFNlcmlhbGl6YXRpb25Qcm94eQAAAAAAAAABAwAAeHBzcgARamF2YS5sYW5nLkludGVnZXIS4qCk94GHOAIAAUkABXZhbHVleHIAEGphdmEubGFuZy5OdW1iZXKGrJUdC5TgiwIAAHhwAAAAAXNxAH4ABQAAAAJzcQB+AAUAAAADc3IALHNjYWxhLmNvbGxlY3Rpb24uaW1tdXRhYmxlLkxpc3RTZXJpYWxpemVFbmQkilxjW/dTC20CAAB4cHg=") @@ -192,22 +192,22 @@ object SerializationStability { // check(g)(mutable.ArrayBuffer(1, 2, 3))( "rO0ABXNyACRzY2FsYS5jb2xsZWN0aW9uLm11dGFibGUuQXJyYXlCdWZmZXIVOLBTg4KOcwIAA0kAC2luaXRpYWxTaXplSQAFc2l6ZTBbAAVhcnJheXQAE1tMamF2YS9sYW5nL09iamVjdDt4cAAAABAAAAADdXIAE1tMamF2YS5sYW5nLk9iamVjdDuQzlifEHMpbAIAAHhwAAAAEHNyABFqYXZhLmxhbmcuSW50ZWdlchLioKT3gYc4AgABSQAFdmFsdWV4cgAQamF2YS5sYW5nLk51bWJlcoaslR0LlOCLAgAAeHAAAAABc3EAfgAFAAAAAnNxAH4ABQAAAANwcHBwcHBwcHBwcHBw") // TODO scala/bug#8576 Uninitialized field under -Xcheckinit // check(g)(mutable.ArraySeq(1, 2, 3))( "rO0ABXNyACFzY2FsYS5jb2xsZWN0aW9uLm11dGFibGUuQXJyYXlTZXEVPD3SKEkOcwIAAkkABmxlbmd0aFsABWFycmF5dAATW0xqYXZhL2xhbmcvT2JqZWN0O3hwAAAAA3VyABNbTGphdmEubGFuZy5PYmplY3Q7kM5YnxBzKWwCAAB4cAAAAANzcgARamF2YS5sYW5nLkludGVnZXIS4qCk94GHOAIAAUkABXZhbHVleHIAEGphdmEubGFuZy5OdW1iZXKGrJUdC5TgiwIAAHhwAAAAAXNxAH4ABQAAAAJzcQB+AAUAAAAD") - check(g)(mutable.AnyRefMap("a" -> "A"))( "rO0ABXNyADJzY2FsYS5jb2xsZWN0aW9uLmdlbmVyaWMuRGVmYXVsdFNlcmlhbGl6YXRpb25Qcm94eQAAAAAAAAADAwABTAAHZmFjdG9yeXQAGkxzY2FsYS9jb2xsZWN0aW9uL0ZhY3Rvcnk7eHBzcgAtc2NhbGEuY29sbGVjdGlvbi5tdXRhYmxlLkFueVJlZk1hcCRUb0ZhY3RvcnkkAAAAAAAAAAMCAAB4cHcEAAAAAXNyAAxzY2FsYS5UdXBsZTIulGZ9W5L59QIAAkwAAl8xdAASTGphdmEvbGFuZy9PYmplY3Q7TAACXzJxAH4ABnhwdAABYXQAAUF4") + check(g)(mutable.AnyRefMap("a" -> "A"))( "rO0ABXNyADJzY2FsYS5jb2xsZWN0aW9uLmdlbmVyaWMuRGVmYXVsdFNlcmlhbGl6YXRpb25Qcm94eQAAAAAAAAADAwABTAAHZmFjdG9yeXQAGkxzY2FsYS9jb2xsZWN0aW9uL0ZhY3Rvcnk7eHBzcgAtc2NhbGEuY29sbGVjdGlvbi5tdXRhYmxlLkFueVJlZk1hcCRUb0ZhY3RvcnkkAAAAAAAAAAMCAAB4cHcEAAAAAXNyAAxzY2FsYS5UdXBsZTIQ3AbXDkRLhAIAAkwAAl8xdAASTGphdmEvbGFuZy9PYmplY3Q7TAACXzJxAH4ABnhwdAABYXQAAUF4") //check(g)(mutable.ArrayStack(1, 2, 3))( "rO0ABXNyACNzY2FsYS5jb2xsZWN0aW9uLm11dGFibGUuQXJyYXlTdGFja3bdxXbcnLBeAgACSQAqc2NhbGEkY29sbGVjdGlvbiRtdXRhYmxlJEFycmF5U3RhY2skJGluZGV4WwAqc2NhbGEkY29sbGVjdGlvbiRtdXRhYmxlJEFycmF5U3RhY2skJHRhYmxldAATW0xqYXZhL2xhbmcvT2JqZWN0O3hwAAAAA3VyABNbTGphdmEubGFuZy5PYmplY3Q7kM5YnxBzKWwCAAB4cAAAAANzcgARamF2YS5sYW5nLkludGVnZXIS4qCk94GHOAIAAUkABXZhbHVleHIAEGphdmEubGFuZy5OdW1iZXKGrJUdC5TgiwIAAHhwAAAAA3NxAH4ABQAAAAJzcQB+AAUAAAAB") //check(g)(mutable.DoubleLinkedList(1, 2, 3))( "rO0ABXNyAClzY2FsYS5jb2xsZWN0aW9uLm11dGFibGUuRG91YmxlTGlua2VkTGlzdI73LKsKRr1RAgADTAAEZWxlbXQAEkxqYXZhL2xhbmcvT2JqZWN0O0wABG5leHR0ACtMc2NhbGEvY29sbGVjdGlvbi9tdXRhYmxlL0RvdWJsZUxpbmtlZExpc3Q7TAAEcHJldnEAfgACeHBzcgARamF2YS5sYW5nLkludGVnZXIS4qCk94GHOAIAAUkABXZhbHVleHIAEGphdmEubGFuZy5OdW1iZXKGrJUdC5TgiwIAAHhwAAAAAXNxAH4AAHNxAH4ABAAAAAJzcQB+AABzcQB+AAQAAAADc3EAfgAAcHEAfgALcQB+AAlxAH4AB3EAfgADcA==") check(g)(mutable.HashMap())( "rO0ABXNyADJzY2FsYS5jb2xsZWN0aW9uLmdlbmVyaWMuRGVmYXVsdFNlcmlhbGl6YXRpb25Qcm94eQAAAAAAAAADAwABTAAHZmFjdG9yeXQAGkxzY2FsYS9jb2xsZWN0aW9uL0ZhY3Rvcnk7eHBzcgAlc2NhbGEuY29sbGVjdGlvbi5NYXBGYWN0b3J5JFRvRmFjdG9yeQAAAAAAAAADAgABTAAHZmFjdG9yeXQAHUxzY2FsYS9jb2xsZWN0aW9uL01hcEZhY3Rvcnk7eHBzcgAhc2NhbGEuY29sbGVjdGlvbi5tdXRhYmxlLkhhc2hNYXAkAAAAAAAAAAMCAAB4cHcEAAAAAHg=") - check(g)(mutable.HashMap(1 -> 1))( "rO0ABXNyADJzY2FsYS5jb2xsZWN0aW9uLmdlbmVyaWMuRGVmYXVsdFNlcmlhbGl6YXRpb25Qcm94eQAAAAAAAAADAwABTAAHZmFjdG9yeXQAGkxzY2FsYS9jb2xsZWN0aW9uL0ZhY3Rvcnk7eHBzcgAlc2NhbGEuY29sbGVjdGlvbi5NYXBGYWN0b3J5JFRvRmFjdG9yeQAAAAAAAAADAgABTAAHZmFjdG9yeXQAHUxzY2FsYS9jb2xsZWN0aW9uL01hcEZhY3Rvcnk7eHBzcgAhc2NhbGEuY29sbGVjdGlvbi5tdXRhYmxlLkhhc2hNYXAkAAAAAAAAAAMCAAB4cHcEAAAAAXNyAAxzY2FsYS5UdXBsZTIulGZ9W5L59QIAAkwAAl8xdAASTGphdmEvbGFuZy9PYmplY3Q7TAACXzJxAH4ACXhwc3IAEWphdmEubGFuZy5JbnRlZ2VyEuKgpPeBhzgCAAFJAAV2YWx1ZXhyABBqYXZhLmxhbmcuTnVtYmVyhqyVHQuU4IsCAAB4cAAAAAFxAH4ADXg=") + check(g)(mutable.HashMap(1 -> 1))( "rO0ABXNyADJzY2FsYS5jb2xsZWN0aW9uLmdlbmVyaWMuRGVmYXVsdFNlcmlhbGl6YXRpb25Qcm94eQAAAAAAAAADAwABTAAHZmFjdG9yeXQAGkxzY2FsYS9jb2xsZWN0aW9uL0ZhY3Rvcnk7eHBzcgAlc2NhbGEuY29sbGVjdGlvbi5NYXBGYWN0b3J5JFRvRmFjdG9yeQAAAAAAAAADAgABTAAHZmFjdG9yeXQAHUxzY2FsYS9jb2xsZWN0aW9uL01hcEZhY3Rvcnk7eHBzcgAhc2NhbGEuY29sbGVjdGlvbi5tdXRhYmxlLkhhc2hNYXAkAAAAAAAAAAMCAAB4cHcEAAAAAXNyAAxzY2FsYS5UdXBsZTIQ3AbXDkRLhAIAAkwAAl8xdAASTGphdmEvbGFuZy9PYmplY3Q7TAACXzJxAH4ACXhwc3IAEWphdmEubGFuZy5JbnRlZ2VyEuKgpPeBhzgCAAFJAAV2YWx1ZXhyABBqYXZhLmxhbmcuTnVtYmVyhqyVHQuU4IsCAAB4cAAAAAFxAH4ADXg=") check(g)(mutable.HashSet(1, 2, 3))( "rO0ABXNyADJzY2FsYS5jb2xsZWN0aW9uLmdlbmVyaWMuRGVmYXVsdFNlcmlhbGl6YXRpb25Qcm94eQAAAAAAAAADAwABTAAHZmFjdG9yeXQAGkxzY2FsYS9jb2xsZWN0aW9uL0ZhY3Rvcnk7eHBzcgAqc2NhbGEuY29sbGVjdGlvbi5JdGVyYWJsZUZhY3RvcnkkVG9GYWN0b3J5AAAAAAAAAAMCAAFMAAdmYWN0b3J5dAAiTHNjYWxhL2NvbGxlY3Rpb24vSXRlcmFibGVGYWN0b3J5O3hwc3IAIXNjYWxhLmNvbGxlY3Rpb24ubXV0YWJsZS5IYXNoU2V0JAAAAAAAAAADAgAAeHB3BAAAAANzcgARamF2YS5sYW5nLkludGVnZXIS4qCk94GHOAIAAUkABXZhbHVleHIAEGphdmEubGFuZy5OdW1iZXKGrJUdC5TgiwIAAHhwAAAAAXNxAH4ACAAAAAJzcQB+AAgAAAADeA==") check(g)(mutable.TreeMap[Int, Int]())( "rO0ABXNyADJzY2FsYS5jb2xsZWN0aW9uLmdlbmVyaWMuRGVmYXVsdFNlcmlhbGl6YXRpb25Qcm94eQAAAAAAAAADAwABTAAHZmFjdG9yeXQAGkxzY2FsYS9jb2xsZWN0aW9uL0ZhY3Rvcnk7eHBzcgArc2NhbGEuY29sbGVjdGlvbi5Tb3J0ZWRNYXBGYWN0b3J5JFRvRmFjdG9yeQAAAAAAAAADAgACTAALZXZpZGVuY2UkNDF0ABVMc2NhbGEvbWF0aC9PcmRlcmluZztMAAdmYWN0b3J5dAAjTHNjYWxhL2NvbGxlY3Rpb24vU29ydGVkTWFwRmFjdG9yeTt4cHNyABhzY2FsYS5tYXRoLk9yZGVyaW5nJEludCRSrFKndXqrowIAAHhwc3IAIXNjYWxhLmNvbGxlY3Rpb24ubXV0YWJsZS5UcmVlTWFwJAAAAAAAAAADAgAAeHB3BAAAAAB4") - check(g)(mutable.TreeMap(1 -> 1, 3 -> 6))( "rO0ABXNyADJzY2FsYS5jb2xsZWN0aW9uLmdlbmVyaWMuRGVmYXVsdFNlcmlhbGl6YXRpb25Qcm94eQAAAAAAAAADAwABTAAHZmFjdG9yeXQAGkxzY2FsYS9jb2xsZWN0aW9uL0ZhY3Rvcnk7eHBzcgArc2NhbGEuY29sbGVjdGlvbi5Tb3J0ZWRNYXBGYWN0b3J5JFRvRmFjdG9yeQAAAAAAAAADAgACTAALZXZpZGVuY2UkNDF0ABVMc2NhbGEvbWF0aC9PcmRlcmluZztMAAdmYWN0b3J5dAAjTHNjYWxhL2NvbGxlY3Rpb24vU29ydGVkTWFwRmFjdG9yeTt4cHNyABhzY2FsYS5tYXRoLk9yZGVyaW5nJEludCRSrFKndXqrowIAAHhwc3IAIXNjYWxhLmNvbGxlY3Rpb24ubXV0YWJsZS5UcmVlTWFwJAAAAAAAAAADAgAAeHB3BAAAAAJzcgAMc2NhbGEuVHVwbGUyLpRmfVuS+fUCAAJMAAJfMXQAEkxqYXZhL2xhbmcvT2JqZWN0O0wAAl8ycQB+AAx4cHNyABFqYXZhLmxhbmcuSW50ZWdlchLioKT3gYc4AgABSQAFdmFsdWV4cgAQamF2YS5sYW5nLk51bWJlcoaslR0LlOCLAgAAeHAAAAABcQB+ABBzcQB+AAtzcQB+AA4AAAADc3EAfgAOAAAABng=") - check(g)(mutable.TreeMap(1 -> 1, 3 -> 6).range(1, 2))( "rO0ABXNyADJzY2FsYS5jb2xsZWN0aW9uLmdlbmVyaWMuRGVmYXVsdFNlcmlhbGl6YXRpb25Qcm94eQAAAAAAAAADAwABTAAHZmFjdG9yeXQAGkxzY2FsYS9jb2xsZWN0aW9uL0ZhY3Rvcnk7eHBzcgArc2NhbGEuY29sbGVjdGlvbi5Tb3J0ZWRNYXBGYWN0b3J5JFRvRmFjdG9yeQAAAAAAAAADAgACTAALZXZpZGVuY2UkNDF0ABVMc2NhbGEvbWF0aC9PcmRlcmluZztMAAdmYWN0b3J5dAAjTHNjYWxhL2NvbGxlY3Rpb24vU29ydGVkTWFwRmFjdG9yeTt4cHNyABhzY2FsYS5tYXRoLk9yZGVyaW5nJEludCRSrFKndXqrowIAAHhwc3IAIXNjYWxhLmNvbGxlY3Rpb24ubXV0YWJsZS5UcmVlTWFwJAAAAAAAAAADAgAAeHB3BP////9zcgAMc2NhbGEuVHVwbGUyLpRmfVuS+fUCAAJMAAJfMXQAEkxqYXZhL2xhbmcvT2JqZWN0O0wAAl8ycQB+AAx4cHNyABFqYXZhLmxhbmcuSW50ZWdlchLioKT3gYc4AgABSQAFdmFsdWV4cgAQamF2YS5sYW5nLk51bWJlcoaslR0LlOCLAgAAeHAAAAABcQB+ABBzcgAmc2NhbGEuY29sbGVjdGlvbi5nZW5lcmljLlNlcmlhbGl6ZUVuZCQAAAAAAAAAAwIAAHhweA==") + check(g)(mutable.TreeMap(1 -> 1, 3 -> 6))( "rO0ABXNyADJzY2FsYS5jb2xsZWN0aW9uLmdlbmVyaWMuRGVmYXVsdFNlcmlhbGl6YXRpb25Qcm94eQAAAAAAAAADAwABTAAHZmFjdG9yeXQAGkxzY2FsYS9jb2xsZWN0aW9uL0ZhY3Rvcnk7eHBzcgArc2NhbGEuY29sbGVjdGlvbi5Tb3J0ZWRNYXBGYWN0b3J5JFRvRmFjdG9yeQAAAAAAAAADAgACTAALZXZpZGVuY2UkNDF0ABVMc2NhbGEvbWF0aC9PcmRlcmluZztMAAdmYWN0b3J5dAAjTHNjYWxhL2NvbGxlY3Rpb24vU29ydGVkTWFwRmFjdG9yeTt4cHNyABhzY2FsYS5tYXRoLk9yZGVyaW5nJEludCRSrFKndXqrowIAAHhwc3IAIXNjYWxhLmNvbGxlY3Rpb24ubXV0YWJsZS5UcmVlTWFwJAAAAAAAAAADAgAAeHB3BAAAAAJzcgAMc2NhbGEuVHVwbGUyENwG1w5ES4QCAAJMAAJfMXQAEkxqYXZhL2xhbmcvT2JqZWN0O0wAAl8ycQB+AAx4cHNyABFqYXZhLmxhbmcuSW50ZWdlchLioKT3gYc4AgABSQAFdmFsdWV4cgAQamF2YS5sYW5nLk51bWJlcoaslR0LlOCLAgAAeHAAAAABcQB+ABBzcQB+AAtzcQB+AA4AAAADc3EAfgAOAAAABng=") + check(g)(mutable.TreeMap(1 -> 1, 3 -> 6).range(1, 2))( "rO0ABXNyADJzY2FsYS5jb2xsZWN0aW9uLmdlbmVyaWMuRGVmYXVsdFNlcmlhbGl6YXRpb25Qcm94eQAAAAAAAAADAwABTAAHZmFjdG9yeXQAGkxzY2FsYS9jb2xsZWN0aW9uL0ZhY3Rvcnk7eHBzcgArc2NhbGEuY29sbGVjdGlvbi5Tb3J0ZWRNYXBGYWN0b3J5JFRvRmFjdG9yeQAAAAAAAAADAgACTAALZXZpZGVuY2UkNDF0ABVMc2NhbGEvbWF0aC9PcmRlcmluZztMAAdmYWN0b3J5dAAjTHNjYWxhL2NvbGxlY3Rpb24vU29ydGVkTWFwRmFjdG9yeTt4cHNyABhzY2FsYS5tYXRoLk9yZGVyaW5nJEludCRSrFKndXqrowIAAHhwc3IAIXNjYWxhLmNvbGxlY3Rpb24ubXV0YWJsZS5UcmVlTWFwJAAAAAAAAAADAgAAeHB3BP////9zcgAMc2NhbGEuVHVwbGUyENwG1w5ES4QCAAJMAAJfMXQAEkxqYXZhL2xhbmcvT2JqZWN0O0wAAl8ycQB+AAx4cHNyABFqYXZhLmxhbmcuSW50ZWdlchLioKT3gYc4AgABSQAFdmFsdWV4cgAQamF2YS5sYW5nLk51bWJlcoaslR0LlOCLAgAAeHAAAAABcQB+ABBzcgAmc2NhbGEuY29sbGVjdGlvbi5nZW5lcmljLlNlcmlhbGl6ZUVuZCQAAAAAAAAAAwIAAHhweA==") check(g)(mutable.TreeSet[Int]())( "rO0ABXNyADJzY2FsYS5jb2xsZWN0aW9uLmdlbmVyaWMuRGVmYXVsdFNlcmlhbGl6YXRpb25Qcm94eQAAAAAAAAADAwABTAAHZmFjdG9yeXQAGkxzY2FsYS9jb2xsZWN0aW9uL0ZhY3Rvcnk7eHBzcgAyc2NhbGEuY29sbGVjdGlvbi5FdmlkZW5jZUl0ZXJhYmxlRmFjdG9yeSRUb0ZhY3RvcnkAAAAAAAAAAwIAAkwAC2V2aWRlbmNlJDE1dAASTGphdmEvbGFuZy9PYmplY3Q7TAAHZmFjdG9yeXQAKkxzY2FsYS9jb2xsZWN0aW9uL0V2aWRlbmNlSXRlcmFibGVGYWN0b3J5O3hwc3IAGHNjYWxhLm1hdGguT3JkZXJpbmckSW50JFKsUqd1equjAgAAeHBzcgAhc2NhbGEuY29sbGVjdGlvbi5tdXRhYmxlLlRyZWVTZXQkAAAAAAAAAAMCAAB4cHcEAAAAAHg=") check(g)(mutable.TreeSet(1, 3))( "rO0ABXNyADJzY2FsYS5jb2xsZWN0aW9uLmdlbmVyaWMuRGVmYXVsdFNlcmlhbGl6YXRpb25Qcm94eQAAAAAAAAADAwABTAAHZmFjdG9yeXQAGkxzY2FsYS9jb2xsZWN0aW9uL0ZhY3Rvcnk7eHBzcgAyc2NhbGEuY29sbGVjdGlvbi5FdmlkZW5jZUl0ZXJhYmxlRmFjdG9yeSRUb0ZhY3RvcnkAAAAAAAAAAwIAAkwAC2V2aWRlbmNlJDE1dAASTGphdmEvbGFuZy9PYmplY3Q7TAAHZmFjdG9yeXQAKkxzY2FsYS9jb2xsZWN0aW9uL0V2aWRlbmNlSXRlcmFibGVGYWN0b3J5O3hwc3IAGHNjYWxhLm1hdGguT3JkZXJpbmckSW50JFKsUqd1equjAgAAeHBzcgAhc2NhbGEuY29sbGVjdGlvbi5tdXRhYmxlLlRyZWVTZXQkAAAAAAAAAAMCAAB4cHcEAAAAAnNyABFqYXZhLmxhbmcuSW50ZWdlchLioKT3gYc4AgABSQAFdmFsdWV4cgAQamF2YS5sYW5nLk51bWJlcoaslR0LlOCLAgAAeHAAAAABc3EAfgALAAAAA3g=") check(g)(mutable.TreeSet(1, 3).range(1, 2))( "rO0ABXNyADJzY2FsYS5jb2xsZWN0aW9uLmdlbmVyaWMuRGVmYXVsdFNlcmlhbGl6YXRpb25Qcm94eQAAAAAAAAADAwABTAAHZmFjdG9yeXQAGkxzY2FsYS9jb2xsZWN0aW9uL0ZhY3Rvcnk7eHBzcgAyc2NhbGEuY29sbGVjdGlvbi5FdmlkZW5jZUl0ZXJhYmxlRmFjdG9yeSRUb0ZhY3RvcnkAAAAAAAAAAwIAAkwAC2V2aWRlbmNlJDE1dAASTGphdmEvbGFuZy9PYmplY3Q7TAAHZmFjdG9yeXQAKkxzY2FsYS9jb2xsZWN0aW9uL0V2aWRlbmNlSXRlcmFibGVGYWN0b3J5O3hwc3IAGHNjYWxhLm1hdGguT3JkZXJpbmckSW50JFKsUqd1equjAgAAeHBzcgAhc2NhbGEuY29sbGVjdGlvbi5tdXRhYmxlLlRyZWVTZXQkAAAAAAAAAAMCAAB4cHcE/////3NyABFqYXZhLmxhbmcuSW50ZWdlchLioKT3gYc4AgABSQAFdmFsdWV4cgAQamF2YS5sYW5nLk51bWJlcoaslR0LlOCLAgAAeHAAAAABc3IAJnNjYWxhLmNvbGxlY3Rpb24uZ2VuZXJpYy5TZXJpYWxpemVFbmQkAAAAAAAAAAMCAAB4cHg=") // TODO scala/bug#8576 Uninitialized field under -Xcheckinit // check(g)(new mutable.History())( "rO0ABXNyACBzY2FsYS5jb2xsZWN0aW9uLm11dGFibGUuSGlzdG9yeUhuXxDIFJrsAgACSQAKbWF4SGlzdG9yeUwAA2xvZ3QAIExzY2FsYS9jb2xsZWN0aW9uL211dGFibGUvUXVldWU7eHAAAAPoc3IAHnNjYWxhLmNvbGxlY3Rpb24ubXV0YWJsZS5RdWV1ZbjMURVfOuHHAgAAeHIAJHNjYWxhLmNvbGxlY3Rpb24ubXV0YWJsZS5NdXRhYmxlTGlzdFJpnjJ+gFbAAgADSQADbGVuTAAGZmlyc3QwdAAlTHNjYWxhL2NvbGxlY3Rpb24vbXV0YWJsZS9MaW5rZWRMaXN0O0wABWxhc3QwcQB+AAV4cAAAAABzcgAjc2NhbGEuY29sbGVjdGlvbi5tdXRhYmxlLkxpbmtlZExpc3Sak+nGCZHaUQIAAkwABGVsZW10ABJMamF2YS9sYW5nL09iamVjdDtMAARuZXh0dAAeTHNjYWxhL2NvbGxlY3Rpb24vbXV0YWJsZS9TZXE7eHBwcQB+AApxAH4ACg==") - check(g)(mutable.LinkedHashMap(1 -> 2))( "rO0ABXNyADJzY2FsYS5jb2xsZWN0aW9uLmdlbmVyaWMuRGVmYXVsdFNlcmlhbGl6YXRpb25Qcm94eQAAAAAAAAADAwABTAAHZmFjdG9yeXQAGkxzY2FsYS9jb2xsZWN0aW9uL0ZhY3Rvcnk7eHBzcgAlc2NhbGEuY29sbGVjdGlvbi5NYXBGYWN0b3J5JFRvRmFjdG9yeQAAAAAAAAADAgABTAAHZmFjdG9yeXQAHUxzY2FsYS9jb2xsZWN0aW9uL01hcEZhY3Rvcnk7eHBzcgAnc2NhbGEuY29sbGVjdGlvbi5tdXRhYmxlLkxpbmtlZEhhc2hNYXAkAAAAAAAAAAMCAAB4cHcEAAAAAXNyAAxzY2FsYS5UdXBsZTIulGZ9W5L59QIAAkwAAl8xdAASTGphdmEvbGFuZy9PYmplY3Q7TAACXzJxAH4ACXhwc3IAEWphdmEubGFuZy5JbnRlZ2VyEuKgpPeBhzgCAAFJAAV2YWx1ZXhyABBqYXZhLmxhbmcuTnVtYmVyhqyVHQuU4IsCAAB4cAAAAAFzcQB+AAsAAAACeA==") + check(g)(mutable.LinkedHashMap(1 -> 2))( "rO0ABXNyADJzY2FsYS5jb2xsZWN0aW9uLmdlbmVyaWMuRGVmYXVsdFNlcmlhbGl6YXRpb25Qcm94eQAAAAAAAAADAwABTAAHZmFjdG9yeXQAGkxzY2FsYS9jb2xsZWN0aW9uL0ZhY3Rvcnk7eHBzcgAlc2NhbGEuY29sbGVjdGlvbi5NYXBGYWN0b3J5JFRvRmFjdG9yeQAAAAAAAAADAgABTAAHZmFjdG9yeXQAHUxzY2FsYS9jb2xsZWN0aW9uL01hcEZhY3Rvcnk7eHBzcgAnc2NhbGEuY29sbGVjdGlvbi5tdXRhYmxlLkxpbmtlZEhhc2hNYXAkAAAAAAAAAAMCAAB4cHcEAAAAAXNyAAxzY2FsYS5UdXBsZTIQ3AbXDkRLhAIAAkwAAl8xdAASTGphdmEvbGFuZy9PYmplY3Q7TAACXzJxAH4ACXhwc3IAEWphdmEubGFuZy5JbnRlZ2VyEuKgpPeBhzgCAAFJAAV2YWx1ZXhyABBqYXZhLmxhbmcuTnVtYmVyhqyVHQuU4IsCAAB4cAAAAAFzcQB+AAsAAAACeA==") check(g)(mutable.LinkedHashSet(1, 2, 3))( "rO0ABXNyADJzY2FsYS5jb2xsZWN0aW9uLmdlbmVyaWMuRGVmYXVsdFNlcmlhbGl6YXRpb25Qcm94eQAAAAAAAAADAwABTAAHZmFjdG9yeXQAGkxzY2FsYS9jb2xsZWN0aW9uL0ZhY3Rvcnk7eHBzcgAqc2NhbGEuY29sbGVjdGlvbi5JdGVyYWJsZUZhY3RvcnkkVG9GYWN0b3J5AAAAAAAAAAMCAAFMAAdmYWN0b3J5dAAiTHNjYWxhL2NvbGxlY3Rpb24vSXRlcmFibGVGYWN0b3J5O3hwc3IAJ3NjYWxhLmNvbGxlY3Rpb24ubXV0YWJsZS5MaW5rZWRIYXNoU2V0JAAAAAAAAAADAgAAeHB3BAAAAANzcgARamF2YS5sYW5nLkludGVnZXIS4qCk94GHOAIAAUkABXZhbHVleHIAEGphdmEubGFuZy5OdW1iZXKGrJUdC5TgiwIAAHhwAAAAAXNxAH4ACAAAAAJzcQB+AAgAAAADeA==") //check(g)(mutable.LinkedList(1, 2, 3))( "rO0ABXNyACNzY2FsYS5jb2xsZWN0aW9uLm11dGFibGUuTGlua2VkTGlzdJqT6cYJkdpRAgACTAAEZWxlbXQAEkxqYXZhL2xhbmcvT2JqZWN0O0wABG5leHR0ACVMc2NhbGEvY29sbGVjdGlvbi9tdXRhYmxlL0xpbmtlZExpc3Q7eHBzcgARamF2YS5sYW5nLkludGVnZXIS4qCk94GHOAIAAUkABXZhbHVleHIAEGphdmEubGFuZy5OdW1iZXKGrJUdC5TgiwIAAHhwAAAAAXNxAH4AAHNxAH4ABAAAAAJzcQB+AABzcQB+AAQAAAADc3EAfgAAcHEAfgAL") diff --git a/test/scaladoc/run/implicits-chaining.scala b/test/scaladoc/run/implicits-chaining.scala index 858ca9ce61ce..9222b2f316b4 100644 --- a/test/scaladoc/run/implicits-chaining.scala +++ b/test/scaladoc/run/implicits-chaining.scala @@ -23,7 +23,7 @@ object Test extends ScaladocModelTest { val A = base._class("A") conv = A._conversion(base.qualifiedName + ".convertToZ") - assert(conv.members.length == 1) + assert(conv.members.length == 2) assert(conv.constraints.length == 1) //// class B /////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -31,7 +31,7 @@ object Test extends ScaladocModelTest { val B = base._class("B") conv = B._conversion(base.qualifiedName + ".convertToZ") - assert(conv.members.length == 1) + assert(conv.members.length == 2) assert(conv.constraints.length == 0) //// class C /////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -45,7 +45,7 @@ object Test extends ScaladocModelTest { val D = base._class("D") conv = D._conversion(base.qualifiedName + ".convertToZ") - assert(conv.members.length == 1) + assert(conv.members.length == 2) assert(conv.constraints.length == 0) //// class E /////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -53,7 +53,7 @@ object Test extends ScaladocModelTest { val E = base._class("E") conv = E._conversion(base.qualifiedName + ".convertToZ") - assert(conv.members.length == 1) + assert(conv.members.length == 2) assert(conv.constraints.length == 0) //// class F /////////////////////////////////////////////////////////////////////////////////////////////////////////// From 340c0c08cf2ec6e7ddf62f044b833521dca4c1e1 Mon Sep 17 00:00:00 2001 From: Lukas Rytz Date: Fri, 22 Jun 2018 15:33:20 +0200 Subject: [PATCH 134/143] Overriding pairs: consider redundant base classes by class, not by type --- .../scala/tools/nsc/transform/Erasure.scala | 2 +- .../scala/reflect/internal/SymbolPairs.scala | 4 ++-- test/files/run/t10853.scala | 12 ++++++++++++ test/junit/scala/lang/traits/BytecodeTest.scala | 15 +++++++++++++++ 4 files changed, 30 insertions(+), 3 deletions(-) create mode 100644 test/files/run/t10853.scala diff --git a/src/compiler/scala/tools/nsc/transform/Erasure.scala b/src/compiler/scala/tools/nsc/transform/Erasure.scala index ec87a1021bd3..375941b6f19f 100644 --- a/src/compiler/scala/tools/nsc/transform/Erasure.scala +++ b/src/compiler/scala/tools/nsc/transform/Erasure.scala @@ -472,7 +472,7 @@ abstract class Erasure extends InfoTransform def computeAndEnter(): Unit = { while (opc.hasNext) { if (enteringExplicitOuter(!opc.low.isDeferred)) - checkPair(opc. currentPair) + checkPair(opc.currentPair) opc.next() } diff --git a/src/reflect/scala/reflect/internal/SymbolPairs.scala b/src/reflect/scala/reflect/internal/SymbolPairs.scala index e6e1bd634332..7c6ed9a17a73 100644 --- a/src/reflect/scala/reflect/internal/SymbolPairs.scala +++ b/src/reflect/scala/reflect/internal/SymbolPairs.scala @@ -35,7 +35,7 @@ abstract class SymbolPairs { * when viewed from IterableClass. */ def sameInBaseClass(baseClass: Symbol)(tp1: Type, tp2: Type) = - (tp1 baseType baseClass) =:= (tp2 baseType baseClass) + tp1.baseType(baseClass).typeSymbol == tp2.baseType(baseClass).typeSymbol final case class SymbolPair(base: Symbol, low: Symbol, high: Symbol) { private[this] val self = base.thisType @@ -125,7 +125,7 @@ abstract class SymbolPairs { * i = index(p) * j = index(b) * p isSubClass b - * p.baseType(b) == self.baseType(b) + * p.baseType(b).typeSymbol == self.baseType(b).typeSymbol */ private val subParents = new Array[BitSet](size) diff --git a/test/files/run/t10853.scala b/test/files/run/t10853.scala new file mode 100644 index 000000000000..1870e608c59f --- /dev/null +++ b/test/files/run/t10853.scala @@ -0,0 +1,12 @@ +trait F[T1, R] { def apply(funArg: T1): R } + +trait SetOps[A, +C] extends F[A, Boolean] { final def apply(setEl: A): Boolean = false } + +class AbstractSet[A] extends SetOps[A, AbstractSet[A]] +class AbstractSet2[A] extends AbstractSet[A] with SetOps[A, AbstractSet2[A]] + +object Test { + def main(args: Array[String]): Unit = { + new AbstractSet2[String] + } +} diff --git a/test/junit/scala/lang/traits/BytecodeTest.scala b/test/junit/scala/lang/traits/BytecodeTest.scala index 5f0c4b1854cf..efc36f5709d1 100644 --- a/test/junit/scala/lang/traits/BytecodeTest.scala +++ b/test/junit/scala/lang/traits/BytecodeTest.scala @@ -24,6 +24,21 @@ class BytecodeTest extends BytecodeTesting { assertSameCode(f, List(VarOp(ALOAD, 0), Invoke(INVOKESTATIC, target, "f$", s"(L$target;)I", true), Op(IRETURN))) } + @Test + def t10853(): Unit = { + val code = + """trait F[T1, R] { def apply(funArg: T1): R } + | + |trait SetOps[A, +C] extends F[A, Boolean] { final def apply(setEl: A): Boolean = false } + | + |class AbstractSet[A] extends SetOps[A, AbstractSet[A]] + |class AbstractSet2[A] extends AbstractSet[A] with SetOps[A, AbstractSet2[A]] + """.stripMargin + val cs = compileClasses(code) + val c = cs.find(_.name == "AbstractSet2").get + assertEquals(c.methods.asScala.map(_.name).toList, List("")) // no bridge for apply (there's already one in AbstractSet) + } + @Test def traitMethodForwarders(): Unit = { val code = From c8958442ea276169fef435f62df184bd82d42463 Mon Sep 17 00:00:00 2001 From: Lukas Rytz Date: Fri, 22 Jun 2018 16:30:30 +0200 Subject: [PATCH 135/143] Mark workarounds for 10853 with deprecatedOverriding We cannot make them final until the starr compiler includes the fix for 10853. Otherwise the locker build causes VerifyErrors --- src/library/scala/collection/immutable/Map.scala | 3 ++- src/library/scala/collection/immutable/Set.scala | 3 ++- src/library/scala/collection/mutable/Map.scala | 6 ++++-- 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/src/library/scala/collection/immutable/Map.scala b/src/library/scala/collection/immutable/Map.scala index 58df27908a93..23be6ba62109 100644 --- a/src/library/scala/collection/immutable/Map.scala +++ b/src/library/scala/collection/immutable/Map.scala @@ -61,7 +61,8 @@ trait MapOps[K, +V, +CC[X, +Y] <: MapOps[X, Y, CC, _], +C <: MapOps[K, V, CC, C] def remove(key: K): C /** Alias for `remove` */ - /* @`inline` final */ def - (key: K): C = remove(key) + @deprecatedOverriding("This method should be final, but is not due to scala/bug#10853", "2.13.0") + /*@`inline` final*/ def - (key: K): C = remove(key) @deprecated("Use -- with an explicit collection", "2.13.0") def - (key1: K, key2: K, keys: K*): C = remove(key1).remove(key2).removeAll(keys) diff --git a/src/library/scala/collection/immutable/Set.scala b/src/library/scala/collection/immutable/Set.scala index 3f12d8028b00..b46b4d30dc58 100644 --- a/src/library/scala/collection/immutable/Set.scala +++ b/src/library/scala/collection/immutable/Set.scala @@ -43,7 +43,8 @@ trait SetOps[A, +CC[X], +C <: SetOps[A, CC, C]] def excl(elem: A): C /** Alias for `excl` */ - /* @`inline` final */ override def - (elem: A): C = excl(elem) + @deprecatedOverriding("This method should be final, but is not due to scala/bug#10853", "2.13.0") + /*@`inline` final*/ override def - (elem: A): C = excl(elem) override def concat(that: collection.Iterable[A]): C = { var result: C = coll diff --git a/src/library/scala/collection/mutable/Map.scala b/src/library/scala/collection/mutable/Map.scala index fb948d95b79a..af7169fa9fbe 100644 --- a/src/library/scala/collection/mutable/Map.scala +++ b/src/library/scala/collection/mutable/Map.scala @@ -59,10 +59,12 @@ trait MapOps[K, V, +CC[X, Y] <: MapOps[X, Y, CC, _], +C <: MapOps[K, V, CC, C]] with Shrinkable[K] { @deprecated("Use - or remove on an immutable Map", "2.13.0") - /* final */ def - (key: K): C = clone() -= key + @deprecatedOverriding("This method should be final, but is not due to scala/bug#10853", "2.13.0") + /*final*/ def - (key: K): C = clone() -= key @deprecated("Use -- or removeAll on an immutable Map", "2.13.0") - /* final */ def - (key1: K, key2: K, keys: K*): C = clone() -= key1 -= key2 --= keys + @deprecatedOverriding("This method should be final, but is not due to scala/bug#10853", "2.13.0") + /*final*/ def - (key1: K, key2: K, keys: K*): C = clone() -= key1 -= key2 --= keys /** Adds a new key/value pair to this map and optionally returns previously bound value. * If the map already contains a From 6eedfbd5ecb39e097848534b26b76772ea5a546f Mon Sep 17 00:00:00 2001 From: Eugene Platonov Date: Thu, 15 Feb 2018 09:40:06 -0500 Subject: [PATCH 136/143] add Left#up and Right#up to upcast to Either --- src/library/scala/util/Either.scala | 18 ++++++++++++ test/junit/scala/util/EitherTest.scala | 38 ++++++++++++++++++++++---- 2 files changed, 50 insertions(+), 6 deletions(-) diff --git a/src/library/scala/util/Either.scala b/src/library/scala/util/Either.scala index 6cd2aec06e64..0b2e6a54ba6b 100644 --- a/src/library/scala/util/Either.scala +++ b/src/library/scala/util/Either.scala @@ -441,6 +441,15 @@ sealed abstract class Either[+A, +B] extends Product with Serializable { final case class Left[+A, +B](value: A) extends Either[A, B] { def isLeft = true def isRight = false + + /** + * Upcasts this `Left[A, B]` to `Either[A, B1]` + * {{{ + * Left(1).up[String] // Either[Int, String] + * }}} + */ + def up[B1 >: B]: Either[A, B1] = this + } /** The right side of the disjoint union, as opposed to the [[scala.util.Left]] side. @@ -450,6 +459,15 @@ final case class Left[+A, +B](value: A) extends Either[A, B] { final case class Right[+A, +B](value: B) extends Either[A, B] { def isLeft = false def isRight = true + + /** + * Upcasts this `Right[A, B]` to `Either[A1, B]` + * {{{ + * Right("1").up[Int] // Either[Int, String] + * }}} + */ + def up[A1 >: A]: Either[A1, B] = this + } object Either { diff --git a/test/junit/scala/util/EitherTest.scala b/test/junit/scala/util/EitherTest.scala index 9cf68578d0db..80bab6f2bab4 100644 --- a/test/junit/scala/util/EitherTest.scala +++ b/test/junit/scala/util/EitherTest.scala @@ -1,6 +1,7 @@ package scala.util -import org.junit.{ Assert, Test } +import org.junit.Assert._ +import org.junit.Test class EitherTest { @@ -13,9 +14,34 @@ class EitherTest { val flatrl: Either[String, Int] = rl.flatten val flatrr: Either[String, Int] = rr.flatten - Assert.assertEquals(Left("pancake"), flatl) - Assert.assertEquals(Left("flounder"), flatrl) - Assert.assertEquals(Right(7), flatrr) - + assertEquals(Left("pancake"), flatl) + assertEquals(Left("flounder"), flatrl) + assertEquals(Right(7), flatrr) } -} \ No newline at end of file + + @Test + def testLeftUp: Unit = { + + def rightSumOrLeftEmpty(l: List[Int]) = + l.foldLeft(Left("empty").up[Int]) { + case (Left(_), i) => Right(i) + case (Right(s), i) => Right(s + i) + } + + assertEquals(rightSumOrLeftEmpty(List(1, 2, 3)), Right(6)) + assertEquals(rightSumOrLeftEmpty(Nil), Left("empty")) + } + + @Test + def testRightUp: Unit = { + + def leftSumOrRightEmpty(l: List[Int]) = + l.foldLeft(Right("empty").up[Int]) { + case (Right(_), i) => Left(i) + case (Left(s), i) => Left(s + i) + } + + assertEquals(leftSumOrRightEmpty(List(1, 2, 3)), Left(6)) + assertEquals(leftSumOrRightEmpty(Nil), Right("empty")) + } +} From 88f911e1613ad31c1c51dbfe52bad767727f1189 Mon Sep 17 00:00:00 2001 From: Miles Sabin Date: Tue, 7 Aug 2018 23:43:29 +0100 Subject: [PATCH 137/143] Avoid allocations when traversing TypeRefs. --- src/compiler/scala/tools/nsc/typechecker/Implicits.scala | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/compiler/scala/tools/nsc/typechecker/Implicits.scala b/src/compiler/scala/tools/nsc/typechecker/Implicits.scala index a0e3fa4a30bd..41e2e2132994 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Implicits.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Implicits.scala @@ -482,7 +482,10 @@ trait Implicits { case AnnotatedType(annots, tp) => core(tp) case ExistentialType(tparams, result) => core(result).subst(tparams, tparams map (t => core(t.info.bounds.hi))) case PolyType(tparams, result) => core(result).subst(tparams, tparams map (t => core(t.info.bounds.hi))) - case TypeRef(pre, sym, args) => typeRef(pre, sym, args.map(core)) + case TypeRef(pre, sym, args) => + val coreArgs = args.mapConserve(core) + if (coreArgs eq args) tp + else typeRef(pre, sym, coreArgs) case _ => tp } From bc0b8dcd073786ed245ec450546e438c71061630 Mon Sep 17 00:00:00 2001 From: Kazuhiro Sera Date: Wed, 8 Aug 2018 13:38:25 +0900 Subject: [PATCH 138/143] Fix several minor typos in comments detected by github.com/client9/misspell --- src/compiler/scala/tools/nsc/ast/TreeGen.scala | 2 +- .../scala/tools/nsc/backend/jvm/BCodeBodyBuilder.scala | 2 +- src/compiler/scala/tools/nsc/transform/patmat/Solving.scala | 2 +- src/compiler/scala/tools/nsc/typechecker/Typers.scala | 6 +++--- src/scalacheck/org/scalacheck/Prop.scala | 2 +- src/scalacheck/org/scalacheck/Test.scala | 2 +- src/scalacheck/org/scalacheck/commands/Commands.scala | 2 +- 7 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/compiler/scala/tools/nsc/ast/TreeGen.scala b/src/compiler/scala/tools/nsc/ast/TreeGen.scala index d3655785126f..952666a3f2d3 100644 --- a/src/compiler/scala/tools/nsc/ast/TreeGen.scala +++ b/src/compiler/scala/tools/nsc/ast/TreeGen.scala @@ -314,7 +314,7 @@ abstract class TreeGen extends scala.reflect.internal.TreeGen with TreeDSL { // Rewrite This(enclModuleClass) to Ident(enclModuleClass) to avoid unnecessary capture of the module // class, which might hamper serializability. // - // Analagous to this special case in ExplicitOuter: https://github.com/scala/scala/blob/d2d33ddf8c/src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala#L410-L412 + // Analogous to this special case in ExplicitOuter: https://github.com/scala/scala/blob/d2d33ddf8c/src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala#L410-L412 // that understands that such references shouldn't give rise to outer params. val enclosingStaticModules = owner.enclClassChain.filter(x => !x.hasPackageFlag && x.isModuleClass && x.isStatic) enclosingStaticModules.foldLeft(tree)((tree, moduleClass) => tree.substituteThis(moduleClass, gen.mkAttributedIdent(moduleClass.sourceModule)) ) diff --git a/src/compiler/scala/tools/nsc/backend/jvm/BCodeBodyBuilder.scala b/src/compiler/scala/tools/nsc/backend/jvm/BCodeBodyBuilder.scala index 86ed9fd8bbbe..2848d56177f9 100644 --- a/src/compiler/scala/tools/nsc/backend/jvm/BCodeBodyBuilder.scala +++ b/src/compiler/scala/tools/nsc/backend/jvm/BCodeBodyBuilder.scala @@ -568,7 +568,7 @@ abstract class BCodeBodyBuilder extends BCodeSkelBuilder { } } - // scala/bug#10290: qual can be `this.$outer()` (not just `this`), so we call genLoad (not jsut ALOAD_0) + // scala/bug#10290: qual can be `this.$outer()` (not just `this`), so we call genLoad (not just ALOAD_0) genLoad(superQual) genLoadArguments(args, paramTKs(app)) generatedType = genCallMethod(fun.symbol, InvokeStyle.Super, app.pos, sup.tpe.typeSymbol) diff --git a/src/compiler/scala/tools/nsc/transform/patmat/Solving.scala b/src/compiler/scala/tools/nsc/transform/patmat/Solving.scala index 1f580eb743b7..1aa4b70efddb 100644 --- a/src/compiler/scala/tools/nsc/transform/patmat/Solving.scala +++ b/src/compiler/scala/tools/nsc/transform/patmat/Solving.scala @@ -528,7 +528,7 @@ trait Solving extends Logic { * * See also [[https://en.wikipedia.org/wiki/DPLL_algorithm]]. * - * This implementation uses a `List` to reify the seach stack, thus making + * This implementation uses a `List` to reify the search stack, thus making * it run in constant stack space. The stack is composed of pairs of * `(remaining clauses, variable assignments)`, and depth-first search * is achieved by using a stack rather than a queue. diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala index 89135b525d3e..71c02ba92230 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala @@ -4172,7 +4172,7 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper } // - // START: applyDynamic suport + // START: applyDynamic support // import treeInfo.{isApplyDynamicName, DynamicUpdate, DynamicApplicationNamed} @@ -5963,10 +5963,10 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper for (sym <- classes) { for ((ownAcc, superAcc) <- superConstructorCalls.getOrElse(sym, Nil)) { - // We have a corresponding paramter in the super class. + // We have a corresponding parameter in the super class. val superClazz = sym.superClass val alias = ( - superAcc.initialize.alias // Is the param accessor is an alias for a field further up the class heirarchy? + superAcc.initialize.alias // Is the param accessor is an alias for a field further up the class hierarchy? orElse (superAcc getterIn superAcc.owner) // otherwise, lookup the accessor for the super filter (alias => superClazz.info.nonPrivateMember(alias.name) == alias) // the accessor must be public ) diff --git a/src/scalacheck/org/scalacheck/Prop.scala b/src/scalacheck/org/scalacheck/Prop.scala index 1f5e78587f1e..b5ba429680ed 100644 --- a/src/scalacheck/org/scalacheck/Prop.scala +++ b/src/scalacheck/org/scalacheck/Prop.scala @@ -496,7 +496,7 @@ object Prop { /** * This handles situations where we have a starting seed in our - * paramters. + * parameters. * * If we do, then we remove it from parameters and return it. If * not, we create a new random seed. The new parameters from this diff --git a/src/scalacheck/org/scalacheck/Test.scala b/src/scalacheck/org/scalacheck/Test.scala index 2a9c714c2e7c..84aabc9067b2 100644 --- a/src/scalacheck/org/scalacheck/Test.scala +++ b/src/scalacheck/org/scalacheck/Test.scala @@ -128,7 +128,7 @@ object Test { /** Test parameters used by the check methods. Default * parameters are defined by [[Test.Parameters.default]]. */ object Parameters { - /** Default test parameters. Can be overriden if you need to + /** Default test parameters. Can be overridden if you need to * tweak the parameters: * * {{{ diff --git a/src/scalacheck/org/scalacheck/commands/Commands.scala b/src/scalacheck/org/scalacheck/commands/Commands.scala index 5c8009e8944d..19a518dfa148 100644 --- a/src/scalacheck/org/scalacheck/commands/Commands.scala +++ b/src/scalacheck/org/scalacheck/commands/Commands.scala @@ -77,7 +77,7 @@ trait Commands { def destroySut(sut: Sut): Unit /** The precondition for the initial state, when no commands yet have - * run. This is used by ScalaCheck when command sequences are shrinked + * run. This is used by ScalaCheck when command sequences are shrunk * and the first state might differ from what is returned from * [[genInitialState]]. */ def initialPreCondition(state: State): Boolean From 1b1aefe0d8f691e6c926a5db23ecd8c52316774f Mon Sep 17 00:00:00 2001 From: Jason Zaugg Date: Wed, 8 Aug 2018 16:35:45 +1000 Subject: [PATCH 139/143] Add a test to show a problem in switch pattern translation The performance optimization in #6607 assumed that a translated match would always be a `Match` node itself, but it can also be a `{ synthetic val x1 = ...; x1 match { .. } }` block. --- test/files/run/patmat-origtp-switch.check | 18 ++++++++++++++++++ test/files/run/patmat-origtp-switch.scala | 21 +++++++++++++++++++++ 2 files changed, 39 insertions(+) create mode 100644 test/files/run/patmat-origtp-switch.check create mode 100644 test/files/run/patmat-origtp-switch.scala diff --git a/test/files/run/patmat-origtp-switch.check b/test/files/run/patmat-origtp-switch.check new file mode 100644 index 000000000000..a5bb136c6604 --- /dev/null +++ b/test/files/run/patmat-origtp-switch.check @@ -0,0 +1,18 @@ +[[syntax trees at end of patmat]] // newSource1.scala +package {.type} { + class C extends scala.AnyRef { + def (): C = { + C.super{C.super.type}.{()Object}(){Object}; + (){Unit} + }{Unit}; + def foo[A](a: A, b: A with C, i: Int): A = { + case val x1: Int = i{Int}; + x1{Int} match { + case 0{Int(0)} => a{A} + case 1{Int(1)} => b{A with C} + case _{Int} => throw new MatchError{MatchError}{(obj: Any)MatchError}(x1{Int}){MatchError}{Nothing} + }{Any} + }{A} + } +} + diff --git a/test/files/run/patmat-origtp-switch.scala b/test/files/run/patmat-origtp-switch.scala new file mode 100644 index 000000000000..bf7eb62a9123 --- /dev/null +++ b/test/files/run/patmat-origtp-switch.scala @@ -0,0 +1,21 @@ +import scala.tools.partest._ +import java.io.{Console => _, _} + +object Test extends DirectTest { + + override def extraSettings: String = "-usejavacp -Xprint:patmat -Xprint-types -d " + testOutput.path + + override def code = """class C { + def foo[A](a: A, b: A with C, i: Int) = i match { + case 0 => a + case 1 => b + } + } + """ + + override def show(): Unit = { + Console.withErr(System.out) { + compile() + } + } +} From 72656e79d347bd1ff2621cf43674b575a858d7d8 Mon Sep 17 00:00:00 2001 From: Jason Zaugg Date: Wed, 8 Aug 2018 16:36:14 +1000 Subject: [PATCH 140/143] Fix regression in switch pattern translation The performance optimization in #6607 assumed that a translated match would always be a `Match` node itself, but it can also be a `{ synthetic val x1 = ...; x1 match { .. } }` block. --- .../tools/nsc/transform/patmat/PatternMatching.scala | 8 +++++++- test/files/run/patmat-origtp-switch.check | 2 +- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/src/compiler/scala/tools/nsc/transform/patmat/PatternMatching.scala b/src/compiler/scala/tools/nsc/transform/patmat/PatternMatching.scala index 0ba85e5a01bb..829818fbb1d2 100644 --- a/src/compiler/scala/tools/nsc/transform/patmat/PatternMatching.scala +++ b/src/compiler/scala/tools/nsc/transform/patmat/PatternMatching.scala @@ -65,7 +65,13 @@ trait PatternMatching extends Transform // Keep 2.12 behaviour of using wildcard expected type, recomputing the LUB, then throwing it away for the continuations plugins // but for the rest of us pass in top as the expected type to avoid waste. val pt = if (origTp <:< definitions.AnyTpe) definitions.AnyTpe else WildcardType - localTyper.typed(translated, pt) setType origTp + localTyper.typed(translated, pt) match { + case b @ Block(stats, m: Match) => + b.setType(origTp) + m.setType(origTp) + b + case tree => tree setType origTp + } } catch { case x: (Types#TypeError) => // TODO: this should never happen; error should've been reported during type checking diff --git a/test/files/run/patmat-origtp-switch.check b/test/files/run/patmat-origtp-switch.check index a5bb136c6604..84a92e1c6ab3 100644 --- a/test/files/run/patmat-origtp-switch.check +++ b/test/files/run/patmat-origtp-switch.check @@ -11,7 +11,7 @@ package {.type} { case 0{Int(0)} => a{A} case 1{Int(1)} => b{A with C} case _{Int} => throw new MatchError{MatchError}{(obj: Any)MatchError}(x1{Int}){MatchError}{Nothing} - }{Any} + }{A} }{A} } } From dabb617313bde3b08d268e2d0230f1f42a9320bf Mon Sep 17 00:00:00 2001 From: Lukas Rytz Date: Wed, 8 Aug 2018 13:48:42 +0200 Subject: [PATCH 141/143] PriorityQueue.dequeueAll returns an immutable.Seq --- src/library/scala/collection/mutable/PriorityQueue.scala | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/library/scala/collection/mutable/PriorityQueue.scala b/src/library/scala/collection/mutable/PriorityQueue.scala index 48fc83fa33bf..d0702c33478e 100644 --- a/src/library/scala/collection/mutable/PriorityQueue.scala +++ b/src/library/scala/collection/mutable/PriorityQueue.scala @@ -29,7 +29,7 @@ import scala.math.Ordering * @example {{{ * val pq = collection.mutable.PriorityQueue(1, 2, 5, 3, 7) * println(pq) // elements probably not in order - * println(pq.clone.dequeueAll) // prints Vector(7, 5, 3, 2, 1) + * println(pq.clone.dequeueAll) // prints ArraySeq(7, 5, 3, 2, 1) * }}} * * @tparam A type of the elements in this priority queue. @@ -219,12 +219,13 @@ sealed class PriorityQueue[A](implicit val ord: Ordering[A]) } else throw new NoSuchElementException("no element to remove from heap") - def dequeueAll[A1 >: A]: Seq[A1] = { - val b = new ArrayBuffer[A1](size) + def dequeueAll[A1 >: A]: immutable.Seq[A1] = { + val b = ArrayBuilder.make[Any] + b.sizeHint(size) while (nonEmpty) { b += dequeue() } - b + immutable.ArraySeq.unsafeWrapArray(b.result()).asInstanceOf[immutable.ArraySeq[A1]] } /** Returns the element with the highest priority in the queue, From 36baab8279074092a97363d0b80af82d76e8d2a5 Mon Sep 17 00:00:00 2001 From: Stefan Zeiger Date: Wed, 8 Aug 2018 14:32:27 +0200 Subject: [PATCH 142/143] Add deprecated `updated` method to s.c.m.Map Fixes https://github.com/scala/bug/issues/10990 --- src/library/scala/collection/mutable/AnyRefMap.scala | 9 +++------ src/library/scala/collection/mutable/LongMap.scala | 9 +++------ src/library/scala/collection/mutable/Map.scala | 3 +++ src/library/scala/collection/mutable/SortedMap.scala | 4 ++++ 4 files changed, 13 insertions(+), 12 deletions(-) diff --git a/src/library/scala/collection/mutable/AnyRefMap.scala b/src/library/scala/collection/mutable/AnyRefMap.scala index b5d7484eb973..a52d9095c9d6 100644 --- a/src/library/scala/collection/mutable/AnyRefMap.scala +++ b/src/library/scala/collection/mutable/AnyRefMap.scala @@ -381,12 +381,9 @@ class AnyRefMap[K <: AnyRef, V] private[collection] (defaultEntry: K => V, initi override def ++[V2 >: V](xs: scala.collection.Iterable[(K, V2)]): AnyRefMap[K, V2] = concat(xs) - @deprecated("Use AnyRefMap.from(m).add(k,v) instead of m.updated(k, v)", "2.13.0") - def updated[V1 >: V](key: K, value: V1): AnyRefMap[K, V1] = { - val arm = clone().asInstanceOf[AnyRefMap[K, V1]] - arm += ((key, value)) - arm - } + @deprecated("Use m.clone().addOne(k,v) instead of m.updated(k, v)", "2.13.0") + override def updated[V1 >: V](key: K, value: V1): AnyRefMap[K, V1] = + clone().asInstanceOf[AnyRefMap[K, V1]].addOne(key, value) private[this] def foreachElement[A,B](elems: Array[AnyRef], f: A => B): Unit = { var i,j = 0 diff --git a/src/library/scala/collection/mutable/LongMap.scala b/src/library/scala/collection/mutable/LongMap.scala index e3345b00af2e..1c420339a0a6 100644 --- a/src/library/scala/collection/mutable/LongMap.scala +++ b/src/library/scala/collection/mutable/LongMap.scala @@ -452,12 +452,9 @@ final class LongMap[V] private[collection] (defaultEntry: Long => V, initialBuff override def ++ [V1 >: V](xs: scala.collection.Iterable[(Long, V1)]): LongMap[V1] = concat(xs) - @deprecated("Use LongMap.from(m).add(k,v) instead of m.updated(k, v)", "2.13.0") - def updated[V1 >: V](key: Long, value: V1): LongMap[V1] = { - val lm = clone().asInstanceOf[LongMap[V1]] - lm += (key, value) - lm - } + @deprecated("Use m.clone().addOne(k,v) instead of m.updated(k, v)", "2.13.0") + override def updated[V1 >: V](key: Long, value: V1): LongMap[V1] = + clone().asInstanceOf[LongMap[V1]].addOne(key, value) /** Applies a function to all keys of this map. */ def foreachKey[A](f: Long => A): Unit = { diff --git a/src/library/scala/collection/mutable/Map.scala b/src/library/scala/collection/mutable/Map.scala index fb948d95b79a..92a21f7ee46e 100644 --- a/src/library/scala/collection/mutable/Map.scala +++ b/src/library/scala/collection/mutable/Map.scala @@ -157,6 +157,9 @@ trait MapOps[K, V, +CC[X, Y] <: MapOps[X, Y, CC, _], +C <: MapOps[K, V, CC, C]] this } + @deprecated("Use m.clone().addOne((k,v)) instead of m.updated(k, v)", "2.13.0") + def updated[V1 >: V](key: K, value: V1): CC[K, V1] = + clone().asInstanceOf[CC[K, V1]].addOne((key, value)) } /** diff --git a/src/library/scala/collection/mutable/SortedMap.scala b/src/library/scala/collection/mutable/SortedMap.scala index 6ce1283d60ca..ed91e6770fb4 100644 --- a/src/library/scala/collection/mutable/SortedMap.scala +++ b/src/library/scala/collection/mutable/SortedMap.scala @@ -44,6 +44,10 @@ trait SortedMapOps[K, V, +CC[X, Y] <: Map[X, Y] with SortedMapOps[X, Y, CC, _], with MapOps[K, V, Map, C] { def unsorted: Map[K, V] + + @deprecated("Use m.clone().addOne((k,v)) instead of m.updated(k, v)", "2.13.0") + override def updated[V1 >: V](key: K, value: V1): CC[K, V1] = + clone().asInstanceOf[CC[K, V1]].addOne((key, value)) } @SerialVersionUID(3L) From ac9c8074f7b91b58385efe6f4a2756efe46e6ffe Mon Sep 17 00:00:00 2001 From: Georgi Krastev Date: Sun, 18 Feb 2018 11:28:17 +0100 Subject: [PATCH 143/143] Don't abort on glb/lub of TypeVar; ignore it. Fixes scala/bug#10514 by turning the crash into an error message. --- src/reflect/scala/reflect/internal/Types.scala | 2 +- test/files/neg/t10514.check | 13 +++++++++++++ test/files/neg/t10514.flags | 1 + test/files/neg/t10514.scala | 9 +++++++++ 4 files changed, 24 insertions(+), 1 deletion(-) create mode 100644 test/files/neg/t10514.check create mode 100644 test/files/neg/t10514.flags create mode 100644 test/files/neg/t10514.scala diff --git a/src/reflect/scala/reflect/internal/Types.scala b/src/reflect/scala/reflect/internal/Types.scala index 12a1ec22171a..f74b307c5110 100644 --- a/src/reflect/scala/reflect/internal/Types.scala +++ b/src/reflect/scala/reflect/internal/Types.scala @@ -4669,7 +4669,7 @@ trait Types case tv@TypeVar(_, constr) => if (tv.instValid) stripType(constr.inst) else if (tv.untouchable) stripped += tv - else abort("trying to do lub/glb of typevar " + tv) + else {} // ignore when this happens (neg/t10514.scala) -- don't abort("trying to do lub/glb of typevar " + tv) case tp => stripped += tp } ts foreach stripType diff --git a/test/files/neg/t10514.check b/test/files/neg/t10514.check new file mode 100644 index 000000000000..23a70703e576 --- /dev/null +++ b/test/files/neg/t10514.check @@ -0,0 +1,13 @@ +t10514.scala:8: error: no type parameters for constructor Foo: (value: F[C[G[Foo[F,G]]]])Foo[F,G] exist so that it can be applied to arguments (Some[C[Foo[Option,Test.this.Id]]]) + --- because --- +argument expression's type is not compatible with formal parameter type; + found : Some[C[Foo[Option,Test.this.Id]]] + required: ?F[C[?G[Foo[?F,?G]]]] + new Foo(Some(new C(new Foo[Option, Id](None)))) + ^ +t10514.scala:8: error: type mismatch; + found : Some[C[Foo[Option,Test.this.Id]]] + required: F[C[G[Foo[F,G]]]] + new Foo(Some(new C(new Foo[Option, Id](None)))) + ^ +two errors found diff --git a/test/files/neg/t10514.flags b/test/files/neg/t10514.flags new file mode 100644 index 000000000000..b5c02117c012 --- /dev/null +++ b/test/files/neg/t10514.flags @@ -0,0 +1 @@ +-language:higherKinds diff --git a/test/files/neg/t10514.scala b/test/files/neg/t10514.scala new file mode 100644 index 000000000000..cd3d1846e33b --- /dev/null +++ b/test/files/neg/t10514.scala @@ -0,0 +1,9 @@ +// document status quo (used to crash, now just fails to infer) +// to make this compile, explicitly provide type args +class C[T](x: T) +class Foo[F[_], G[_]](value: F[C[G[Foo[F, G]]]]) + +class Test { + type Id[A] = A + new Foo(Some(new C(new Foo[Option, Id](None)))) +} \ No newline at end of file