diff options
96 files changed, 2232 insertions, 338 deletions
diff --git a/bincompat-backward.whitelist.conf b/bincompat-backward.whitelist.conf index b88fa64584..9ea78a2977 100644 --- a/bincompat-backward.whitelist.conf +++ b/bincompat-backward.whitelist.conf @@ -34,6 +34,14 @@ filter { problemName=DirectMissingMethodProblem }, { + matchName="scala.reflect.runtime.SynchronizedOps.scala$reflect$runtime$SynchronizedOps$$super$newMappedBaseTypeSeq" + problemName=ReversedMissingMethodProblem + }, + { + matchName="scala.reflect.runtime.SynchronizedOps#SynchronizedBaseTypeSeq.lateMap" + problemName=DirectMissingMethodProblem + }, + { matchName="scala.collection.immutable.HashMap.contains0" problemName=DirectMissingMethodProblem }, @@ -48,6 +56,217 @@ filter { { matchName="scala.collection.immutable.HashMap#HashMapCollision1.contains0" problemName=DirectMissingMethodProblem + }, + { + matchName="scala.collection.mutable.ArrayOps.unzip" + problemName=MissingMethodProblem + }, + { + matchName="scala.collection.mutable.ArrayOps.unzip3" + problemName=MissingMethodProblem + }, + { + matchName="scala.collection.mutable.ArrayOps#ofFloat.unzip" + problemName=IncompatibleMethTypeProblem + }, + { + matchName="scala.collection.mutable.ArrayOps#ofFloat.unzip3" + problemName=IncompatibleMethTypeProblem + }, + { + matchName="scala.collection.mutable.ArrayOps#ofBoolean.unzip" + problemName=IncompatibleMethTypeProblem + }, + { + matchName="scala.collection.mutable.ArrayOps#ofBoolean.unzip3" + problemName=IncompatibleMethTypeProblem + }, + { + matchName="scala.collection.mutable.ArrayOps#ofRef.unzip" + problemName=IncompatibleMethTypeProblem + }, + { + matchName="scala.collection.mutable.ArrayOps#ofRef.unzip3" + problemName=IncompatibleMethTypeProblem + }, + { + matchName="scala.collection.mutable.ArrayOps#ofUnit.unzip" + problemName=IncompatibleMethTypeProblem + }, + { + matchName="scala.collection.mutable.ArrayOps#ofUnit.unzip3" + problemName=IncompatibleMethTypeProblem + }, + { + matchName="scala.collection.mutable.ArrayOps#ofDouble.unzip" + problemName=IncompatibleMethTypeProblem + }, + { + matchName="scala.collection.mutable.ArrayOps#ofDouble.unzip3" + problemName=IncompatibleMethTypeProblem + }, + // see SI-8200 + { + matchName="scala.reflect.api.StandardLiftables#StandardLiftableInstances.liftTree" + problemName=MissingMethodProblem + }, + // see SI-8331 + { + matchName="scala.reflect.api.Internals#ReificationSupportApi#SyntacticTypeAppliedExtractor.unapply" + problemName=IncompatibleResultTypeProblem + }, + { + matchName="scala.reflect.api.Internals#ReificationSupportApi#SyntacticTypeAppliedExtractor.unapply" + problemName=MissingMethodProblem + }, + { + matchName="scala.reflect.api.Internals#ReificationSupportApi.SyntacticSelectType" + problemName=MissingMethodProblem + }, + { + matchName="scala.reflect.api.Internals#ReificationSupportApi.SyntacticAppliedType" + problemName=MissingMethodProblem + }, + { + matchName="scala.reflect.api.Internals#ReificationSupportApi.SyntacticSelectTerm" + problemName=MissingMethodProblem + }, + // see SI-8366 + { + matchName="scala.reflect.api.Internals#ReificationSupportApi.SyntacticPartialFunction" + problemName=MissingMethodProblem + }, + { + matchName="scala.reflect.api.Mirror.symbolOf" + problemName=MissingMethodProblem + }, + { + matchName="scala.reflect.api.Mirror.typeOf" + problemName=MissingMethodProblem + }, + { + matchName="scala.reflect.api.Mirror.weakTypeOf" + problemName=MissingMethodProblem + }, + // see SI-8388 + { + matchName="scala.reflect.api.Internals$ReificationSupportApi$SyntacticIdentExtractor" + problemName=MissingClassProblem + }, + { + matchName="scala.reflect.api.Internals#ReificationSupportApi.SyntacticIdent" + problemName=MissingMethodProblem + }, + { + matchName="scala.reflect.api.Internals#ReificationSupportApi.SyntacticSingletonType" + problemName=MissingMethodProblem + }, + { + matchName="scala.reflect.api.Internals#ReificationSupportApi.SyntacticTermIdent" + problemName=MissingMethodProblem + }, + { + matchName="scala.reflect.api.Internals#ReificationSupportApi.SyntacticTypeIdent" + problemName=MissingMethodProblem + }, + { + matchName="scala.reflect.api.Internals#ReificationSupportApi.SyntacticCompoundType" + problemName=MissingMethodProblem + }, + { + matchName="scala.reflect.api.Internals#ReificationSupportApi.SyntacticAnnotatedType" + problemName=MissingMethodProblem + }, + { + matchName="scala.reflect.api.Internals#ReificationSupportApi.SyntacticTypeProjection" + problemName=MissingMethodProblem + }, + { + matchName="scala.reflect.api.Internals#ReificationSupportApi.SyntacticExistentialType" + problemName=MissingMethodProblem + }, + { + matchName="scala.reflect.runtime.SynchronizedOps.newNestedScope" + problemName=MissingMethodProblem + }, + // https://github.com/scala/scala/pull/3848 -- SI-8680 + { + matchName="scala.collection.immutable.Stream.scala$collection$immutable$Stream$$loop$6" + problemName=MissingMethodProblem + }, + { + matchName="scala.collection.immutable.Stream.scala$collection$immutable$Stream$$loop$5" + problemName=MissingMethodProblem + }, + { + matchName="scala.collection.immutable.Stream.scala$collection$immutable$Stream$$loop$4" + problemName=MissingMethodProblem + }, + // SI-8946 + { + matchName="scala.reflect.runtime.ThreadLocalStorage#MyThreadLocalStorage.values" + problemName=MissingMethodProblem + }, + // the below method was the unused private (sic!) method but the compatibility checker was complaining about it + { + matchName="scala.reflect.io.ZipArchive.scala$reflect$io$ZipArchive$$walkIterator" + problemName=MissingMethodProblem + }, + // SI-8362: AbstractPromise extends AtomicReference + // It's ok to change a package-protected class in an impl package, + // even though it's not clear why it changed -- bug in generic signature generation? + // -public class scala.concurrent.impl.Promise$DefaultPromise<T> extends scala.concurrent.impl.AbstractPromise implements scala.concurrent.impl.Promise<T> + // +public class scala.concurrent.impl.Promise$DefaultPromise<T extends java.lang.Object> extends scala.concurrent.impl.AbstractPromise implements scala.concurrent.impl.Promise<T> + { + matchName="scala.concurrent.impl.Promise$DefaultPromise" + problemName=MissingTypesProblem + }, + // SI-9488: Due to SI-8362 above, toString was silently changed to the AtomicReference toString implementation, + // This is fixed by SI-9488, and this should be safe since the class in question is stdlib internal. + { + matchName="scala.concurrent.impl.Promise.toString" + problemName=MissingMethodProblem + }, + // https://github.com/scala/scala/pull/5652 + { + matchName="scala.collection.mutable.ArrayOps#ofChar.slice" + problemName=FinalMethodProblem + }, + { + matchName="scala.collection.mutable.ArrayOps#ofShort.slice" + problemName=FinalMethodProblem + }, + { + matchName="scala.collection.mutable.ArrayOps#ofUnit.slice" + problemName=FinalMethodProblem + }, + { + matchName="scala.collection.mutable.ArrayOps#ofInt.slice" + problemName=FinalMethodProblem + }, + { + matchName="scala.collection.mutable.ArrayOps#ofBoolean.slice" + problemName=FinalMethodProblem + }, + { + matchName="scala.collection.mutable.ArrayOps#ofDouble.slice" + problemName=FinalMethodProblem + }, + { + matchName="scala.collection.mutable.ArrayOps#ofRef.slice" + problemName=FinalMethodProblem + }, + { + matchName="scala.collection.mutable.ArrayOps#ofByte.slice" + problemName=FinalMethodProblem + }, + { + matchName="scala.collection.mutable.ArrayOps#ofLong.slice" + problemName=FinalMethodProblem + }, + { + matchName="scala.collection.mutable.ArrayOps#ofFloat.slice" + problemName=FinalMethodProblem } ] } diff --git a/bincompat-forward.whitelist.conf b/bincompat-forward.whitelist.conf index eee2d6df34..b765fb384b 100644 --- a/bincompat-forward.whitelist.conf +++ b/bincompat-forward.whitelist.conf @@ -44,6 +44,14 @@ filter { problemName=DirectMissingMethodProblem }, { + matchName="scala.reflect.runtime.SynchronizedOps.newMappedBaseTypeSeq" + problemName=DirectMissingMethodProblem + }, + { + matchName="scala.reflect.runtime.JavaUniverse.newMappedBaseTypeSeq" + problemName=DirectMissingMethodProblem + }, + { matchName="scala.collection.immutable.HashMap.contains0" problemName=DirectMissingMethodProblem }, @@ -60,6 +68,355 @@ filter { problemName=DirectMissingMethodProblem }, { + matchName="scala.reflect.api.SerializedTypeTag.serialVersionUID" + problemName=MissingFieldProblem + }, + { + matchName="scala.collection.mutable.ArrayOps$ofChar" + problemName=MissingTypesProblem + }, + { + matchName="scala.collection.mutable.ArrayOps#ofChar.sliceImpl" + problemName=DirectMissingMethodProblem + }, + { + matchName="scala.collection.mutable.ArrayOps#ofChar.emptyImpl" + problemName=DirectMissingMethodProblem + }, + { + matchName="scala.collection.mutable.ArrayOps$ofShort" + problemName=MissingTypesProblem + }, + { + matchName="scala.collection.mutable.ArrayOps#ofShort.sliceImpl" + problemName=DirectMissingMethodProblem + }, + { + matchName="scala.collection.mutable.ArrayOps#ofShort.emptyImpl" + problemName=DirectMissingMethodProblem + }, + { + matchName="scala.collection.mutable.WrappedArray#ofByte.sliceImpl" + problemName=DirectMissingMethodProblem + }, + { + matchName="scala.collection.mutable.WrappedArray#ofByte.emptyImpl" + problemName=DirectMissingMethodProblem + }, + { + matchName="scala.collection.mutable.WrappedArray#ofBoolean.sliceImpl" + problemName=DirectMissingMethodProblem + }, + { + matchName="scala.collection.mutable.WrappedArray#ofBoolean.emptyImpl" + problemName=DirectMissingMethodProblem + }, + { + matchName="scala.collection.mutable.WrappedArray#ofChar.sliceImpl" + problemName=DirectMissingMethodProblem + }, + { + matchName="scala.collection.mutable.WrappedArray#ofChar.emptyImpl" + problemName=DirectMissingMethodProblem + }, + { + matchName="scala.collection.mutable.WrappedArray#ofDouble.sliceImpl" + problemName=DirectMissingMethodProblem + }, + { + matchName="scala.collection.mutable.WrappedArray#ofDouble.emptyImpl" + problemName=DirectMissingMethodProblem + }, + { + matchName="scala.collection.mutable.ArrayOps$ofUnit" + problemName=MissingTypesProblem + }, + { + matchName="scala.collection.mutable.ArrayOps#ofUnit.sliceImpl" + problemName=DirectMissingMethodProblem + }, + { + matchName="scala.collection.mutable.ArrayOps#ofUnit.emptyImpl" + problemName=DirectMissingMethodProblem + }, + { + matchName="scala.collection.mutable.ArrayOps#ofInt.sliceImpl$extension" + problemName=DirectMissingMethodProblem + }, + { + matchName="scala.collection.mutable.ArrayOps#ofInt.emptyImpl$extension" + problemName=DirectMissingMethodProblem + }, + { + matchName="scala.collection.mutable.ArrayOps$ofInt" + problemName=MissingTypesProblem + }, + { + matchName="scala.collection.mutable.ArrayOps#ofInt.sliceImpl" + problemName=DirectMissingMethodProblem + }, + { + matchName="scala.collection.mutable.ArrayOps#ofInt.emptyImpl" + problemName=DirectMissingMethodProblem + }, + { + matchName="scala.collection.mutable.ArrayOps#ofRef.sliceImpl$extension" + problemName=DirectMissingMethodProblem + }, + { + matchName="scala.collection.mutable.ArrayOps#ofRef.emptyImpl$extension" + problemName=DirectMissingMethodProblem + }, + { + matchName="scala.collection.mutable.ArrayOps#ofChar.sliceImpl$extension" + problemName=DirectMissingMethodProblem + }, + { + matchName="scala.collection.mutable.ArrayOps#ofChar.emptyImpl$extension" + problemName=DirectMissingMethodProblem + }, + { + matchName="scala.collection.mutable.ArrayOps#ofUnit.sliceImpl$extension" + problemName=DirectMissingMethodProblem + }, + { + matchName="scala.collection.mutable.ArrayOps#ofUnit.emptyImpl$extension" + problemName=DirectMissingMethodProblem + }, + { + matchName="scala.collection.mutable.ArrayOps$ofBoolean" + problemName=MissingTypesProblem + }, + { + matchName="scala.collection.mutable.ArrayOps#ofBoolean.sliceImpl" + problemName=DirectMissingMethodProblem + }, + { + matchName="scala.collection.mutable.ArrayOps#ofBoolean.emptyImpl" + problemName=DirectMissingMethodProblem + }, + { + matchName="scala.collection.mutable.ArrayOps#ofShort.sliceImpl$extension" + problemName=DirectMissingMethodProblem + }, + { + matchName="scala.collection.mutable.ArrayOps#ofShort.emptyImpl$extension" + problemName=DirectMissingMethodProblem + }, + { + matchName="scala.collection.mutable.WrappedArray#ofShort.sliceImpl" + problemName=DirectMissingMethodProblem + }, + { + matchName="scala.collection.mutable.WrappedArray#ofShort.emptyImpl" + problemName=DirectMissingMethodProblem + }, + { + matchName="scala.collection.mutable.WrappedArray#ofRef.sliceImpl" + problemName=DirectMissingMethodProblem + }, + { + matchName="scala.collection.mutable.WrappedArray#ofRef.emptyImpl" + problemName=DirectMissingMethodProblem + }, + { + matchName="scala.collection.mutable.WrappedArray#ofUnit.sliceImpl" + problemName=DirectMissingMethodProblem + }, + { + matchName="scala.collection.mutable.WrappedArray#ofUnit.emptyImpl" + problemName=DirectMissingMethodProblem + }, + { + matchName="scala.collection.mutable.ArrayOps#ofByte.sliceImpl$extension" + problemName=DirectMissingMethodProblem + }, + { + matchName="scala.collection.mutable.ArrayOps#ofByte.emptyImpl$extension" + problemName=DirectMissingMethodProblem + }, + { + matchName="scala.collection.mutable.ArrayOps#ofDouble.sliceImpl$extension" + problemName=DirectMissingMethodProblem + }, + { + matchName="scala.collection.mutable.ArrayOps#ofDouble.emptyImpl$extension" + problemName=DirectMissingMethodProblem + }, + { + matchName="scala.collection.mutable.ArrayOpsImpl" + problemName=MissingClassProblem + }, + { + matchName="scala.collection.mutable.WrappedArray#ofInt.sliceImpl" + problemName=DirectMissingMethodProblem + }, + { + matchName="scala.collection.mutable.WrappedArray#ofInt.emptyImpl" + problemName=DirectMissingMethodProblem + }, + { + matchName="scala.collection.mutable.ArrayOps$ofDouble" + problemName=MissingTypesProblem + }, + { + matchName="scala.collection.mutable.ArrayOps#ofDouble.sliceImpl" + problemName=DirectMissingMethodProblem + }, + { + matchName="scala.collection.mutable.ArrayOps#ofDouble.emptyImpl" + problemName=DirectMissingMethodProblem + }, + { + matchName="scala.collection.mutable.ArrayOps$ofRef" + problemName=MissingTypesProblem + }, + { + matchName="scala.collection.mutable.ArrayOps#ofRef.sliceImpl" + problemName=DirectMissingMethodProblem + }, + { + matchName="scala.collection.mutable.ArrayOps#ofRef.emptyImpl" + problemName=DirectMissingMethodProblem + }, + { + matchName="scala.collection.mutable.WrappedArray#ofLong.sliceImpl" + problemName=DirectMissingMethodProblem + }, + { + matchName="scala.collection.mutable.WrappedArray#ofLong.emptyImpl" + problemName=DirectMissingMethodProblem + }, + { + matchName="scala.collection.mutable.ArrayOps$ofByte" + problemName=MissingTypesProblem + }, + { + matchName="scala.collection.mutable.ArrayOps#ofByte.sliceImpl" + problemName=DirectMissingMethodProblem + }, + { + matchName="scala.collection.mutable.ArrayOps#ofByte.emptyImpl" + problemName=DirectMissingMethodProblem + }, + { + matchName="scala.collection.mutable.ArrayOps#ofFloat.sliceImpl$extension" + problemName=DirectMissingMethodProblem + }, + { + matchName="scala.collection.mutable.ArrayOps#ofFloat.emptyImpl$extension" + problemName=DirectMissingMethodProblem + }, + { + matchName="scala.collection.mutable.ArrayOps#ofLong.sliceImpl$extension" + problemName=DirectMissingMethodProblem + }, + { + matchName="scala.collection.mutable.ArrayOps#ofLong.emptyImpl$extension" + problemName=DirectMissingMethodProblem + }, + { + matchName="scala.collection.mutable.ArrayOps#ofBoolean.sliceImpl$extension" + problemName=DirectMissingMethodProblem + }, + { + matchName="scala.collection.mutable.ArrayOps#ofBoolean.emptyImpl$extension" + problemName=DirectMissingMethodProblem + }, + { + matchName="scala.collection.mutable.WrappedArray$ofByte" + problemName=MissingTypesProblem + }, + { + matchName="scala.collection.mutable.WrappedArray$ofBoolean" + problemName=MissingTypesProblem + }, + { + matchName="scala.collection.mutable.WrappedArray$ofChar" + problemName=MissingTypesProblem + }, + { + matchName="scala.collection.mutable.WrappedArray$ofDouble" + problemName=MissingTypesProblem + }, + { + matchName="scala.collection.mutable.WrappedArray$ofShort" + problemName=MissingTypesProblem + }, + { + matchName="scala.collection.mutable.WrappedArray$ofRef" + problemName=MissingTypesProblem + }, + { + matchName="scala.collection.mutable.WrappedArray$ofUnit" + problemName=MissingTypesProblem + }, + { + matchName="scala.collection.mutable.WrappedArray$ofInt" + problemName=MissingTypesProblem + }, + { + matchName="scala.collection.mutable.WrappedArrayImpl" + problemName=MissingClassProblem + }, + { + matchName="scala.collection.mutable.WrappedArray$ofLong" + problemName=MissingTypesProblem + }, + { + matchName="scala.collection.mutable.WrappedArray$ofFloat" + problemName=MissingTypesProblem + }, + { + matchName="scala.collection.mutable.WrappedArray#ofFloat.sliceImpl" + problemName=DirectMissingMethodProblem + }, + { + matchName="scala.collection.mutable.WrappedArray#ofFloat.emptyImpl" + problemName=DirectMissingMethodProblem + }, + { + matchName="scala.collection.mutable.ArrayOps$ofLong" + problemName=MissingTypesProblem + }, + { + matchName="scala.collection.mutable.ArrayOps#ofLong.sliceImpl" + problemName=DirectMissingMethodProblem + }, + { + matchName="scala.collection.mutable.ArrayOps#ofLong.emptyImpl" + problemName=DirectMissingMethodProblem + }, + { + matchName="scala.collection.mutable.ArrayOps$ofFloat" + problemName=MissingTypesProblem + }, + { + matchName="scala.collection.mutable.ArrayOps#ofFloat.sliceImpl" + problemName=DirectMissingMethodProblem + }, + { + matchName="scala.collection.mutable.ArrayOps#ofFloat.emptyImpl" + problemName=DirectMissingMethodProblem + }, + // introduce FilteredTraversableInternal + { + matchName="scala.collection.immutable.Nil$" + problemName=MissingTypesProblem + }, + { + matchName="scala.collection.immutable.FilteredTraversableInternal" + problemName=MissingClassProblem + }, + { + matchName="scala.collection.immutable.List" + problemName=MissingTypesProblem + }, + { + matchName="scala.collection.immutable.$colon$colon" + problemName=MissingTypesProblem + }, + { matchName="scala.annotation.showAsInfix$" problemName=MissingClassProblem }, @@ -32,6 +32,7 @@ * - to modularize the Scala compiler or library further */ +import scala.build._ import VersionUtil._ // Scala dependencies: diff --git a/project/BuildSettings.scala b/project/BuildSettings.scala index 76cd888a2d..8456f91f86 100644 --- a/project/BuildSettings.scala +++ b/project/BuildSettings.scala @@ -1,3 +1,5 @@ +package scala.build + import sbt._ /** This object defines keys that should be visible with an unqualified name in all .sbt files and the command line */ diff --git a/project/GenerateAnyVals.scala b/project/GenerateAnyVals.scala index 84454cb0ed..f349bfd16b 100644 --- a/project/GenerateAnyVals.scala +++ b/project/GenerateAnyVals.scala @@ -1,3 +1,5 @@ +package scala.build + /** Code generation of the AnyVal types and their companions. */ trait GenerateAnyValReps { self: GenerateAnyVals => diff --git a/project/JarJar.scala b/project/JarJar.scala index 918060c9ee..3cb9e4cfff 100644 --- a/project/JarJar.scala +++ b/project/JarJar.scala @@ -1,3 +1,5 @@ +package scala.build + import org.pantsbuild.jarjar import org.pantsbuild.jarjar._ import org.pantsbuild.jarjar.util._ diff --git a/project/MiMa.scala b/project/MiMa.scala index ceda8f5594..fb9bb175ab 100644 --- a/project/MiMa.scala +++ b/project/MiMa.scala @@ -1,3 +1,5 @@ +package scala.build + // It would be nice to use sbt-mima-plugin here, but the plugin is missing // at least two features we need: // * ability to run MiMa twice, swapping `curr` and `prev`, to detect diff --git a/project/Osgi.scala b/project/Osgi.scala index 082fd91ed1..b05751958a 100644 --- a/project/Osgi.scala +++ b/project/Osgi.scala @@ -1,3 +1,5 @@ +package scala.build + import aQute.bnd.osgi.Builder import aQute.bnd.osgi.Constants._ import java.util.Properties diff --git a/project/ParserUtil.scala b/project/ParserUtil.scala index cdaf8831a5..bbd9129dbe 100644 --- a/project/ParserUtil.scala +++ b/project/ParserUtil.scala @@ -1,3 +1,5 @@ +package scala.build + import sbt._ import sbt.complete.Parser._ import sbt.complete.Parsers._ diff --git a/project/PartestUtil.scala b/project/PartestUtil.scala index 23570a88ec..127dcafefa 100644 --- a/project/PartestUtil.scala +++ b/project/PartestUtil.scala @@ -1,3 +1,5 @@ +package scala.build + import sbt._ import sbt.complete._, Parser._, Parsers._ diff --git a/project/Quiet.scala b/project/Quiet.scala index 0a186d8f28..8ae08ad5a6 100644 --- a/project/Quiet.scala +++ b/project/Quiet.scala @@ -1,3 +1,5 @@ +package scala.build + import sbt._ import Keys._ diff --git a/project/ScalaOptionParser.scala b/project/ScalaOptionParser.scala index 27ed1f0e6f..0208921959 100644 --- a/project/ScalaOptionParser.scala +++ b/project/ScalaOptionParser.scala @@ -1,3 +1,5 @@ +package scala.build + import ParserUtil._ import sbt._ import sbt.complete.Parser._ diff --git a/project/ScalaTool.scala b/project/ScalaTool.scala index 98e18235c4..ace547c640 100644 --- a/project/ScalaTool.scala +++ b/project/ScalaTool.scala @@ -1,3 +1,5 @@ +package scala.build + import sbt._ import org.apache.commons.lang3.SystemUtils import org.apache.commons.lang3.StringUtils.replaceEach diff --git a/project/ScriptCommands.scala b/project/ScriptCommands.scala index 8d5d09943a..f6b700f007 100644 --- a/project/ScriptCommands.scala +++ b/project/ScriptCommands.scala @@ -1,3 +1,5 @@ +package scala.build + import sbt._ import Keys._ import BuildSettings.autoImport._ diff --git a/project/VersionUtil.scala b/project/VersionUtil.scala index 7c4909697f..ebc2488345 100644 --- a/project/VersionUtil.scala +++ b/project/VersionUtil.scala @@ -1,3 +1,5 @@ +package scala.build + import sbt._ import Keys._ import java.util.Properties diff --git a/spec/05-classes-and-objects.md b/spec/05-classes-and-objects.md index 6738c7a5b7..5bd520589d 100644 --- a/spec/05-classes-and-objects.md +++ b/spec/05-classes-and-objects.md @@ -597,10 +597,12 @@ overridden in subclasses. A `final` class may not be inherited by a template. `final` is redundant for object definitions. Members of final classes or objects are implicitly also final, so the `final` modifier is generally redundant for them, too. Note, however, that -[constant value definitions](04-basic-declarations-and-definitions.html#value-declarations-and-definitions) do require -an explicit `final` modifier, even if they are defined in a final class or -object. `final` may not be applied to incomplete members, and it may not be -combined in one modifier list with `sealed`. +[constant value definitions](04-basic-declarations-and-definitions.html#value-declarations-and-definitions) +do require an explicit `final` modifier, +even if they are defined in a final class or object. +`final` is permitted for abstract classes +but it may not be applied to traits or incomplete members, +and it may not be combined in one modifier list with `sealed`. ### `sealed` The `sealed` modifier applies to class definitions. A diff --git a/spec/README.md b/spec/README.md index b19ce6441f..ad524dfdf3 100644 --- a/spec/README.md +++ b/spec/README.md @@ -8,7 +8,11 @@ Third, we'd like to support different output formats. An html page per chapter w ## Editing -We use Jekyll 2 and [Redcarpet](https://github.com/vmg/redcarpet) to generate the html. Essentially, this is what github pages use. +At the time of writing we are using Jekyll 3.3.0 and [Redcarpet 3.3.2](https://github.com/vmg/redcarpet) to generate the html. + +Check `Gemfile` for the current versions. + +We aim to track the configuration GitHub Pages use but at times differences will arise as GitHub Pages evolves. ## Building diff --git a/src/compiler/scala/tools/nsc/ast/parser/Scanners.scala b/src/compiler/scala/tools/nsc/ast/parser/Scanners.scala index 226c49ec07..d72002f0a7 100644 --- a/src/compiler/scala/tools/nsc/ast/parser/Scanners.scala +++ b/src/compiler/scala/tools/nsc/ast/parser/Scanners.scala @@ -543,24 +543,36 @@ trait Scanners extends ScannersCommon { } fetchDoubleQuote() case '\'' => + def unclosedCharLit() = { + val msg = "unclosed character literal" + // previous token was Symbol contiguous with the orphan single quote at offset + if (token == SYMBOLLIT && offset == lastOffset) { + syntaxError(s"""$msg (or use " for string literal "$strVal")""") + } else { + syntaxError(msg) + } + } def fetchSingleQuote() = { nextChar() if (isIdentifierStart(ch)) charLitOr(getIdentRest) else if (isOperatorPart(ch) && (ch != '\\')) charLitOr(getOperatorRest) + else if (ch == '\'') { + nextChar() + val advice = if (ch == '\'') { do nextChar() while (ch == '\''); " (use '\\'' for single quote)" } else "" + syntaxError(s"empty character literal${advice}") + } else if (!isAtEnd && (ch != SU && ch != CR && ch != LF || isUnicodeEscape)) { getLitChar() - if (ch == '\'') { + if (ch != '\'') unclosedCharLit() + else { nextChar() token = CHARLIT setStrVal() - } else { - syntaxError("unclosed character literal") } } - else - syntaxError("unclosed character literal") + else unclosedCharLit() } fetchSingleQuote() case '.' => @@ -792,7 +804,7 @@ trait Scanners extends ScannersCommon { next.token = kwArray(idx) } } else { - syntaxError("invalid string interpolation: `$$', `$'ident or `$'BlockExpr expected") + syntaxError(s"invalid string interpolation $$$ch, expected: $$$$, $$identifier or $${expression}") } } else { val isUnclosedLiteral = !isUnicodeEscape && (ch == SU || (!multiLine && (ch == CR || ch == LF))) @@ -983,6 +995,8 @@ trait Scanners extends ScannersCommon { def intVal: Long = intVal(negated = false) + private val zeroFloat = raw"[0.]+(?:[eE][+-]?[0-9]+)?[fFdD]?".r + /** Convert current strVal, base to float value. */ def floatVal(negated: Boolean): Float = { @@ -990,8 +1004,7 @@ trait Scanners extends ScannersCommon { val value: Float = java.lang.Float.parseFloat(strVal) if (value > Float.MaxValue) syntaxError("floating point number too large") - val zeroly = "0.fF" - if (value == 0.0f && strVal.exists(c => !zeroly.contains(c))) + if (value == 0.0f && !zeroFloat.pattern.matcher(strVal).matches) syntaxError("floating point number too small") if (negated) -value else value } catch { @@ -1010,8 +1023,7 @@ trait Scanners extends ScannersCommon { val value: Double = java.lang.Double.parseDouble(strVal) if (value > Double.MaxValue) syntaxError("double precision floating point number too large") - val zeroly = "0.dD" - if (value == 0.0d && strVal.exists(c => !zeroly.contains(c))) + if (value == 0.0d && !zeroFloat.pattern.matcher(strVal).matches) syntaxError("double precision floating point number too small") if (negated) -value else value } catch { diff --git a/src/compiler/scala/tools/nsc/classpath/DirectoryClassPath.scala b/src/compiler/scala/tools/nsc/classpath/DirectoryClassPath.scala index 1ea152b29c..fbd59eb04a 100644 --- a/src/compiler/scala/tools/nsc/classpath/DirectoryClassPath.scala +++ b/src/compiler/scala/tools/nsc/classpath/DirectoryClassPath.scala @@ -10,9 +10,10 @@ import java.util.function.IntFunction import java.util import java.util.Comparator -import scala.reflect.io.{AbstractFile, PlainFile} +import scala.reflect.io.{AbstractFile, PlainFile, PlainNioFile} import scala.tools.nsc.util.{ClassPath, ClassRepresentation} import FileUtils._ +import scala.collection.JavaConverters._ /** * A trait allowing to look for classpath entries in directories. It provides common logic for @@ -121,51 +122,78 @@ trait JFileDirectoryLookup[FileEntryType <: ClassRepresentation] extends Directo def asClassPathStrings: Seq[String] = Seq(dir.getPath) } -object JImageDirectoryLookup { - import java.nio.file._, java.net.URI, scala.collection.JavaConverters._ - def apply(): List[ClassPath] = { +object JrtClassPath { + import java.nio.file._, java.net.URI + def apply(): Option[ClassPath] = { try { val fs = FileSystems.getFileSystem(URI.create("jrt:/")) - val dir: Path = fs.getPath("/modules") - val modules = Files.list(dir).iterator().asScala.toList - modules.map(m => new JImageDirectoryLookup(fs, m.getFileName.toString)) + Some(new JrtClassPath(fs)) } catch { case _: ProviderNotFoundException | _: FileSystemNotFoundException => - Nil + None } } } -class JImageDirectoryLookup(fs: java.nio.file.FileSystem, module: String) extends DirectoryLookup[ClassFileEntryImpl] with NoSourcePaths { + +/** + * Implementation `ClassPath` based on the JDK 9 encapsulated runtime modules (JEP-220) + * + * https://bugs.openjdk.java.net/browse/JDK-8066492 is the most up to date reference + * for the structure of the jrt:// filesystem. + * + * The implementation assumes that no classes exist in the empty package. + */ +final class JrtClassPath(fs: java.nio.file.FileSystem) extends ClassPath with NoSourcePaths { import java.nio.file.Path, java.nio.file._ type F = Path - val dir: Path = fs.getPath("/modules/" + module) + private val dir: Path = fs.getPath("/packages") - protected def emptyFiles: Array[Path] = Array.empty - protected def getSubDir(packageDirName: String): Option[Path] = { - val packageDir = dir.resolve(packageDirName) - if (Files.exists(packageDir) && Files.isDirectory(packageDir)) Some(packageDir) - else None + // e.g. "java.lang" -> Seq("/modules/java.base") + private val packageToModuleBases: Map[String, Seq[Path]] = { + val ps = Files.newDirectoryStream(dir).iterator().asScala + def lookup(pack: Path): Seq[Path] = { + Files.list(pack).iterator().asScala.map(l => if (Files.isSymbolicLink(l)) Files.readSymbolicLink(l) else l).toList + } + ps.map(p => (p.toString.stripPrefix("/packages/"), lookup(p))).toMap } - protected def listChildren(dir: Path, filter: Option[Path => Boolean]): Array[Path] = { - import scala.collection.JavaConverters._ - val f = filter.getOrElse((p: Path) => true) - Files.list(dir).iterator().asScala.filter(f).toArray[Path] + + override private[nsc] def packages(inPackage: String): Seq[PackageEntry] = { + def matches(packageDottedName: String) = + if (packageDottedName.contains(".")) + packageOf(packageDottedName) == inPackage + else inPackage == "" + packageToModuleBases.keysIterator.filter(matches).map(PackageEntryImpl(_)).toVector + } + private[nsc] def classes(inPackage: String): Seq[ClassFileEntry] = { + if (inPackage == "") Nil + else { + packageToModuleBases.getOrElse(inPackage, Nil).flatMap(x => + Files.list(x.resolve(inPackage.replace('.', '/'))).iterator().asScala.filter(_.getFileName.toString.endsWith(".class"))).map(x => + ClassFileEntryImpl(new PlainNioFile(x))).toVector + } } - protected def getName(f: Path): String = f.getFileName.toString - protected def toAbstractFile(f: Path): AbstractFile = new scala.reflect.io.PlainNioFile(f) - protected def isPackage(f: Path): Boolean = Files.isDirectory(f) && mayBeValidPackage(f.getFileName.toString) + + override private[nsc] def list(inPackage: String): ClassPathEntries = + if (inPackage == "") ClassPathEntries(packages(inPackage), Nil) + else ClassPathEntries(packages(inPackage), classes(inPackage)) def asURLs: Seq[URL] = Seq(dir.toUri.toURL) - def asClassPathStrings: Seq[String] = asURLs.map(_.toString) + // We don't yet have a scheme to represent the JDK modules in our `-classpath`. + // java models them as entries in the new "module path", we'll probably need to follow this. + def asClassPathStrings: Seq[String] = Nil def findClassFile(className: String): Option[AbstractFile] = { - val relativePath = FileUtils.dirPath(className) + ".class" - val classFile = dir.resolve(relativePath) - if (Files.exists(classFile)) Some(new scala.reflect.io.PlainNioFile(classFile)) else None + if (!className.contains(".")) None + else { + val inPackage = packageOf(className) + packageToModuleBases.getOrElse(inPackage, Nil).iterator.flatMap{x => + val file = x.resolve(className.replace('.', '/') + ".class") + if (Files.exists(file)) new scala.reflect.io.PlainNioFile(file) :: Nil else Nil + }.take(1).toList.headOption + } } - override protected def createFileEntry(file: AbstractFile): ClassFileEntryImpl = ClassFileEntryImpl(file) - override protected def isMatchingFile(f: Path): Boolean = Files.isRegularFile(f) && f.getFileName.toString.endsWith(".class") - override private[nsc] def classes(inPackage: String): Seq[ClassFileEntry] = files(inPackage) + private def packageOf(dottedClassName: String): String = + dottedClassName.substring(0, dottedClassName.lastIndexOf(".")) } case class DirectoryClassPath(dir: File) extends JFileDirectoryLookup[ClassFileEntryImpl] with NoSourcePaths { diff --git a/src/compiler/scala/tools/nsc/reporters/ConsoleReporter.scala b/src/compiler/scala/tools/nsc/reporters/ConsoleReporter.scala index 99263bf834..f1f5f37c36 100644 --- a/src/compiler/scala/tools/nsc/reporters/ConsoleReporter.scala +++ b/src/compiler/scala/tools/nsc/reporters/ConsoleReporter.scala @@ -14,8 +14,10 @@ import StringOps.{countElementsAsString => countAs, trimAllTrailingSpace => trim /** This class implements a Reporter that displays messages on a text console. */ -class ConsoleReporter(val settings: Settings, reader: BufferedReader, writer: PrintWriter) extends AbstractReporter { - def this(settings: Settings) = this(settings, Console.in, new PrintWriter(Console.err, true)) +class ConsoleReporter(val settings: Settings, reader: BufferedReader, writer: PrintWriter, echoWriter: PrintWriter) extends AbstractReporter { + def this(settings: Settings) = this(settings, Console.in, new PrintWriter(Console.err, true), new PrintWriter(Console.out, true)) + def this(settings: Settings, reader: BufferedReader, writer: PrintWriter) = + this(settings, reader, writer, writer) /** Whether a short file name should be displayed before errors */ var shortname: Boolean = false @@ -41,6 +43,12 @@ class ConsoleReporter(val settings: Settings, reader: BufferedReader, writer: Pr writer.flush() } + /** Prints the message to the echoWriter, which is usually stdout. */ + override def echo(msg: String): Unit = { + echoWriter.println(trimTrailing(msg)) + echoWriter.flush() + } + /** Prints the message with the given position indication. */ def printMessage(posIn: Position, msg: String): Unit = printMessage(formatMessage(posIn, msg, shortname)) diff --git a/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala b/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala index 1a4671e15f..9129478b41 100644 --- a/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala +++ b/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala @@ -663,10 +663,9 @@ abstract class ClassfileParser { // so have to check unsafeTypeParams.isEmpty before worrying about raw type case below, // or we'll create a boatload of needless existentials. else if (classSym.isMonomorphicType || classSym.unsafeTypeParams.isEmpty) tp - else debuglogResult(s"raw type from $classSym"){ + else debuglogResult(s"raw type from $classSym") { // raw type - existentially quantify all type parameters - val eparams = typeParamsToExistentials(classSym, classSym.unsafeTypeParams) - newExistentialType(eparams, typeRef(pre, classSym, eparams.map(_.tpeHK))) + classExistentialType(pre, classSym) } case tp => assert(sig.charAt(index) != '<', s"sig=$sig, index=$index, tp=$tp") diff --git a/src/compiler/scala/tools/nsc/transform/Erasure.scala b/src/compiler/scala/tools/nsc/transform/Erasure.scala index 3ce7db35d8..e327a6658c 100644 --- a/src/compiler/scala/tools/nsc/transform/Erasure.scala +++ b/src/compiler/scala/tools/nsc/transform/Erasure.scala @@ -456,7 +456,15 @@ abstract class Erasure extends InfoTransform override def newTyper(context: Context) = new Eraser(context) class ComputeBridges(unit: CompilationUnit, root: Symbol) { - assert(phase == currentRun.erasurePhase, phase) + + class BridgesCursor(root: Symbol) extends overridingPairs.Cursor(root) { + override def parents = List(root.info.firstParent) + // Varargs bridges may need generic bridges due to the non-repeated part of the signature of the involved methods. + // The vararg bridge is generated during refchecks (probably to simplify override checking), + // but then the resulting varargs "bridge" method may itself need an actual erasure bridge. + // TODO: like javac, generate just one bridge method that wraps Seq <-> varargs and does erasure-induced casts + override def exclude(sym: Symbol) = !sym.isMethod || super.exclude(sym) + } var toBeRemoved = immutable.Set[Symbol]() val site = root.thisType @@ -464,12 +472,7 @@ abstract class Erasure extends InfoTransform val bridgeTarget = mutable.HashMap[Symbol, Symbol]() var bridges = List[Tree]() - val opc = enteringExplicitOuter { - new overridingPairs.Cursor(root) { - override def parents = List(root.info.firstParent) - override def exclude(sym: Symbol) = !sym.isMethod || super.exclude(sym) - } - } + val opc = enteringExplicitOuter { new BridgesCursor(root) } def compute(): (List[Tree], immutable.Set[Symbol]) = { while (opc.hasNext) { @@ -860,6 +863,16 @@ abstract class Erasure extends InfoTransform } } + private class DoubleDefsCursor(root: Symbol) extends Cursor(root) { + // specialized members have no type history before 'specialize', causing double def errors for curried defs + override def exclude(sym: Symbol): Boolean = ( + sym.isType + || super.exclude(sym) + || !sym.hasTypeAt(currentRun.refchecksPhase.id) + ) + override def matches(lo: Symbol, high: Symbol) = !high.isPrivate + } + /** Emit an error if there is a double definition. This can happen if: * * - A template defines two members with the same name and erased type. @@ -870,21 +883,12 @@ abstract class Erasure extends InfoTransform */ private def checkNoDoubleDefs(root: Symbol) { checkNoDeclaredDoubleDefs(root) - object opc extends Cursor(root) { - // specialized members have no type history before 'specialize', causing double def errors for curried defs - override def exclude(sym: Symbol): Boolean = ( - sym.isType - || super.exclude(sym) - || !sym.hasTypeAt(currentRun.refchecksPhase.id) - ) - override def matches(lo: Symbol, high: Symbol) = !high.isPrivate - } def isErasureDoubleDef(pair: SymbolPair) = { import pair._ log(s"Considering for erasure clash:\n$pair") !exitingRefchecks(lowType matches highType) && sameTypeAfterErasure(low, high) } - opc.iterator filter isErasureDoubleDef foreach doubleDefError + (new DoubleDefsCursor(root)).iterator filter isErasureDoubleDef foreach doubleDefError } /** Add bridge definitions to a template. This means: diff --git a/src/compiler/scala/tools/nsc/transform/UnCurry.scala b/src/compiler/scala/tools/nsc/transform/UnCurry.scala index dcffd7a6ab..f35dd6556f 100644 --- a/src/compiler/scala/tools/nsc/transform/UnCurry.scala +++ b/src/compiler/scala/tools/nsc/transform/UnCurry.scala @@ -342,12 +342,16 @@ abstract class UnCurry extends InfoTransform * the whole tree with it. */ private def replaceElidableTree(tree: Tree): Tree = { + def elisionOf(t: Type): Tree = t.typeSymbol match { + case StringClass => Literal(Constant("")) setType t + case _ => gen.mkZero(t) + } tree match { case DefDef(_,_,_,_,_,rhs) => - val rhs1 = if (rhs == EmptyTree) rhs else Block(Nil, gen.mkZero(rhs.tpe)) setType rhs.tpe + val rhs1 = if (rhs == EmptyTree) rhs else Block(Nil, elisionOf(rhs.tpe)) setType rhs.tpe deriveDefDef(tree)(_ => rhs1) setSymbol tree.symbol setType tree.tpe case _ => - gen.mkZero(tree.tpe) setType tree.tpe + elisionOf(tree.tpe) } } diff --git a/src/compiler/scala/tools/nsc/transform/patmat/MatchOptimization.scala b/src/compiler/scala/tools/nsc/transform/patmat/MatchOptimization.scala index 6fdaa79c10..dc0a457be7 100644 --- a/src/compiler/scala/tools/nsc/transform/patmat/MatchOptimization.scala +++ b/src/compiler/scala/tools/nsc/transform/patmat/MatchOptimization.scala @@ -116,8 +116,8 @@ trait MatchOptimization extends MatchTreeMaking with MatchAnalysis { case _ => } - debug.patmat("sharedPrefix: "+ sharedPrefix) - debug.patmat("suffix: "+ sharedPrefix) + debug.patmat(s"sharedPrefix: $sharedPrefix") + debug.patmat(s"suffix: $suffix") // if the shared prefix contains interesting conditions (!= True) // and the last of such interesting shared conditions reuses another treemaker's test // replace the whole sharedPrefix by a ReusingCondTreeMaker diff --git a/src/compiler/scala/tools/nsc/transform/patmat/MatchTranslation.scala b/src/compiler/scala/tools/nsc/transform/patmat/MatchTranslation.scala index 5750f8f7e7..39971590c7 100644 --- a/src/compiler/scala/tools/nsc/transform/patmat/MatchTranslation.scala +++ b/src/compiler/scala/tools/nsc/transform/patmat/MatchTranslation.scala @@ -109,25 +109,29 @@ trait MatchTranslation { // example check: List[Int] <:< ::[Int] private def extractorStep(): TranslationStep = { - def paramType = extractor.aligner.wholeType import extractor.treeMaker - // chain a type-testing extractor before the actual extractor call - // it tests the type, checks the outer pointer and casts to the expected type - // TODO: the outer check is mandated by the spec for case classes, but we do it for user-defined unapplies as well [SPEC] - // (the prefix of the argument passed to the unapply must equal the prefix of the type of the binder) - lazy val typeTest = TypeTestTreeMaker(binder, binder, paramType, paramType)(pos, extractorArgTypeTest = true) - // check whether typetest implies binder is not null, - // even though the eventual null check will be on typeTest.nextBinder - // it'll be equal to binder casted to paramType anyway (and the type test is on binder) - def extraction: TreeMaker = treeMaker(typeTest.nextBinder, typeTest impliesBinderNonNull binder, pos) // paramType = the type expected by the unapply // TODO: paramType may contain unbound type params (run/t2800, run/t3530) - val makers = ( + val makers = { + val paramType = extractor.aligner.wholeType // Statically conforms to paramType if (tpe <:< paramType) treeMaker(binder, false, pos) :: Nil - else typeTest :: extraction :: Nil - ) + else { + // chain a type-testing extractor before the actual extractor call + // it tests the type, checks the outer pointer and casts to the expected type + // TODO: the outer check is mandated by the spec for case classes, but we do it for user-defined unapplies as well [SPEC] + // (the prefix of the argument passed to the unapply must equal the prefix of the type of the binder) + val typeTest = TypeTestTreeMaker(binder, binder, paramType, paramType)(pos, extractorArgTypeTest = true) + val binderKnownNonNull = typeTest impliesBinderNonNull binder + + // check whether typetest implies binder is not null, + // even though the eventual null check will be on typeTest.nextBinder + // it'll be equal to binder casted to paramType anyway (and the type test is on binder) + typeTest :: treeMaker(typeTest.nextBinder, binderKnownNonNull, pos) :: Nil + } + } + step(makers: _*)(extractor.subBoundTrees: _*) } diff --git a/src/compiler/scala/tools/nsc/typechecker/Contexts.scala b/src/compiler/scala/tools/nsc/typechecker/Contexts.scala index d349597b14..503f64a44f 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Contexts.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Contexts.scala @@ -64,9 +64,8 @@ trait Contexts { self: Analyzer => for (imps <- allImportInfos.remove(unit)) { for (imp <- imps.reverse.distinct) { val used = allUsedSelectors(imp) - def isMask(s: ImportSelector) = s.name != nme.WILDCARD && s.rename == nme.WILDCARD - imp.tree.selectors filterNot (s => isMask(s) || used(s)) foreach { sel => + imp.tree.selectors filterNot (s => isMaskImport(s) || used(s)) foreach { sel => reporter.warning(imp posOf sel, "Unused import") } } @@ -74,6 +73,10 @@ trait Contexts { self: Analyzer => } } + def isMaskImport(s: ImportSelector): Boolean = s.name != nme.WILDCARD && s.rename == nme.WILDCARD + def isIndividualImport(s: ImportSelector): Boolean = s.name != nme.WILDCARD && s.rename != nme.WILDCARD + def isWildcardImport(s: ImportSelector): Boolean = s.name == nme.WILDCARD + var lastAccessCheckDetails: String = "" /** List of symbols to import from in a root context. Typically that @@ -1193,27 +1196,33 @@ trait Contexts { self: Analyzer => res } - final def lookupCompanionOf(original: Symbol): Symbol = { - if (original.isModuleClass) original.sourceModule - else lookupScopeEntry(original) match { - case null => NoSymbol - case entry => entry.owner.lookupCompanion(original) + final def lookupCompanionInIncompleteOwner(original: Symbol): Symbol = { + /* Search scopes in current and enclosing contexts for the definition of `symbol` */ + def lookupScopeEntry(symbol: Symbol): ScopeEntry = { + var res: ScopeEntry = null + var ctx = this + while (res == null && ctx.outer != ctx) { + val s = ctx.scope lookupSymbolEntry symbol + if (s != null) + res = s + else + ctx = ctx.outer + } + res } - } - /** Search scopes in current and enclosing contexts for the definition of `symbol` */ - private def lookupScopeEntry(symbol: Symbol): ScopeEntry = { - var res: ScopeEntry = null - var ctx = this - while (res == null && ctx.outer != ctx) { - val s = ctx.scope lookupSymbolEntry symbol - if (s != null) - res = s - else - ctx = ctx.outer + // 1) Must be owned by the same Scope, to ensure that in + // `{ class C; { ...; object C } }`, the class is not seen as a companion of the object. + // 2) Must be a class and module symbol, so that `{ class C; def C }` or `{ type T; object T }` are not companions. + lookupScopeEntry(original) match { + case null => NoSymbol + case entry => + def isCompanion(sym: Symbol): Boolean = + (original.isModule && sym.isClass || sym.isModule && original.isClass) && sym.isCoDefinedWith(original) + entry.owner.lookupNameInSameScopeAs(original, original.name.companionName).filter(isCompanion) } - res } + } //class Context /** A `Context` focussed on an `Import` tree */ diff --git a/src/compiler/scala/tools/nsc/typechecker/Namers.scala b/src/compiler/scala/tools/nsc/typechecker/Namers.scala index 395bda234b..28169c9da1 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Namers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Namers.scala @@ -1955,9 +1955,12 @@ trait Namers extends MethodSynthesis { // Doing this generally would trigger cycles; that's what we also // use the lower-level scan through the current Context as a fall back. if (!currentRun.compiles(owner)) owner.initialize - original.companionSymbol orElse { - ctx.lookupCompanionOf(original) - } + + if (original.isModuleClass) original.sourceModule + else if (!owner.isTerm && owner.hasCompleteInfo) + original.companionSymbol + else + ctx.lookupCompanionInIncompleteOwner(original) } /** A version of `Symbol#linkedClassOfClass` that works with local companions, ala `companionSymbolOf`. */ diff --git a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala index a787a7bc12..31476e86cd 100644 --- a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala +++ b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala @@ -189,7 +189,7 @@ abstract class RefChecks extends Transform { def varargBridge(member: Symbol, bridgetpe: Type): Tree = { log(s"Generating varargs bridge for ${member.fullLocationString} of type $bridgetpe") - val newFlags = (member.flags | VBRIDGE | ARTIFACT) & ~PRIVATE + val newFlags = (member.flags | VBRIDGE) & ~PRIVATE val bridge = member.cloneSymbolImpl(clazz, newFlags) setPos clazz.pos bridge.setInfo(bridgetpe.cloneInfo(bridge)) clazz.info.decls enter bridge diff --git a/src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala b/src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala index 6d883aee3d..7943187f35 100644 --- a/src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala +++ b/src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala @@ -130,8 +130,9 @@ trait SyntheticMethods extends ast.TreeDSL { */ def canEqualMethod: Tree = { syntheticCanEqual = true - createMethod(nme.canEqual_, List(AnyTpe), BooleanTpe)(m => - Ident(m.firstParam) IS_OBJ classExistentialType(clazz)) + createMethod(nme.canEqual_, List(AnyTpe), BooleanTpe) { m => + Ident(m.firstParam) IS_OBJ classExistentialType(context.prefix, clazz) + } } /* that match { case _: this.C => true ; case _ => false } diff --git a/src/compiler/scala/tools/util/PathResolver.scala b/src/compiler/scala/tools/util/PathResolver.scala index 188cabbc8d..f845656980 100644 --- a/src/compiler/scala/tools/util/PathResolver.scala +++ b/src/compiler/scala/tools/util/PathResolver.scala @@ -234,7 +234,7 @@ final class PathResolver(settings: Settings) { // Assemble the elements! def basis = List[Traversable[ClassPath]]( - JImageDirectoryLookup.apply(), // 0. The Java 9 classpath (backed by the jrt:/ virtual system) + JrtClassPath.apply(), // 0. The Java 9 classpath (backed by the jrt:/ virtual system, if available) classesInPath(javaBootClassPath), // 1. The Java bootstrap class path. contentsOfDirsInPath(javaExtDirs), // 2. The Java extension class path. classesInExpandedPath(javaUserClassPath), // 3. The Java application class path. diff --git a/src/library/scala/collection/immutable/FilteredTraversableInternal.scala b/src/library/scala/collection/immutable/FilteredTraversableInternal.scala new file mode 100644 index 0000000000..35585b7826 --- /dev/null +++ b/src/library/scala/collection/immutable/FilteredTraversableInternal.scala @@ -0,0 +1,104 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2003-2013, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ + +package scala +package collection +package immutable + +import scala.annotation.tailrec + +/** + * Optimised filter functions for List + * n.b. this is an internal class to help maintain compatibility and should not be used directly. + */ +private[immutable] trait FilteredTraversableInternal[+A, +Repr <: AnyRef with TraversableLike[A, Repr]] extends TraversableLike[A, Repr] { + + // Optimized for List + + override def filter(p: A => Boolean): Self = filterImpl(p, isFlipped = false) + + override def filterNot(p: A => Boolean): Self = filterImpl(p, isFlipped = true) + + private[this] def filterImpl(p: A => Boolean, isFlipped: Boolean): Self = { + + // everything seen so far so far is not included + @tailrec def noneIn(l: Repr): Repr = { + if (l.isEmpty) + Nil.asInstanceOf[Repr] + else { + val h = l.head + val t = l.tail + if (p(h) != isFlipped) + allIn(l, t) + else + noneIn(t) + } + } + + // everything from 'start' is included, if everything from this point is in we can return the origin + // start otherwise if we discover an element that is out we must create a new partial list. + @tailrec def allIn(start: Repr, remaining: Repr): Repr = { + if (remaining.isEmpty) + start + else { + val x = remaining.head + if (p(x) != isFlipped) + allIn(start, remaining.tail) + else + partialFill(start, remaining) + } + } + + // we have seen elements that should be included then one that should be excluded, start building + def partialFill(origStart: Repr, firstMiss: Repr): Repr = { + val newHead = new ::(origStart.head, Nil) + var toProcess = origStart.tail + var currentLast = newHead + + // we know that all elements are :: until at least firstMiss.tail + while (!(toProcess eq firstMiss)) { + val newElem = new ::(toProcess.head, Nil) + currentLast.tl = newElem + currentLast = newElem + toProcess = toProcess.tail + } + + // at this point newHead points to a list which is a duplicate of all the 'in' elements up to the first miss. + // currentLast is the last element in that list. + + // now we are going to try and share as much of the tail as we can, only moving elements across when we have to. + var next = firstMiss.tail + var nextToCopy = next // the next element we would need to copy to our list if we cant share. + while (!next.isEmpty) { + // generally recommended is next.isNonEmpty but this incurs an extra method call. + val head: A = next.head + if (p(head) != isFlipped) { + next = next.tail + } else { + // its not a match - do we have outstanding elements? + while (!(nextToCopy eq next)) { + val newElem = new ::(nextToCopy.head, Nil) + currentLast.tl = newElem + currentLast = newElem + nextToCopy = nextToCopy.tail + } + nextToCopy = next.tail + next = next.tail + } + } + + // we have remaining elements - they are unchanged attach them to the end + if (!nextToCopy.isEmpty) + currentLast.tl = nextToCopy.asInstanceOf[List[A]] + + newHead.asInstanceOf[Repr] + } + + noneIn(repr) + } +}
\ No newline at end of file diff --git a/src/library/scala/collection/immutable/List.scala b/src/library/scala/collection/immutable/List.scala index e5444533a8..e12ce7c2eb 100644 --- a/src/library/scala/collection/immutable/List.scala +++ b/src/library/scala/collection/immutable/List.scala @@ -88,6 +88,7 @@ sealed abstract class List[+A] extends AbstractSeq[A] with Product with GenericTraversableTemplate[A, List] with LinearSeqOptimized[A, List[A]] + with FilteredTraversableInternal[A, List[A]] with scala.Serializable { override def companion: GenericCompanion[List] = List @@ -163,30 +164,41 @@ sealed abstract class List[+A] extends AbstractSeq[A] // Note to developers: there exists a duplication between this function and `reflect.internal.util.Collections#map2Conserve`. // If any successful optimization attempts or other changes are made, please rehash them there too. @tailrec - def loop(mapped: ListBuffer[B], unchanged: List[A], pending: List[A]): List[B] = - if (pending.isEmpty) { - if (mapped eq null) unchanged - else mapped.prependToList(unchanged) + def loop(mappedHead: List[B] = Nil, mappedLast: ::[B], unchanged: List[A], pending: List[A]): List[B] = + if (pending.isEmpty) { + if (mappedHead eq null) unchanged + else { + mappedLast.tl = unchanged + mappedHead } + } + else { + val head0 = pending.head + val head1 = f(head0) + + if (head1 eq head0.asInstanceOf[AnyRef]) + loop(mappedHead, mappedLast, unchanged, pending.tail) else { - val head0 = pending.head - val head1 = f(head0) - - if (head1 eq head0.asInstanceOf[AnyRef]) - loop(mapped, unchanged, pending.tail) - else { - val b = if (mapped eq null) new ListBuffer[B] else mapped - var xc = unchanged - while (xc ne pending) { - b += xc.head - xc = xc.tail - } - b += head1 - val tail0 = pending.tail - loop(b, tail0, tail0) + var xc = unchanged + var mappedHead1: List[B] = mappedHead + var mappedLast1: ::[B] = mappedLast + while (xc ne pending) { + val next = new ::[B](xc.head, Nil) + if (mappedHead1 eq null) mappedHead1 = next + if (mappedLast1 ne null) mappedLast1.tl = next + mappedLast1 = next + xc = xc.tail } + val next = new ::(head1, Nil) + if (mappedHead1 eq null) mappedHead1 = next + if (mappedLast1 ne null) mappedLast1.tl = next + mappedLast1 = next + val tail0 = pending.tail + loop(mappedHead1, mappedLast1, tail0, tail0) + } - loop(null, this, this) + } + loop(null, null, this, this) } // Overridden methods from IterableLike and SeqLike or overloaded variants of such methods @@ -402,6 +414,7 @@ sealed abstract class List[+A] extends AbstractSeq[A] // Create a proxy for Java serialization that allows us to avoid mutation // during deserialization. This is the Serialization Proxy Pattern. protected final def writeReplace(): AnyRef = new List.SerializationProxy(this) + } /** The empty list. diff --git a/src/library/scala/collection/immutable/Queue.scala b/src/library/scala/collection/immutable/Queue.scala index 240b5c899e..5081b39bdc 100644 --- a/src/library/scala/collection/immutable/Queue.scala +++ b/src/library/scala/collection/immutable/Queue.scala @@ -125,7 +125,7 @@ sealed class Queue[+A] protected(protected val in: List[A], protected val out: L /** Returns a new queue with all elements provided by an `Iterable` object * added at the end of the queue. * - * The elements are prepended in the order they are given out by the + * The elements are appended in the order they are given out by the * iterator. * * @param iter an iterable object diff --git a/src/library/scala/collection/immutable/RedBlackTree.scala b/src/library/scala/collection/immutable/RedBlackTree.scala index afb4c9c552..4f2e9115fe 100644 --- a/src/library/scala/collection/immutable/RedBlackTree.scala +++ b/src/library/scala/collection/immutable/RedBlackTree.scala @@ -516,9 +516,10 @@ object RedBlackTree { * * According to {@see Integer#numberOfLeadingZeros} ceil(log_2(n)) = (32 - Integer.numberOfLeadingZeros(n - 1)) * - * We also don't store the deepest nodes in the path so the maximum path length is further reduced by one. + * Although we don't store the deepest nodes in the path during iteration, + * we potentially do so in `startFrom`. */ - val maximumHeight = 2 * (32 - Integer.numberOfLeadingZeros(root.count + 2 - 1)) - 2 - 1 + val maximumHeight = 2 * (32 - Integer.numberOfLeadingZeros(root.count + 2 - 1)) - 2 new Array[Tree[A, B]](maximumHeight) } private[this] var index = 0 diff --git a/src/library/scala/collection/mutable/ArrayOps.scala b/src/library/scala/collection/mutable/ArrayOps.scala index 29382134aa..5de3dad256 100644 --- a/src/library/scala/collection/mutable/ArrayOps.scala +++ b/src/library/scala/collection/mutable/ArrayOps.scala @@ -10,6 +10,8 @@ package scala package collection package mutable +import java.util + import scala.reflect.ClassTag import parallel.mutable.ParArray @@ -180,6 +182,23 @@ sealed trait ArrayOps[T] extends Any with ArrayLike[T, Array[T]] with CustomPara def seq = thisCollection } +/** to provide binary compat for 2.11 and 2.12 this class contains + * functionality that should be migrated to ArrayOps in 2.13 + * + */ +private[mutable] sealed trait ArrayOpsImpl[T] extends Any with ArrayOps[T] { + override final def slice(from: Int, until: Int): Array[T] = { + val start = if (from < 0) 0 else from + if (until <= start || start >= repr.length) + return emptyImpl + val end = if (until > length) length else until + sliceImpl(start, end) + } + protected def emptyImpl: Array[T] + protected def sliceImpl(from: Int, until: Int): Array[T] + +} + /** * A companion object for `ArrayOps`. * @@ -187,12 +206,24 @@ sealed trait ArrayOps[T] extends Any with ArrayLike[T, Array[T]] with CustomPara */ object ArrayOps { + private val emptyByteArray = new Array[Byte](0) + private val emptyShortArray = new Array[Short](0) + private val emptyIntArray = new Array[Int](0) + private val emptyLongArray = new Array[Long](0) + private val emptyFloatArray = new Array[Float](0) + private val emptyDoubleArray = new Array[Double](0) + private val emptyUnitArray = new Array[Unit](0) + private val emptyCharArray = new Array[Char](0) + private val emptyBooleanArray = new Array[Boolean](0) + /** A subclass of `ArrayOps` for arrays containing reference types. */ - final class ofRef[T <: AnyRef](override val repr: Array[T]) extends AnyVal with ArrayOps[T] with ArrayLike[T, Array[T]] { + final class ofRef[T <: AnyRef](override val repr: Array[T]) extends AnyVal with ArrayOpsImpl[T] with ArrayLike[T, Array[T]] { override protected[this] def thisCollection: WrappedArray[T] = new WrappedArray.ofRef[T](repr) override protected[this] def toCollection(repr: Array[T]): WrappedArray[T] = new WrappedArray.ofRef[T](repr) override protected[this] def newBuilder = new ArrayBuilder.ofRef[T]()(ClassTag[T](repr.getClass.getComponentType)) + protected override def emptyImpl:Array[T] = util.Arrays.copyOf[T](repr,0) + protected override def sliceImpl(from: Int, until: Int): Array[T] = util.Arrays.copyOfRange[T](repr, from, until) def length: Int = repr.length def apply(index: Int): T = repr(index) @@ -200,11 +231,13 @@ object ArrayOps { } /** A subclass of `ArrayOps` for arrays containing `Byte`s. */ - final class ofByte(override val repr: Array[Byte]) extends AnyVal with ArrayOps[Byte] with ArrayLike[Byte, Array[Byte]] { + final class ofByte(override val repr: Array[Byte]) extends AnyVal with ArrayOpsImpl[Byte] with ArrayLike[Byte, Array[Byte]] { override protected[this] def thisCollection: WrappedArray[Byte] = new WrappedArray.ofByte(repr) override protected[this] def toCollection(repr: Array[Byte]): WrappedArray[Byte] = new WrappedArray.ofByte(repr) override protected[this] def newBuilder = new ArrayBuilder.ofByte + protected override def emptyImpl = emptyByteArray + protected override def sliceImpl(from: Int, until: Int) = util.Arrays.copyOfRange(repr, from, until) def length: Int = repr.length def apply(index: Int): Byte = repr(index) @@ -212,11 +245,13 @@ object ArrayOps { } /** A subclass of `ArrayOps` for arrays containing `Short`s. */ - final class ofShort(override val repr: Array[Short]) extends AnyVal with ArrayOps[Short] with ArrayLike[Short, Array[Short]] { + final class ofShort(override val repr: Array[Short]) extends AnyVal with ArrayOpsImpl[Short] with ArrayLike[Short, Array[Short]] { override protected[this] def thisCollection: WrappedArray[Short] = new WrappedArray.ofShort(repr) override protected[this] def toCollection(repr: Array[Short]): WrappedArray[Short] = new WrappedArray.ofShort(repr) override protected[this] def newBuilder = new ArrayBuilder.ofShort + protected override def emptyImpl = emptyShortArray + protected override def sliceImpl(from: Int, until: Int) = util.Arrays.copyOfRange(repr, from, until) def length: Int = repr.length def apply(index: Int): Short = repr(index) @@ -224,11 +259,13 @@ object ArrayOps { } /** A subclass of `ArrayOps` for arrays containing `Char`s. */ - final class ofChar(override val repr: Array[Char]) extends AnyVal with ArrayOps[Char] with ArrayLike[Char, Array[Char]] { + final class ofChar(override val repr: Array[Char]) extends AnyVal with ArrayOpsImpl[Char] with ArrayLike[Char, Array[Char]] { override protected[this] def thisCollection: WrappedArray[Char] = new WrappedArray.ofChar(repr) override protected[this] def toCollection(repr: Array[Char]): WrappedArray[Char] = new WrappedArray.ofChar(repr) override protected[this] def newBuilder = new ArrayBuilder.ofChar + protected override def emptyImpl = emptyCharArray + protected override def sliceImpl(from: Int, until: Int) = util.Arrays.copyOfRange(repr, from, until) def length: Int = repr.length def apply(index: Int): Char = repr(index) @@ -236,11 +273,13 @@ object ArrayOps { } /** A subclass of `ArrayOps` for arrays containing `Int`s. */ - final class ofInt(override val repr: Array[Int]) extends AnyVal with ArrayOps[Int] with ArrayLike[Int, Array[Int]] { + final class ofInt(override val repr: Array[Int]) extends AnyVal with ArrayOpsImpl[Int] with ArrayLike[Int, Array[Int]] { override protected[this] def thisCollection: WrappedArray[Int] = new WrappedArray.ofInt(repr) override protected[this] def toCollection(repr: Array[Int]): WrappedArray[Int] = new WrappedArray.ofInt(repr) override protected[this] def newBuilder = new ArrayBuilder.ofInt + protected override def emptyImpl = emptyIntArray + protected override def sliceImpl(from: Int, until: Int) = util.Arrays.copyOfRange(repr, from, until) def length: Int = repr.length def apply(index: Int): Int = repr(index) @@ -248,11 +287,13 @@ object ArrayOps { } /** A subclass of `ArrayOps` for arrays containing `Long`s. */ - final class ofLong(override val repr: Array[Long]) extends AnyVal with ArrayOps[Long] with ArrayLike[Long, Array[Long]] { + final class ofLong(override val repr: Array[Long]) extends AnyVal with ArrayOpsImpl[Long] with ArrayLike[Long, Array[Long]] { override protected[this] def thisCollection: WrappedArray[Long] = new WrappedArray.ofLong(repr) override protected[this] def toCollection(repr: Array[Long]): WrappedArray[Long] = new WrappedArray.ofLong(repr) override protected[this] def newBuilder = new ArrayBuilder.ofLong + protected override def emptyImpl = emptyLongArray + protected override def sliceImpl(from: Int, until: Int) = util.Arrays.copyOfRange(repr, from, until) def length: Int = repr.length def apply(index: Int): Long = repr(index) @@ -260,11 +301,13 @@ object ArrayOps { } /** A subclass of `ArrayOps` for arrays containing `Float`s. */ - final class ofFloat(override val repr: Array[Float]) extends AnyVal with ArrayOps[Float] with ArrayLike[Float, Array[Float]] { + final class ofFloat(override val repr: Array[Float]) extends AnyVal with ArrayOpsImpl[Float] with ArrayLike[Float, Array[Float]] { override protected[this] def thisCollection: WrappedArray[Float] = new WrappedArray.ofFloat(repr) override protected[this] def toCollection(repr: Array[Float]): WrappedArray[Float] = new WrappedArray.ofFloat(repr) override protected[this] def newBuilder = new ArrayBuilder.ofFloat + protected override def emptyImpl = emptyFloatArray + protected override def sliceImpl(from: Int, until: Int) = util.Arrays.copyOfRange(repr, from, until) def length: Int = repr.length def apply(index: Int): Float = repr(index) @@ -272,11 +315,13 @@ object ArrayOps { } /** A subclass of `ArrayOps` for arrays containing `Double`s. */ - final class ofDouble(override val repr: Array[Double]) extends AnyVal with ArrayOps[Double] with ArrayLike[Double, Array[Double]] { + final class ofDouble(override val repr: Array[Double]) extends AnyVal with ArrayOpsImpl[Double] with ArrayLike[Double, Array[Double]] { override protected[this] def thisCollection: WrappedArray[Double] = new WrappedArray.ofDouble(repr) override protected[this] def toCollection(repr: Array[Double]): WrappedArray[Double] = new WrappedArray.ofDouble(repr) override protected[this] def newBuilder = new ArrayBuilder.ofDouble + protected override def emptyImpl = emptyDoubleArray + protected override def sliceImpl(from: Int, until: Int) = util.Arrays.copyOfRange(repr, from, until) def length: Int = repr.length def apply(index: Int): Double = repr(index) @@ -284,11 +329,13 @@ object ArrayOps { } /** A subclass of `ArrayOps` for arrays containing `Boolean`s. */ - final class ofBoolean(override val repr: Array[Boolean]) extends AnyVal with ArrayOps[Boolean] with ArrayLike[Boolean, Array[Boolean]] { + final class ofBoolean(override val repr: Array[Boolean]) extends AnyVal with ArrayOpsImpl[Boolean] with ArrayLike[Boolean, Array[Boolean]] { override protected[this] def thisCollection: WrappedArray[Boolean] = new WrappedArray.ofBoolean(repr) override protected[this] def toCollection(repr: Array[Boolean]): WrappedArray[Boolean] = new WrappedArray.ofBoolean(repr) override protected[this] def newBuilder = new ArrayBuilder.ofBoolean + protected override def emptyImpl = emptyBooleanArray + protected override def sliceImpl(from: Int, until: Int) = util.Arrays.copyOfRange(repr, from, until) def length: Int = repr.length def apply(index: Int): Boolean = repr(index) @@ -296,11 +343,18 @@ object ArrayOps { } /** A subclass of `ArrayOps` for arrays of `Unit` types. */ - final class ofUnit(override val repr: Array[Unit]) extends AnyVal with ArrayOps[Unit] with ArrayLike[Unit, Array[Unit]] { + final class ofUnit(override val repr: Array[Unit]) extends AnyVal with ArrayOpsImpl[Unit] with ArrayLike[Unit, Array[Unit]] { override protected[this] def thisCollection: WrappedArray[Unit] = new WrappedArray.ofUnit(repr) override protected[this] def toCollection(repr: Array[Unit]): WrappedArray[Unit] = new WrappedArray.ofUnit(repr) override protected[this] def newBuilder = new ArrayBuilder.ofUnit + protected override def emptyImpl = emptyUnitArray + protected override def sliceImpl(from: Int, until: Int) = { + // cant use util.Arrays.copyOfRange[Unit](repr, from, until) - Unit is special and doesnt compile + val res = new Array[Unit](until-from) + System.arraycopy(repr, from, res, 0, res.size) + res + } def length: Int = repr.length def apply(index: Int): Unit = repr(index) diff --git a/src/library/scala/collection/mutable/WrappedArray.scala b/src/library/scala/collection/mutable/WrappedArray.scala index 0b5ebe7e9a..d0919c4357 100644 --- a/src/library/scala/collection/mutable/WrappedArray.scala +++ b/src/library/scala/collection/mutable/WrappedArray.scala @@ -85,12 +85,26 @@ extends AbstractSeq[T] */ override protected[this] def newBuilder: Builder[T, WrappedArray[T]] = new WrappedArrayBuilder[T](elemTag) +} + +private[mutable] abstract class WrappedArrayImpl[T] extends WrappedArray[T] { + override def slice(from: Int, until: Int): WrappedArray[T] = { + val start = if (from < 0) 0 else from + if (until <= start || start >= repr.length) + return emptyImpl + val end = if (until > length) length else until + sliceImpl(start, end) + } + protected def emptyImpl: WrappedArray[T] + + protected def sliceImpl(from: Int, until: Int): WrappedArray[T] } /** A companion object used to create instances of `WrappedArray`. */ object WrappedArray { + import java.util // This is reused for all calls to empty. private val EmptyWrappedArray = new ofRef[AnyRef](new Array[AnyRef](0)) def empty[T <: AnyRef]: WrappedArray[T] = EmptyWrappedArray.asInstanceOf[WrappedArray[T]] @@ -124,7 +138,17 @@ object WrappedArray { def newBuilder[A]: Builder[A, IndexedSeq[A]] = new ArrayBuffer - final class ofRef[T <: AnyRef](val array: Array[T]) extends WrappedArray[T] with Serializable { + private val emptyWrappedByte = new ofByte(new Array[Byte](0)) + private val emptyWrappedShort = new ofShort(new Array[Short](0)) + private val emptyWrappedInt = new ofInt(new Array[Int](0)) + private val emptyWrappedLong = new ofLong(new Array[Long](0)) + private val emptyWrappedFloat = new ofFloat(new Array[Float](0)) + private val emptyWrappedDouble = new ofDouble(new Array[Double](0)) + private val emptyWrappedUnit = new ofUnit(new Array[Unit](0)) + private val emptyWrappedChar = new ofChar(new Array[Char](0)) + private val emptyWrappedBoolean = new ofBoolean(new Array[Boolean](0)) + + final class ofRef[T <: AnyRef](val array: Array[T]) extends WrappedArrayImpl[T] with Serializable { lazy val elemTag = ClassTag[T](array.getClass.getComponentType) def length: Int = array.length def apply(index: Int): T = array(index).asInstanceOf[T] @@ -134,9 +158,11 @@ object WrappedArray { case that: ofRef[_] => Arrays.equals(array.asInstanceOf[Array[AnyRef]], that.array.asInstanceOf[Array[AnyRef]]) case _ => super.equals(that) } + protected override def emptyImpl = new ofRef(util.Arrays.copyOf[T](array,0)) + protected override def sliceImpl(from: Int, until: Int) = new ofRef[T](util.Arrays.copyOfRange[T](array, from, until)) } - final class ofByte(val array: Array[Byte]) extends WrappedArray[Byte] with Serializable { + final class ofByte(val array: Array[Byte]) extends WrappedArrayImpl[Byte] with Serializable { def elemTag = ClassTag.Byte def length: Int = array.length def apply(index: Int): Byte = array(index) @@ -146,9 +172,11 @@ object WrappedArray { case that: ofByte => Arrays.equals(array, that.array) case _ => super.equals(that) } + protected override def emptyImpl = emptyWrappedByte + protected override def sliceImpl(from: Int, until: Int) = new ofByte(util.Arrays.copyOfRange(array, from, until)) } - final class ofShort(val array: Array[Short]) extends WrappedArray[Short] with Serializable { + final class ofShort(val array: Array[Short]) extends WrappedArrayImpl[Short] with Serializable { def elemTag = ClassTag.Short def length: Int = array.length def apply(index: Int): Short = array(index) @@ -158,9 +186,11 @@ object WrappedArray { case that: ofShort => Arrays.equals(array, that.array) case _ => super.equals(that) } + protected override def emptyImpl = emptyWrappedShort + protected override def sliceImpl(from: Int, until: Int) = new ofShort(util.Arrays.copyOfRange(array, from, until)) } - final class ofChar(val array: Array[Char]) extends WrappedArray[Char] with Serializable { + final class ofChar(val array: Array[Char]) extends WrappedArrayImpl[Char] with Serializable { def elemTag = ClassTag.Char def length: Int = array.length def apply(index: Int): Char = array(index) @@ -170,9 +200,11 @@ object WrappedArray { case that: ofChar => Arrays.equals(array, that.array) case _ => super.equals(that) } + protected override def emptyImpl = emptyWrappedChar + protected override def sliceImpl(from: Int, until: Int) = new ofChar(util.Arrays.copyOfRange(array, from, until)) } - final class ofInt(val array: Array[Int]) extends WrappedArray[Int] with Serializable { + final class ofInt(val array: Array[Int]) extends WrappedArrayImpl[Int] with Serializable { def elemTag = ClassTag.Int def length: Int = array.length def apply(index: Int): Int = array(index) @@ -182,9 +214,11 @@ object WrappedArray { case that: ofInt => Arrays.equals(array, that.array) case _ => super.equals(that) } + protected override def emptyImpl = emptyWrappedInt + protected override def sliceImpl(from: Int, until: Int) = new ofInt(util.Arrays.copyOfRange(array, from, until)) } - final class ofLong(val array: Array[Long]) extends WrappedArray[Long] with Serializable { + final class ofLong(val array: Array[Long]) extends WrappedArrayImpl[Long] with Serializable { def elemTag = ClassTag.Long def length: Int = array.length def apply(index: Int): Long = array(index) @@ -194,9 +228,11 @@ object WrappedArray { case that: ofLong => Arrays.equals(array, that.array) case _ => super.equals(that) } + protected override def emptyImpl = emptyWrappedLong + protected override def sliceImpl(from: Int, until: Int) = new ofLong(util.Arrays.copyOfRange(array, from, until)) } - final class ofFloat(val array: Array[Float]) extends WrappedArray[Float] with Serializable { + final class ofFloat(val array: Array[Float]) extends WrappedArrayImpl[Float] with Serializable { def elemTag = ClassTag.Float def length: Int = array.length def apply(index: Int): Float = array(index) @@ -206,9 +242,11 @@ object WrappedArray { case that: ofFloat => Arrays.equals(array, that.array) case _ => super.equals(that) } + protected override def emptyImpl = emptyWrappedFloat + protected override def sliceImpl(from: Int, until: Int) = new ofFloat(util.Arrays.copyOfRange(array, from, until)) } - final class ofDouble(val array: Array[Double]) extends WrappedArray[Double] with Serializable { + final class ofDouble(val array: Array[Double]) extends WrappedArrayImpl[Double] with Serializable { def elemTag = ClassTag.Double def length: Int = array.length def apply(index: Int): Double = array(index) @@ -218,9 +256,11 @@ object WrappedArray { case that: ofDouble => Arrays.equals(array, that.array) case _ => super.equals(that) } + protected override def emptyImpl = emptyWrappedDouble + protected override def sliceImpl(from: Int, until: Int) = new ofDouble(util.Arrays.copyOfRange(array, from, until)) } - final class ofBoolean(val array: Array[Boolean]) extends WrappedArray[Boolean] with Serializable { + final class ofBoolean(val array: Array[Boolean]) extends WrappedArrayImpl[Boolean] with Serializable { def elemTag = ClassTag.Boolean def length: Int = array.length def apply(index: Int): Boolean = array(index) @@ -230,9 +270,11 @@ object WrappedArray { case that: ofBoolean => Arrays.equals(array, that.array) case _ => super.equals(that) } + protected override def emptyImpl = emptyWrappedBoolean + protected override def sliceImpl(from: Int, until: Int) = new ofBoolean(util.Arrays.copyOfRange(array, from, until)) } - final class ofUnit(val array: Array[Unit]) extends WrappedArray[Unit] with Serializable { + final class ofUnit(val array: Array[Unit]) extends WrappedArrayImpl[Unit] with Serializable { def elemTag = ClassTag.Unit def length: Int = array.length def apply(index: Int): Unit = array(index) @@ -242,5 +284,14 @@ object WrappedArray { case that: ofUnit => array.length == that.array.length case _ => super.equals(that) } + protected override def emptyImpl = emptyWrappedUnit + protected override def sliceImpl(from: Int, until: Int) = { + // cant use + // new ofUnit(util.Arrays.copyOfRange[Unit](array, from, until)) - Unit is special and doesnt compile + // cant use util.Arrays.copyOfRange[Unit](repr, from, until) - Unit is special and doesnt compile + val res = new Array[Unit](until-from) + System.arraycopy(repr, from, res, 0, until-from) + new ofUnit(res) + } } } diff --git a/src/reflect/scala/reflect/internal/BaseTypeSeqs.scala b/src/reflect/scala/reflect/internal/BaseTypeSeqs.scala index 0ef52213e5..1cdefff2e9 100644 --- a/src/reflect/scala/reflect/internal/BaseTypeSeqs.scala +++ b/src/reflect/scala/reflect/internal/BaseTypeSeqs.scala @@ -33,6 +33,9 @@ trait BaseTypeSeqs { protected def newBaseTypeSeq(parents: List[Type], elems: Array[Type]) = new BaseTypeSeq(parents, elems) + protected def newMappedBaseTypeSeq(orig: BaseTypeSeq, f: Type => Type) = + new MappedBaseTypeSeq(orig, f) + /** Note: constructor is protected to force everyone to use the factory method newBaseTypeSeq instead. * This is necessary because when run from reflection every base type sequence needs to have a * SynchronizedBaseTypeSeq as mixin. @@ -125,7 +128,7 @@ trait BaseTypeSeqs { newBaseTypeSeq(parents, arr) } - def lateMap(f: Type => Type): BaseTypeSeq = new MappedBaseTypeSeq(this, f) + def lateMap(f: Type => Type): BaseTypeSeq = newMappedBaseTypeSeq(this, f) def exists(p: Type => Boolean): Boolean = elems exists p diff --git a/src/reflect/scala/reflect/internal/Definitions.scala b/src/reflect/scala/reflect/internal/Definitions.scala index 78a75c63d6..315af267bc 100644 --- a/src/reflect/scala/reflect/internal/Definitions.scala +++ b/src/reflect/scala/reflect/internal/Definitions.scala @@ -667,8 +667,8 @@ trait Definitions extends api.StandardDefinitions { isBundle && isBlackbox } - def isListType(tp: Type) = tp <:< classExistentialType(ListClass) - def isIterableType(tp: Type) = tp <:< classExistentialType(IterableClass) + def isListType(tp: Type) = tp.typeSymbol.isNonBottomSubClass(ListClass) + def isIterableType(tp: Type) = tp.typeSymbol.isNonBottomSubClass(IterableClass) // These "direct" calls perform no dealiasing. They are most needed when // printing types when one wants to preserve the true nature of the type. @@ -980,14 +980,10 @@ trait Definitions extends api.StandardDefinitions { * * C[E1, ..., En] forSome { E1 >: LB1 <: UB1 ... En >: LBn <: UBn }. */ - // TODO Review the way this is used. I see two potential problems: - // 1. `existentialAbstraction` here doesn't create fresh existential type symbols, it just - // uses the class type parameter symbols directly as the list of quantified symbols. - // See SI-8244 for the trouble that this can cause. - // Compare with callers of `typeParamsToExistentials` (used in Java raw type handling) - // 2. Why don't we require a prefix? Could its omission lead to wrong results in CheckabilityChecker? - def classExistentialType(clazz: Symbol): Type = - existentialAbstraction(clazz.typeParams, clazz.tpe_*) + def classExistentialType(prefix: Type, clazz: Symbol): Type = { + val eparams = typeParamsToExistentials(clazz, clazz.unsafeTypeParams) + newExistentialType(eparams, typeRef(prefix, clazz, eparams.map(_.tpeHK))) + } // members of class scala.Any diff --git a/src/reflect/scala/reflect/internal/Flags.scala b/src/reflect/scala/reflect/internal/Flags.scala index 8aa6b16e06..d5bf8b7cef 100644 --- a/src/reflect/scala/reflect/internal/Flags.scala +++ b/src/reflect/scala/reflect/internal/Flags.scala @@ -163,7 +163,7 @@ class Flags extends ModifierFlags { final val LOCKED = 1L << 39 // temporary flag to catch cyclic dependencies final val SPECIALIZED = 1L << 40 // symbol is a generated specialized member - final val VBRIDGE = 1L << 42 // symbol is a varargs bridge + final val VBRIDGE = 1L << 42 // symbol is a varargs bridge (but not a bridge at the bytecode level) final val VARARGS = 1L << 43 // symbol is a Java-style varargs method final val TRIEDCOOKING = 1L << 44 // `Cooking` has been tried on this symbol diff --git a/src/reflect/scala/reflect/internal/Names.scala b/src/reflect/scala/reflect/internal/Names.scala index 9d39ef8b42..055f7c9d5b 100644 --- a/src/reflect/scala/reflect/internal/Names.scala +++ b/src/reflect/scala/reflect/internal/Names.scala @@ -296,11 +296,13 @@ trait Names extends api.Names { */ final def pos(s: String, start: Int): Int = { var i = pos(s.charAt(0), start) - while (i + s.length() <= len) { + val sLen = s.length() + if (sLen == 1) return i + while (i + sLen <= len) { var j = 1 while (s.charAt(j) == chrs(index + i + j)) { j += 1 - if (j == s.length()) return i + if (j == sLen) return i } i = pos(s.charAt(0), i + 1) } diff --git a/src/reflect/scala/reflect/internal/ReificationSupport.scala b/src/reflect/scala/reflect/internal/ReificationSupport.scala index 1b2be64654..21320149a3 100644 --- a/src/reflect/scala/reflect/internal/ReificationSupport.scala +++ b/src/reflect/scala/reflect/internal/ReificationSupport.scala @@ -351,9 +351,13 @@ trait ReificationSupport { self: SymbolTable => List[Tree], List[Tree], ValDef, List[Tree])] = tree match { case ClassDef(mods, name, tparams, impl) => val X = if (mods.isCase) UnMkTemplate.asCase else UnMkTemplate - val X(parents, selfType, ctorMods, vparamss, earlyDefs, body) = impl - if (ctorMods.isTrait || ctorMods.hasFlag(JAVA)) None - else Some((mods, name, tparams, ctorMods, vparamss, earlyDefs, parents, selfType, body)) + impl match { + case X(parents, selfType, ctorMods, vparamss, earlyDefs, body) + if (!ctorMods.isTrait && !ctorMods.hasFlag(JAVA)) => + Some((mods, name, tparams, ctorMods, vparamss, earlyDefs, parents, selfType, body)) + case _ => + None + } case _ => None } diff --git a/src/reflect/scala/reflect/internal/Scopes.scala b/src/reflect/scala/reflect/internal/Scopes.scala index 51fb31d36d..0435a2c1cf 100644 --- a/src/reflect/scala/reflect/internal/Scopes.scala +++ b/src/reflect/scala/reflect/internal/Scopes.scala @@ -291,25 +291,6 @@ trait Scopes extends api.Scopes { self: SymbolTable => null } - final def lookupCompanion(original: Symbol): Symbol = { - lookupSymbolEntry(original) match { - case null => - case entry => - var e = lookupEntry(original.name.companionName) - while (e != null) { - // 1) Must be owned by the same Scope, to ensure that in - // `{ class C; { ...; object C } }`, the class is not seen as a companion of the object. - // 2) Must be a class and module symbol, so that `{ class C; def C }` or `{ type T; object T }` are not companions. - def isClassAndModule(sym1: Symbol, sym2: Symbol) = sym1.isClass && sym2.isModule - if ((e.owner eq entry.owner) && (isClassAndModule(original, e.sym) || isClassAndModule(e.sym, original))) { - return if (e.sym.isCoDefinedWith(original)) e.sym else NoSymbol - } - e = lookupNextEntry(e) - } - } - NoSymbol - } - /** lookup a symbol entry matching given name. * @note from Martin: I believe this is a hotspot or will be one * in future versions of the type system. I have reverted the previous @@ -345,6 +326,20 @@ trait Scopes extends api.Scopes { self: SymbolTable => e } + final def lookupNameInSameScopeAs(original: Symbol, companionName: Name): Symbol = { + lookupSymbolEntry(original) match { + case null => + case entry => + var e = lookupEntry(companionName) + while (e != null) { + if (e.owner eq entry.owner) return e.sym + e = lookupNextEntry(e) + } + } + NoSymbol + } + + /** TODO - we can test this more efficiently than checking isSubScope * in both directions. However the size test might be enough to quickly * rule out most failures. diff --git a/src/reflect/scala/reflect/internal/Types.scala b/src/reflect/scala/reflect/internal/Types.scala index 2a0fb5298b..b46f071717 100644 --- a/src/reflect/scala/reflect/internal/Types.scala +++ b/src/reflect/scala/reflect/internal/Types.scala @@ -3974,7 +3974,7 @@ trait Types * any corresponding non-variant type arguments of bt1 and bt2 are the same */ def isPopulated(tp1: Type, tp2: Type): Boolean = { - def isConsistent(tp1: Type, tp2: Type): Boolean = (tp1, tp2) match { + def isConsistent(tp1: Type, tp2: Type): Boolean = (tp1.dealias, tp2.dealias) match { case (TypeRef(pre1, sym1, args1), TypeRef(pre2, sym2, args2)) => assert(sym1 == sym2, (sym1, sym2)) ( pre1 =:= pre2 diff --git a/src/reflect/scala/reflect/internal/transform/Erasure.scala b/src/reflect/scala/reflect/internal/transform/Erasure.scala index 24f8aa88e6..07ae71538c 100644 --- a/src/reflect/scala/reflect/internal/transform/Erasure.scala +++ b/src/reflect/scala/reflect/internal/transform/Erasure.scala @@ -161,6 +161,11 @@ trait Erasure { } if (newParents eq parents) tp else ClassInfoType(newParents, decls, clazz) + + // can happen while this map is being used before erasure (e.g. when reasoning about sam types) + // the regular mapOver will cause a class cast exception because TypeBounds don't erase to TypeBounds + case _: BoundedWildcardType => tp // skip + case _ => mapOver(tp) } diff --git a/src/reflect/scala/reflect/internal/util/AbstractFileClassLoader.scala b/src/reflect/scala/reflect/internal/util/AbstractFileClassLoader.scala index 3cede1b3c5..49ab0cb30e 100644 --- a/src/reflect/scala/reflect/internal/util/AbstractFileClassLoader.scala +++ b/src/reflect/scala/reflect/internal/util/AbstractFileClassLoader.scala @@ -92,7 +92,7 @@ class AbstractFileClassLoader(val root: AbstractFile, parent: ClassLoader) } } - private val packages = mutable.Map[String, Package]() + private[this] val packages = mutable.Map[String, Package]() override def definePackage(name: String, specTitle: String, specVersion: String, specVendor: String, implTitle: String, implVersion: String, implVendor: String, sealBase: URL): Package = { throw new UnsupportedOperationException() diff --git a/src/reflect/scala/reflect/runtime/JavaUniverseForce.scala b/src/reflect/scala/reflect/runtime/JavaUniverseForce.scala index 9138ed3f02..72e21f67fe 100644 --- a/src/reflect/scala/reflect/runtime/JavaUniverseForce.scala +++ b/src/reflect/scala/reflect/runtime/JavaUniverseForce.scala @@ -459,8 +459,8 @@ trait JavaUniverseForce { self: runtime.JavaUniverse => definitions.DoubleTpe definitions.BooleanTpe definitions.ScalaNumericValueClasses - definitions.ScalaValueClassesNoUnit definitions.ScalaValueClasses + definitions.ScalaValueClassesNoUnit uncurry.VarargsSymbolAttachment uncurry.DesugaredParameterType diff --git a/src/reflect/scala/reflect/runtime/SynchronizedOps.scala b/src/reflect/scala/reflect/runtime/SynchronizedOps.scala index f0d96e0fd6..eadafc8abb 100644 --- a/src/reflect/scala/reflect/runtime/SynchronizedOps.scala +++ b/src/reflect/scala/reflect/runtime/SynchronizedOps.scala @@ -18,6 +18,12 @@ private[reflect] trait SynchronizedOps extends internal.SymbolTable if (elems.exists(_.isInstanceOf[RefinedType])) new BaseTypeSeq(parents, elems) with SynchronizedBaseTypeSeq else new BaseTypeSeq(parents, elems) + override protected def newMappedBaseTypeSeq(orig: BaseTypeSeq, f: Type => Type) = + // MappedBaseTypeSeq's are used rarely enough that we unconditionally mixin the synchronized + // wrapper, rather than doing this conditionally. A previous attempt to do that broke the "late" + // part of the "lateMap" contract in inspecting the mapped elements. + new MappedBaseTypeSeq(orig, f) with SynchronizedBaseTypeSeq + trait SynchronizedBaseTypeSeq extends BaseTypeSeq { override def apply(i: Int): Type = gilSynchronized { super.apply(i) } override def rawElem(i: Int) = gilSynchronized { super.rawElem(i) } @@ -28,11 +34,6 @@ private[reflect] trait SynchronizedOps extends internal.SymbolTable override def exists(p: Type => Boolean): Boolean = gilSynchronized { super.exists(p) } override lazy val maxDepth = gilSynchronized { maxDepthOfElems } override def toString = gilSynchronized { super.toString } - - override def lateMap(f: Type => Type): BaseTypeSeq = - // only need to synchronize BaseTypeSeqs if they contain refined types - if (map(f).toList.exists(_.isInstanceOf[RefinedType])) new MappedBaseTypeSeq(this, f) with SynchronizedBaseTypeSeq - else new MappedBaseTypeSeq(this, f) } // Scopes diff --git a/src/repl/scala/tools/nsc/interpreter/ExprTyper.scala b/src/repl/scala/tools/nsc/interpreter/ExprTyper.scala index 01e3a90950..f68705211f 100644 --- a/src/repl/scala/tools/nsc/interpreter/ExprTyper.scala +++ b/src/repl/scala/tools/nsc/interpreter/ExprTyper.scala @@ -13,6 +13,12 @@ trait ExprTyper { import global.{ reporter => _, Import => _, _ } import naming.freshInternalVarName + private def doInterpret(code: String): IR.Result = { + // interpret/interpretSynthetic may change the phase, which would have unintended effects on types. + val savedPhase = phase + try interpretSynthetic(code) finally phase = savedPhase + } + def symbolOfLine(code: String): Symbol = { def asExpr(): Symbol = { val name = freshInternalVarName() @@ -21,7 +27,7 @@ trait ExprTyper { // behind a def and strip the NullaryMethodType which wraps the expr. val line = "def " + name + " = " + code - interpretSynthetic(line) match { + doInterpret(line) match { case IR.Success => val sym0 = symbolOfTerm(name) // drop NullaryMethodType @@ -32,7 +38,7 @@ trait ExprTyper { def asDefn(): Symbol = { val old = repl.definedSymbolList.toSet - interpretSynthetic(code) match { + doInterpret(code) match { case IR.Success => repl.definedSymbolList filterNot old match { case Nil => NoSymbol @@ -43,7 +49,7 @@ trait ExprTyper { } } def asError(): Symbol = { - interpretSynthetic(code) + doInterpret(code) NoSymbol } beSilentDuring(asExpr()) orElse beSilentDuring(asDefn()) orElse asError() @@ -72,7 +78,7 @@ trait ExprTyper { def asProperType(): Option[Type] = { val name = freshInternalVarName() val line = "def %s: %s = ???" format (name, typeString) - interpretSynthetic(line) match { + doInterpret(line) match { case IR.Success => val sym0 = symbolOfTerm(name) Some(sym0.asMethod.returnType) diff --git a/src/repl/scala/tools/nsc/interpreter/Formatting.scala b/src/repl/scala/tools/nsc/interpreter/Formatting.scala deleted file mode 100644 index 4a9548730a..0000000000 --- a/src/repl/scala/tools/nsc/interpreter/Formatting.scala +++ /dev/null @@ -1,35 +0,0 @@ -/* NSC -- new Scala compiler - * Copyright 2005-2013 LAMP/EPFL - * @author Paul Phillips - */ - -package scala.tools.nsc -package interpreter - -import util.stringFromWriter - -class Formatting(indent: Int) { - - private val indentation = " " * indent - - private def indenting(code: String): Boolean = { - /** Heuristic to avoid indenting and thereby corrupting """-strings and XML literals. */ - val tokens = List("\"\"\"", "</", "/>") - val noIndent = (code contains "\n") && (tokens exists code.contains) - - !noIndent - } - /** Indent some code by the width of the scala> prompt. - * This way, compiler error messages read better. - */ - def indentCode(code: String) = stringFromWriter(str => - for (line <- code.lines) { - if (indenting(code)) str print indentation - str println line - str.flush() - } - ) -} -object Formatting { - def forPrompt(prompt: String) = new Formatting(prompt.lines.toList.last.length) -} diff --git a/src/repl/scala/tools/nsc/interpreter/IMain.scala b/src/repl/scala/tools/nsc/interpreter/IMain.scala index a351d2da95..2ae3b207b7 100644 --- a/src/repl/scala/tools/nsc/interpreter/IMain.scala +++ b/src/repl/scala/tools/nsc/interpreter/IMain.scala @@ -111,11 +111,8 @@ class IMain(initialSettings: Settings, protected val out: JPrintWriter) extends try body finally label = saved } - // the expanded prompt but without color escapes and without leading newline, for purposes of indenting - lazy val formatting = Formatting.forPrompt(replProps.promptText) lazy val reporter: ReplReporter = new ReplReporter(this) - import formatting.indentCode import reporter.{ printMessage, printUntruncatedMessage } // This exists mostly because using the reporter too early leads to deadlock. @@ -867,8 +864,8 @@ class IMain(initialSettings: Settings, protected val out: JPrintWriter) extends |${preambleHeader format lineRep.readName} |${envLines mkString (" ", ";\n ", ";\n")} |$importsPreamble - |${indentCode(toCompute)}""".stripMargin - def preambleLength = preamble.length - toCompute.length - 1 + |${toCompute}""".stripMargin + def preambleLength = preamble.length - toCompute.length val generate = (m: MemberHandler) => m extraCodeToEvaluate Request.this diff --git a/src/repl/scala/tools/nsc/interpreter/MemberHandlers.scala b/src/repl/scala/tools/nsc/interpreter/MemberHandlers.scala index d6c0dafaf2..f455e71476 100644 --- a/src/repl/scala/tools/nsc/interpreter/MemberHandlers.scala +++ b/src/repl/scala/tools/nsc/interpreter/MemberHandlers.scala @@ -213,29 +213,40 @@ trait MemberHandlers { class ImportHandler(imp: Import) extends MemberHandler(imp) { val Import(expr, selectors) = imp + def targetType = intp.global.rootMirror.getModuleIfDefined("" + expr) match { case NoSymbol => intp.typeOfExpression("" + expr) - case sym => sym.thisType + case sym => sym.tpe } - private def importableTargetMembers = importableMembers(targetType).toList - // wildcard imports, e.g. import foo._ - private def selectorWild = selectors filter (_.name == nme.USCOREkw) - // renamed imports, e.g. import foo.{ bar => baz } - private def selectorRenames = selectors map (_.rename) filterNot (_ == null) + + private def isFlattenedSymbol(sym: Symbol) = + sym.owner.isPackageClass && + sym.name.containsName(nme.NAME_JOIN_STRING) && + sym.owner.info.member(sym.name.take(sym.name.indexOf(nme.NAME_JOIN_STRING))) != NoSymbol + + private def importableTargetMembers = + importableMembers(exitingTyper(targetType)).filterNot(isFlattenedSymbol).toList + + // non-wildcard imports + private def individualSelectors = selectors filter analyzer.isIndividualImport /** Whether this import includes a wildcard import */ - val importsWildcard = selectorWild.nonEmpty + val importsWildcard = selectors exists analyzer.isWildcardImport def implicitSymbols = importedSymbols filter (_.isImplicit) def importedSymbols = individualSymbols ++ wildcardSymbols - private val selectorNames = selectorRenames filterNot (_ == nme.USCOREkw) flatMap (_.bothNames) toSet - lazy val individualSymbols: List[Symbol] = exitingTyper(importableTargetMembers filter (m => selectorNames(m.name))) - lazy val wildcardSymbols: List[Symbol] = exitingTyper(if (importsWildcard) importableTargetMembers else Nil) + lazy val importableSymbolsWithRenames = { + val selectorRenameMap = individualSelectors.flatMap(x => x.name.bothNames zip x.rename.bothNames).toMap + importableTargetMembers flatMap (m => selectorRenameMap.get(m.name) map (m -> _)) + } + + lazy val individualSymbols: List[Symbol] = importableSymbolsWithRenames map (_._1) + lazy val wildcardSymbols: List[Symbol] = if (importsWildcard) importableTargetMembers else Nil /** Complete list of names imported by a wildcard */ lazy val wildcardNames: List[Name] = wildcardSymbols map (_.name) - lazy val individualNames: List[Name] = individualSymbols map (_.name) + lazy val individualNames: List[Name] = importableSymbolsWithRenames map (_._2) /** The names imported by this statement */ override lazy val importedNames: List[Name] = wildcardNames ++ individualNames diff --git a/src/repl/scala/tools/nsc/interpreter/ReplReporter.scala b/src/repl/scala/tools/nsc/interpreter/ReplReporter.scala index 3a0b69f41e..b01d242d44 100644 --- a/src/repl/scala/tools/nsc/interpreter/ReplReporter.scala +++ b/src/repl/scala/tools/nsc/interpreter/ReplReporter.scala @@ -9,7 +9,7 @@ package interpreter import reporters._ import IMain._ -import scala.reflect.internal.util.Position +import scala.reflect.internal.util.{OffsetPosition, Position} /** Like ReplGlobal, a layer for ensuring extra functionality. */ @@ -40,14 +40,25 @@ class ReplReporter(intp: IMain) extends ConsoleReporter(intp.settings, Console.i case INFO => RESET } + private val promptLength = replProps.promptText.lines.toList.last.length + private val indentation = " " * promptLength + + // colorized console labels + override protected def clabel(severity: Severity): String = { + val label0 = super.clabel(severity) + if (replProps.colorOk) s"${severityColor(severity)}${label0}${RESET}" else label0 + } + + // shift indentation for source text entered at prompt override def print(pos: Position, msg: String, severity: Severity) { - val prefix = ( - if (replProps.colorOk) - severityColor(severity) + clabel(severity) + RESET - else - clabel(severity) - ) - printMessage(pos, prefix + msg) + val adjusted = + if (pos.source.file.name == "<console>") + new OffsetPosition(pos.source, pos.offset.getOrElse(0)) { + override def lineContent = s"${indentation}${super.lineContent}" + override def lineCaret = s"${indentation}${super.lineCaret}" + } + else pos + super.print(adjusted, msg, severity) } override def printMessage(msg: String) { @@ -63,12 +74,8 @@ class ReplReporter(intp: IMain) extends ConsoleReporter(intp.settings, Console.i else Console.println("[init] " + msg) } - override def displayPrompt() { - if (intp.totalSilence) () - else super.displayPrompt() - } + override def displayPrompt() = if (!intp.totalSilence) super.displayPrompt() override def rerunWithDetails(setting: reflect.internal.settings.MutableSettings#Setting, name: String) = s"; for details, enable `:setting $name' or `:replay $name'" - } diff --git a/src/repl/scala/tools/nsc/interpreter/Scripted.scala b/src/repl/scala/tools/nsc/interpreter/Scripted.scala index 6aef486957..8d87d98e53 100644 --- a/src/repl/scala/tools/nsc/interpreter/Scripted.scala +++ b/src/repl/scala/tools/nsc/interpreter/Scripted.scala @@ -331,7 +331,7 @@ class WriterOutputStream(writer: Writer) extends OutputStream { byteBuffer.flip() val result = decoder.decode(byteBuffer, charBuffer, /*eoi=*/ false) if (byteBuffer.remaining == 0) byteBuffer.clear() - if (charBuffer.position > 0) { + if (charBuffer.position() > 0) { charBuffer.flip() writer write charBuffer.toString charBuffer.clear() diff --git a/test/benchmarks/src/main/scala/scala/collection/immutable/ListBenchmark.scala b/test/benchmarks/src/main/scala/scala/collection/immutable/ListBenchmark.scala new file mode 100644 index 0000000000..94844dcae2 --- /dev/null +++ b/test/benchmarks/src/main/scala/scala/collection/immutable/ListBenchmark.scala @@ -0,0 +1,72 @@ +package scala.collection.immutable + +import java.util.concurrent.TimeUnit + +import org.openjdk.jmh.annotations._ + +object ListBenchmark { + case class Content(value: Int) +} + +@BenchmarkMode(Array(Mode.AverageTime)) +@Fork(2) +@Threads(1) +@Warmup(iterations = 10) +@Measurement(iterations = 10) +@OutputTimeUnit(TimeUnit.NANOSECONDS) +@State(Scope.Benchmark) +class ListBenchmark { + import ListBenchmark._ + @Param(Array("0", "1", "10", "100", "1000")) + var size: Int = _ + + var values: List[Content] = _ + var mid: Content = _ + var last: Content = _ + + + @Setup(Level.Trial) def initKeys(): Unit = { + values = List.tabulate(size)(v => Content(v)) + mid = Content(size / 2) + last = Content(Math.max(0,size -1)) + } + + @Benchmark def filter_includeAll: Any = { + values.filter(v => true) + } + + @Benchmark def filter_excludeAll: Any = { + values.filter(_ => false) + } + + @Benchmark def filter_exc_mid: Any = { + values.filter(v => v.value != mid.value) + } + + @Benchmark def filter_from_mid: Any = { + values.filter(v => v.value <= mid.value) + } + + @Benchmark def filter_exc_last: Any = { + values.filter(v => v.value != last.value) + } + + @Benchmark def filter_only_last: Any = { + values.filter(v => v.value == last.value) + } + + @Setup(Level.Trial) def initKeys(): Unit = { + values = List.tabulate(size)(n => if (n == size / 2) "mid" else "") + } + + @Benchmark def mapConserve_identity: Any = { + values.mapConserve(x => x) + } + + @Benchmark def mapConserve_modifyAll: Any = { + values.mapConserve(x => "replace") + } + @Benchmark def mapConserve_modifyMid: Any = { + values.mapConserve(x => if (x == "mid") "replace" else x) + } +} diff --git a/test/files/jvm/interpreter.check b/test/files/jvm/interpreter.check index 72d8d39fd0..6b712b93c7 100644 --- a/test/files/jvm/interpreter.check +++ b/test/files/jvm/interpreter.check @@ -278,13 +278,13 @@ scala> // both of the following should abort immediately: scala> def x => y => z <console>:1: error: '=' expected but '=>' found. -def x => y => z - ^ + def x => y => z + ^ scala> [1,2,3] <console>:1: error: illegal start of definition -[1,2,3] -^ + [1,2,3] + ^ scala> diff --git a/test/files/neg/badtok-1.check b/test/files/neg/badtok-1.check index b05bc60161..5d5a8e1f35 100644 --- a/test/files/neg/badtok-1.check +++ b/test/files/neg/badtok-1.check @@ -4,4 +4,10 @@ badtok-1.scala:2: error: unclosed character literal badtok-1.scala:2: error: unclosed character literal '42' ^ -two errors found +badtok-1.scala:6: error: empty character literal (use '\'' for single quote) +''' +^ +badtok-1.scala:9: error: unclosed character literal (or use " for string literal "abc") +'abc' + ^ +four errors found diff --git a/test/files/neg/badtok-1.scala b/test/files/neg/badtok-1.scala index 706e794946..cc7dc6cecc 100644 --- a/test/files/neg/badtok-1.scala +++ b/test/files/neg/badtok-1.scala @@ -1,2 +1,9 @@ // bug 989 '42' + + +// SI-10133 +''' + +// SI-10120 +'abc' diff --git a/test/files/neg/t5856.check b/test/files/neg/t5856.check index 08a61bdc07..306cc04177 100644 --- a/test/files/neg/t5856.check +++ b/test/files/neg/t5856.check @@ -1,4 +1,4 @@ -t5856.scala:10: error: invalid string interpolation: `$$', `$'ident or `$'BlockExpr expected +t5856.scala:10: error: invalid string interpolation $", expected: $$, $identifier or ${expression} val s9 = s"$" ^ t5856.scala:10: error: unclosed string literal diff --git a/test/files/pos/sam_erasure_boundedwild.scala b/test/files/pos/sam_erasure_boundedwild.scala new file mode 100644 index 0000000000..1ec27e0ea4 --- /dev/null +++ b/test/files/pos/sam_erasure_boundedwild.scala @@ -0,0 +1,11 @@ +class Test { + trait Q[T] { + def toArray[T](x: Array[T]): Array[T] + def toArray(): Array[T] + } + + def crashTyper: Array[_] = { + val x : Q[_] = ??? + x.toArray // crashes while doing overload resolution + } +}
\ No newline at end of file diff --git a/test/files/pos/t9331.scala b/test/files/pos/t9331.scala new file mode 100644 index 0000000000..00a667886f --- /dev/null +++ b/test/files/pos/t9331.scala @@ -0,0 +1,6 @@ +import scala.language.higherKinds + +trait Proxy[+T] +case class Stuff[+P[PP] <: Proxy[PP]]() { + // canEqual was incorrectly synthetized and started reporting a kind error. +} diff --git a/test/files/run/elidable-opt.check b/test/files/run/elidable-opt.check index 88cf98e0d1..969b9a420a 100644 --- a/test/files/run/elidable-opt.check +++ b/test/files/run/elidable-opt.check @@ -11,4 +11,4 @@ false 0 0.0 0.0 -null + diff --git a/test/files/run/elidable.check b/test/files/run/elidable.check index 88cf98e0d1..969b9a420a 100644 --- a/test/files/run/elidable.check +++ b/test/files/run/elidable.check @@ -11,4 +11,4 @@ false 0 0.0 0.0 -null + diff --git a/test/files/run/elidable.scala b/test/files/run/elidable.scala index 02785972bb..fed1c7b392 100644 --- a/test/files/run/elidable.scala +++ b/test/files/run/elidable.scala @@ -3,31 +3,36 @@ import elidable._ // runs -Xelide-below WARNING or 900 +object Fail { + def fail(msg: String): Unit = throw new IllegalStateException(s"Expected failure: $msg") +} +import Fail.fail + trait T { @elidable(FINEST) def f1() @elidable(SEVERE) def f2() - @elidable(FINEST) def f3() = assert(false, "Should have been elided.") + @elidable(FINEST) def f3() = fail("Should have been elided.") def f4() } class C extends T { def f1() = println("Good for me, I was not elided. C.f1") def f2() = println("Good for me, I was not elided. C.f2") - @elidable(FINEST) def f4() = assert(false, "Should have been elided.") + @elidable(FINEST) def f4() = fail("Should have been elided.") } object O { - @elidable(FINEST) def f1() = assert(false, "Should have been elided.") - @elidable(INFO) def f2() = assert(false, "Should have been elided.") + @elidable(FINEST) def f1() = fail("Should have been elided.") + @elidable(INFO) def f2() = fail("Should have been elided.") @elidable(SEVERE) def f3() = println("Good for me, I was not elided. O.f3") - @elidable(INFO) def f4 = assert(false, "Should have been elided (no parens).") + @elidable(INFO) def f4 = fail("Should have been elided (no parens).") } object Test { - @elidable(FINEST) def f1() = assert(false, "Should have been elided.") - @elidable(INFO) def f2() = assert(false, "Should have been elided.") + @elidable(FINEST) def f1() = fail("Should have been elided.") + @elidable(INFO) def f2() = fail("Should have been elided.") @elidable(SEVERE) def f3() = println("Good for me, I was not elided. Test.f3") - @elidable(INFO) def f4 = assert(false, "Should have been elided (no parens).") + @elidable(INFO) def f4 = fail("Should have been elided (no parens).") @elidable(FINEST) def f5() = {} @elidable(FINEST) def f6() = true @@ -38,12 +43,12 @@ object Test { @elidable(FINEST) def fb() = 1l @elidable(FINEST) def fc() = 1.0f @elidable(FINEST) def fd() = 1.0 - @elidable(FINEST) def fe() = "s" + @elidable(FINEST) def fe() = { fail("Should have been elided to empty string.") ; "hello, world" } /* variable elisions? see test/files/neg/t10068.scala - @elidable(INFO) val goner1: Int = { assert(false, "Should have been elided.") ; 42 } - @elidable(INFO) lazy val goner2: Int = { assert(false, "Should have been elided.") ; 42 } - @elidable(INFO) var goner3: Int = { assert(false, "Should have been elided.") ; 42 } + @elidable(INFO) val goner1: Int = { fail("Should have been elided.") ; 42 } + @elidable(INFO) lazy val goner2: Int = { fail("Should have been elided.") ; 42 } + @elidable(INFO) var goner3: Int = { fail("Should have been elided.") ; 42 } @elidable(INFO) var goner4: Nothing = _ */ @@ -74,6 +79,19 @@ object Test { println(fc()) println(fd()) println(fe()) + if (!fe().isEmpty) fail(s"Not empty: [${fe()}]") +/* +() +false +0 +0 +0 +0 +0 +0.0 +0.0 + // was: null +*/ // this one won't show up in the output because a call to f1 is elidable when accessed through T (c:T).f1() diff --git a/test/files/run/existentials-in-compiler.check b/test/files/run/existentials-in-compiler.check index b0d852865d..8800df0823 100644 --- a/test/files/run/existentials-in-compiler.check +++ b/test/files/run/existentials-in-compiler.check @@ -2,28 +2,28 @@ abstract trait Bippy[A <: AnyRef, B] extends AnyRef extest.Bippy[_ <: AnyRef, _] abstract trait BippyBud[A <: AnyRef, B, C <: List[A]] extends AnyRef - extest.BippyBud[A,B,C] forSome { A <: AnyRef; B; C <: List[A] } + extest.BippyBud[?0,?1,?2] forSome { type ?0 <: AnyRef; type ?1; type ?2 <: List[?0] } abstract trait BippyLike[A <: AnyRef, B <: List[A], This <: extest.BippyLike[A,B,This] with extest.Bippy[A,B]] extends AnyRef - extest.BippyLike[A,B,This] forSome { A <: AnyRef; B <: List[A]; This <: extest.BippyLike[A,B,This] with extest.Bippy[A,B] } + extest.BippyLike[?0,?1,?2] forSome { type ?0 <: AnyRef; type ?1 <: List[?0]; type ?2 <: extest.BippyLike[?0,?1,?2] with extest.Bippy[?0,?1] } abstract trait Contra[-A >: AnyRef, -B] extends AnyRef - extest.Contra[AnyRef, _] + extest.Contra[_ >: AnyRef, _] abstract trait ContraLike[-A >: AnyRef, -B >: List[A]] extends AnyRef - extest.ContraLike[A,B] forSome { -A >: AnyRef; -B >: List[A] } + extest.ContraLike[?0,?1] forSome { type ?0 >: AnyRef; type ?1 >: List[?0] } abstract trait Cov01[+A <: AnyRef, +B] extends AnyRef - extest.Cov01[AnyRef,Any] + extest.Cov01[_ <: AnyRef, _] abstract trait Cov02[+A <: AnyRef, B] extends AnyRef - extest.Cov02[AnyRef, _] + extest.Cov02[_ <: AnyRef, _] abstract trait Cov03[+A <: AnyRef, -B] extends AnyRef - extest.Cov03[AnyRef, _] + extest.Cov03[_ <: AnyRef, _] abstract trait Cov04[A <: AnyRef, +B] extends AnyRef - extest.Cov04[_ <: AnyRef, Any] + extest.Cov04[_ <: AnyRef, _] abstract trait Cov05[A <: AnyRef, B] extends AnyRef extest.Cov05[_ <: AnyRef, _] @@ -32,7 +32,7 @@ abstract trait Cov06[A <: AnyRef, -B] extends AnyRef extest.Cov06[_ <: AnyRef, _] abstract trait Cov07[-A <: AnyRef, +B] extends AnyRef - extest.Cov07[_ <: AnyRef, Any] + extest.Cov07[_ <: AnyRef, _] abstract trait Cov08[-A <: AnyRef, B] extends AnyRef extest.Cov08[_ <: AnyRef, _] @@ -41,16 +41,16 @@ abstract trait Cov09[-A <: AnyRef, -B] extends AnyRef extest.Cov09[_ <: AnyRef, _] abstract trait Cov11[+A <: AnyRef, +B <: List[_]] extends AnyRef - extest.Cov11[AnyRef,List[_]] + extest.Cov11[_ <: AnyRef, _ <: List[_]] abstract trait Cov12[+A <: AnyRef, B <: List[_]] extends AnyRef - extest.Cov12[AnyRef, _ <: List[_]] + extest.Cov12[_ <: AnyRef, _ <: List[_]] abstract trait Cov13[+A <: AnyRef, -B <: List[_]] extends AnyRef - extest.Cov13[AnyRef, _ <: List[_]] + extest.Cov13[_ <: AnyRef, _ <: List[_]] abstract trait Cov14[A <: AnyRef, +B <: List[_]] extends AnyRef - extest.Cov14[_ <: AnyRef, List[_]] + extest.Cov14[_ <: AnyRef, _ <: List[_]] abstract trait Cov15[A <: AnyRef, B <: List[_]] extends AnyRef extest.Cov15[_ <: AnyRef, _ <: List[_]] @@ -59,7 +59,7 @@ abstract trait Cov16[A <: AnyRef, -B <: List[_]] extends AnyRef extest.Cov16[_ <: AnyRef, _ <: List[_]] abstract trait Cov17[-A <: AnyRef, +B <: List[_]] extends AnyRef - extest.Cov17[_ <: AnyRef, List[_]] + extest.Cov17[_ <: AnyRef, _ <: List[_]] abstract trait Cov18[-A <: AnyRef, B <: List[_]] extends AnyRef extest.Cov18[_ <: AnyRef, _ <: List[_]] @@ -68,16 +68,16 @@ abstract trait Cov19[-A <: AnyRef, -B <: List[_]] extends AnyRef extest.Cov19[_ <: AnyRef, _ <: List[_]] abstract trait Cov21[+A, +B] extends AnyRef - extest.Cov21[Any,Any] + extest.Cov21[_, _] abstract trait Cov22[+A, B] extends AnyRef - extest.Cov22[Any, _] + extest.Cov22[_, _] abstract trait Cov23[+A, -B] extends AnyRef - extest.Cov23[Any, _] + extest.Cov23[_, _] abstract trait Cov24[A, +B] extends AnyRef - extest.Cov24[_, Any] + extest.Cov24[_, _] abstract trait Cov25[A, B] extends AnyRef extest.Cov25[_, _] @@ -86,7 +86,7 @@ abstract trait Cov26[A, -B] extends AnyRef extest.Cov26[_, _] abstract trait Cov27[-A, +B] extends AnyRef - extest.Cov27[_, Any] + extest.Cov27[_, _] abstract trait Cov28[-A, B] extends AnyRef extest.Cov28[_, _] @@ -95,43 +95,43 @@ abstract trait Cov29[-A, -B] extends AnyRef extest.Cov29[_, _] abstract trait Cov31[+A, +B, C <: (A, B)] extends AnyRef - extest.Cov31[A,B,C] forSome { +A; +B; C <: (A, B) } + extest.Cov31[?0,?1,?2] forSome { type ?0; type ?1; type ?2 <: (?0, ?1) } abstract trait Cov32[+A, B, C <: (A, B)] extends AnyRef - extest.Cov32[A,B,C] forSome { +A; B; C <: (A, B) } + extest.Cov32[?0,?1,?2] forSome { type ?0; type ?1; type ?2 <: (?0, ?1) } abstract trait Cov33[+A, -B, C <: Tuple2[A, _]] extends AnyRef - extest.Cov33[A,B,C] forSome { +A; -B; C <: Tuple2[A, _] } + extest.Cov33[?0,?1,?2] forSome { type ?0; type ?1; type ?2 <: Tuple2[?0, _] } abstract trait Cov34[A, +B, C <: (A, B)] extends AnyRef - extest.Cov34[A,B,C] forSome { A; +B; C <: (A, B) } + extest.Cov34[?0,?1,?2] forSome { type ?0; type ?1; type ?2 <: (?0, ?1) } abstract trait Cov35[A, B, C <: (A, B)] extends AnyRef - extest.Cov35[A,B,C] forSome { A; B; C <: (A, B) } + extest.Cov35[?0,?1,?2] forSome { type ?0; type ?1; type ?2 <: (?0, ?1) } abstract trait Cov36[A, -B, C <: Tuple2[A, _]] extends AnyRef - extest.Cov36[A,B,C] forSome { A; -B; C <: Tuple2[A, _] } + extest.Cov36[?0,?1,?2] forSome { type ?0; type ?1; type ?2 <: Tuple2[?0, _] } abstract trait Cov37[-A, +B, C <: Tuple2[_, B]] extends AnyRef - extest.Cov37[A,B,C] forSome { -A; +B; C <: Tuple2[_, B] } + extest.Cov37[?0,?1,?2] forSome { type ?0; type ?1; type ?2 <: Tuple2[_, ?1] } abstract trait Cov38[-A, B, C <: Tuple2[_, B]] extends AnyRef - extest.Cov38[A,B,C] forSome { -A; B; C <: Tuple2[_, B] } + extest.Cov38[?0,?1,?2] forSome { type ?0; type ?1; type ?2 <: Tuple2[_, ?1] } abstract trait Cov39[-A, -B, C <: Tuple2[_, _]] extends AnyRef extest.Cov39[_, _, _ <: Tuple2[_, _]] abstract trait Cov41[+A >: Null, +B] extends AnyRef - extest.Cov41[Any,Any] + extest.Cov41[_ >: Null, _] abstract trait Cov42[+A >: Null, B] extends AnyRef - extest.Cov42[Any, _] + extest.Cov42[_ >: Null, _] abstract trait Cov43[+A >: Null, -B] extends AnyRef - extest.Cov43[Any, _] + extest.Cov43[_ >: Null, _] abstract trait Cov44[A >: Null, +B] extends AnyRef - extest.Cov44[_ >: Null, Any] + extest.Cov44[_ >: Null, _] abstract trait Cov45[A >: Null, B] extends AnyRef extest.Cov45[_ >: Null, _] @@ -140,7 +140,7 @@ abstract trait Cov46[A >: Null, -B] extends AnyRef extest.Cov46[_ >: Null, _] abstract trait Cov47[-A >: Null, +B] extends AnyRef - extest.Cov47[_ >: Null, Any] + extest.Cov47[_ >: Null, _] abstract trait Cov48[-A >: Null, B] extends AnyRef extest.Cov48[_ >: Null, _] @@ -149,8 +149,8 @@ abstract trait Cov49[-A >: Null, -B] extends AnyRef extest.Cov49[_ >: Null, _] abstract trait Covariant[+A <: AnyRef, +B] extends AnyRef - extest.Covariant[AnyRef,Any] + extest.Covariant[_ <: AnyRef, _] abstract trait CovariantLike[+A <: AnyRef, +B <: List[A], +This <: extest.CovariantLike[A,B,This] with extest.Covariant[A,B]] extends AnyRef - extest.CovariantLike[A,B,This] forSome { +A <: AnyRef; +B <: List[A]; +This <: extest.CovariantLike[A,B,This] with extest.Covariant[A,B] } + extest.CovariantLike[?0,?1,?2] forSome { type ?0 <: AnyRef; type ?1 <: List[?0]; type ?2 <: extest.CovariantLike[?0,?1,?2] with extest.Covariant[?0,?1] } diff --git a/test/files/run/existentials-in-compiler.scala b/test/files/run/existentials-in-compiler.scala index e516eddf95..e35b7231c2 100644 --- a/test/files/run/existentials-in-compiler.scala +++ b/test/files/run/existentials-in-compiler.scala @@ -79,7 +79,7 @@ package extest { exitingTyper { clazz.info println(clazz.defString) - println(" " + classExistentialType(clazz) + "\n") + println(" " + classExistentialType(clazz.owner.typeOfThis, clazz) + "\n") } } } diff --git a/test/files/run/literals.scala b/test/files/run/literals.scala index 25501123b5..a7962e5cd9 100644 --- a/test/files/run/literals.scala +++ b/test/files/run/literals.scala @@ -6,7 +6,7 @@ object Test { - /* I add a couple of Unicode identifier tests here temporarily */ + /* I add a couple of Unicode identifier tests here "temporarily" */ def \u03b1\u03c1\u03b5\u03c4\u03b7 = "alpha rho epsilon tau eta" @@ -80,6 +80,9 @@ object Test { check_success("1e1f == 10.0f", 1e1f, 10.0f) check_success(".3f == 0.3f", .3f, 0.3f) check_success("0f == 0.0f", 0f, 0.0f) + check_success("0f == -0.000000000000000000e+00f", 0f, -0.000000000000000000e+00f) + check_success("0f == -0.000000000000000000e+00F", 0f, -0.000000000000000000e+00F) + check_success("0f == -0.0000000000000000e14f", 0f, -0.0000000000000000e14f) check_success("01.23f == 1.23f", 01.23f, 1.23f) check_success("3.14f == 3.14f", 3.14f, 3.14f) check_success("6.022e23f == 6.022e23f", 6.022e23f, 6.022e23f) @@ -96,6 +99,11 @@ object Test { check_success(".3 == 0.3", .3, 0.3) check_success("0.0 == 0.0", 0.0, 0.0) check_success("0d == 0.0", 0d, 0.0) + check_success("0d == 0.000000000000000000e+00d", 0d, 0.000000000000000000e+00d) + check_success("0d == -0.000000000000000000e+00d", 0d, -0.000000000000000000e+00d) + check_success("0d == -0.000000000000000000e+00D", 0d, -0.000000000000000000e+00D) + check_success("0.0 == 0.000000000000000000e+00", 0.0, 0.000000000000000000e+00) + check_success("0.0 == -0.000000000000000000e+00", 0.0, -0.000000000000000000e+00) check_success("01.23 == 1.23", 01.23, 1.23) check_success("01.23d == 1.23d", 01.23d, 1.23d) check_success("3.14 == 3.14", 3.14, 3.14) diff --git a/test/files/run/reify_newimpl_22.check b/test/files/run/reify_newimpl_22.check index 985f646579..b2f4d5624e 100644 --- a/test/files/run/reify_newimpl_22.check +++ b/test/files/run/reify_newimpl_22.check @@ -15,7 +15,7 @@ scala> { } println(code.eval) } -<console>:19: free term: Ident(TermName("x")) defined by res0 in <console>:18:14 +<console>:19: free term: Ident(TermName("x")) defined by res0 in <console>:18:7 val code = reify { ^ 2 diff --git a/test/files/run/reify_newimpl_23.check b/test/files/run/reify_newimpl_23.check index f60113c69f..abf314b26a 100644 --- a/test/files/run/reify_newimpl_23.check +++ b/test/files/run/reify_newimpl_23.check @@ -14,7 +14,7 @@ scala> def foo[T]{ } println(code.eval) } -<console>:17: free type: Ident(TypeName("T")) defined by foo in <console>:16:16 +<console>:17: free type: Ident(TypeName("T")) defined by foo in <console>:16:9 val code = reify { ^ foo: [T]=> Unit diff --git a/test/files/run/reify_newimpl_25.check b/test/files/run/reify_newimpl_25.check index 9104d8df0b..d446caa91a 100644 --- a/test/files/run/reify_newimpl_25.check +++ b/test/files/run/reify_newimpl_25.check @@ -5,7 +5,7 @@ scala> { val tt = implicitly[TypeTag[x.type]] println(tt) } -<console>:15: free term: Ident(TermName("x")) defined by res0 in <console>:14:14 +<console>:15: free term: Ident(TermName("x")) defined by res0 in <console>:14:7 val tt = implicitly[TypeTag[x.type]] ^ TypeTag[x.type] diff --git a/test/files/run/reify_newimpl_26.check b/test/files/run/reify_newimpl_26.check index cbb21854ba..099231bf62 100644 --- a/test/files/run/reify_newimpl_26.check +++ b/test/files/run/reify_newimpl_26.check @@ -4,7 +4,7 @@ scala> def foo[T]{ val tt = implicitly[WeakTypeTag[List[T]]] println(tt) } -<console>:13: free type: Ident(TypeName("T")) defined by foo in <console>:11:16 +<console>:13: free type: Ident(TypeName("T")) defined by foo in <console>:11:9 val tt = implicitly[WeakTypeTag[List[T]]] ^ foo: [T]=> Unit diff --git a/test/files/run/repl-colon-type.check b/test/files/run/repl-colon-type.check index 1217e8d8c2..3fdd318df6 100644 --- a/test/files/run/repl-colon-type.check +++ b/test/files/run/repl-colon-type.check @@ -1,8 +1,8 @@ scala> :type List[1, 2, 3] <console>:1: error: identifier expected but integer literal found. -List[1, 2, 3] - ^ + List[1, 2, 3] + ^ scala> :type List(1, 2, 3) List[Int] @@ -38,8 +38,8 @@ scala> :type protected lazy val f = 5 Access to protected lazy value f not permitted because enclosing object $eval in package $line13 is not a subclass of object $iw where target is defined - lazy val $result = f - ^ + lazy val $result = f + ^ scala> :type def f = 5 => Int @@ -75,7 +75,7 @@ TypeRef( ) TypeRef( TypeSymbol( - sealed abstract class List[+A] extends AbstractSeq[A] with LinearSeq[A] with Product with GenericTraversableTemplate[A,List] with LinearSeqOptimized[A,List[A]] with Serializable + sealed abstract class List[+A] extends AbstractSeq[A] with LinearSeq[A] with Product with GenericTraversableTemplate[A,List] with LinearSeqOptimized[A,List[A]] with FilteredTraversableInternal[A,List[A]] with Serializable ) args = List( @@ -142,7 +142,7 @@ TypeRef( args = List( TypeRef( TypeSymbol( - sealed abstract class List[+A] extends AbstractSeq[A] with LinearSeq[A] with Product with GenericTraversableTemplate[A,List] with LinearSeqOptimized[A,List[A]] with Serializable + sealed abstract class List[+A] extends AbstractSeq[A] with LinearSeq[A] with Product with GenericTraversableTemplate[A,List] with LinearSeqOptimized[A,List[A]] with FilteredTraversableInternal[A,List[A]] with Serializable ) args = List( @@ -175,7 +175,7 @@ PolyType( args = List( TypeRef( TypeSymbol( - sealed abstract class List[+A] extends AbstractSeq[A] with LinearSeq[A] with Product with GenericTraversableTemplate[A,List] with LinearSeqOptimized[A,List[A]] with Serializable + sealed abstract class List[+A] extends AbstractSeq[A] with LinearSeq[A] with Product with GenericTraversableTemplate[A,List] with LinearSeqOptimized[A,List[A]] with FilteredTraversableInternal[A,List[A]] with Serializable ) args = List(TypeParamTypeRef(TypeParam(T <: AnyVal))) @@ -198,7 +198,7 @@ PolyType( params = List(TermSymbol(x: T), TermSymbol(y: List[U])) resultType = TypeRef( TypeSymbol( - sealed abstract class List[+A] extends AbstractSeq[A] with LinearSeq[A] with Product with GenericTraversableTemplate[A,List] with LinearSeqOptimized[A,List[A]] with Serializable + sealed abstract class List[+A] extends AbstractSeq[A] with LinearSeq[A] with Product with GenericTraversableTemplate[A,List] with LinearSeqOptimized[A,List[A]] with FilteredTraversableInternal[A,List[A]] with Serializable ) args = List(TypeParamTypeRef(TypeParam(U >: T))) diff --git a/test/files/run/t10026.check b/test/files/run/t10026.check new file mode 100644 index 0000000000..15a62794a9 --- /dev/null +++ b/test/files/run/t10026.check @@ -0,0 +1 @@ +List(1, 2, 3) diff --git a/test/files/run/t10026.scala b/test/files/run/t10026.scala new file mode 100644 index 0000000000..a56840c8c2 --- /dev/null +++ b/test/files/run/t10026.scala @@ -0,0 +1,11 @@ +import scala.reflect.runtime.universe +import scala.tools.reflect.ToolBox + +object Test { + def main(args: Array[String]): Unit = { + val classloader = getClass.getClassLoader + val toolbox = universe.runtimeMirror(classloader).mkToolBox() + println(toolbox.compile(toolbox.parse("Array(1, 2, 3).toList")).apply()) + } +} + diff --git a/test/files/run/t1459.check b/test/files/run/t1459.check new file mode 100644 index 0000000000..93b4c5a810 --- /dev/null +++ b/test/files/run/t1459.check @@ -0,0 +1,3 @@ +JavaPrinter: one two three +InheritingPrinter extends JavaPrinter: one two three +ScalaPrinter: onetwothree diff --git a/test/files/run/t1459/InheritingPrinter.scala b/test/files/run/t1459/InheritingPrinter.scala new file mode 100644 index 0000000000..70301307f5 --- /dev/null +++ b/test/files/run/t1459/InheritingPrinter.scala @@ -0,0 +1,6 @@ +class InheritingPrinter extends JavaPrinter { + override def doit(s: String*) { + print("InheritingPrinter extends ") + super.doit(s: _*); + } +}
\ No newline at end of file diff --git a/test/files/run/t1459/JavaPrinter.java b/test/files/run/t1459/JavaPrinter.java new file mode 100644 index 0000000000..3912ea613a --- /dev/null +++ b/test/files/run/t1459/JavaPrinter.java @@ -0,0 +1,7 @@ +public class JavaPrinter implements VarArg { + public void doit(String... s) { + System.out.print("JavaPrinter: "); + for(String str : s) + System.out.print(str + " "); + } +} diff --git a/test/files/run/t1459/ScalaPrinter.scala b/test/files/run/t1459/ScalaPrinter.scala new file mode 100644 index 0000000000..46305804c2 --- /dev/null +++ b/test/files/run/t1459/ScalaPrinter.scala @@ -0,0 +1,6 @@ +class ScalaPrinter extends VarArg { + override def doit(s: String*) = { + print("ScalaPrinter: ") + s.foreach(print _) + } +}
\ No newline at end of file diff --git a/test/files/run/t1459/Test.java b/test/files/run/t1459/Test.java new file mode 100644 index 0000000000..3cf91e2e8b --- /dev/null +++ b/test/files/run/t1459/Test.java @@ -0,0 +1,15 @@ +public class Test { + public static void main(String[] args) { + VarArg jp = new JavaPrinter(); + VarArg ip = new InheritingPrinter(); + VarArg sp = new ScalaPrinter(); + doYourThing(jp); + doYourThing(ip); + doYourThing(sp); + } + + public static void doYourThing(VarArg va) { + va.doit("one", "two", "three"); + System.out.println(); + } +} diff --git a/test/files/run/t1459/VarArg.java b/test/files/run/t1459/VarArg.java new file mode 100644 index 0000000000..7039f99e7b --- /dev/null +++ b/test/files/run/t1459/VarArg.java @@ -0,0 +1,3 @@ +public interface VarArg { + void doit(String... s); +} diff --git a/test/files/run/t1459generic.check b/test/files/run/t1459generic.check new file mode 100644 index 0000000000..346fadbc0d --- /dev/null +++ b/test/files/run/t1459generic.check @@ -0,0 +1,4 @@ +Note: t1459generic/Test.java uses unchecked or unsafe operations. +Note: Recompile with -Xlint:unchecked for details. +ab +ab diff --git a/test/files/run/t1459generic/Impl.scala b/test/files/run/t1459generic/Impl.scala new file mode 100644 index 0000000000..9234e70456 --- /dev/null +++ b/test/files/run/t1459generic/Impl.scala @@ -0,0 +1,4 @@ +class Impl extends VarargGeneric[String] { + def genericOne(x: String, arg: String): String = x + arg + def genericVar(x: String, args: String*): String = x + args.head +} diff --git a/test/files/run/t1459generic/Test.java b/test/files/run/t1459generic/Test.java new file mode 100644 index 0000000000..a97158796b --- /dev/null +++ b/test/files/run/t1459generic/Test.java @@ -0,0 +1,10 @@ +public class Test { + public static void main(String[] args) throws Exception { + VarargGeneric vg = new Impl(); + System.out.println(vg.genericOne("a", "b")); + System.out.println(vg.genericVar("a", "b")); + // should not result in java.lang.AbstractMethodError: Impl.genericVar(Ljava/lang/Object;[Ljava/lang/String;)Ljava/lang/String; + // --> genericVar needs a varargs bridge (scala -> java varargs) and a standard generics bridge + // (for comparison, including genericOne, which needs only a generics bridge) + } +} diff --git a/test/files/run/t1459generic/VarargGeneric.java b/test/files/run/t1459generic/VarargGeneric.java new file mode 100644 index 0000000000..9b37a0fe3f --- /dev/null +++ b/test/files/run/t1459generic/VarargGeneric.java @@ -0,0 +1,7 @@ +public interface VarargGeneric<T> { + String genericOne(T x, String args); + // we cannot annotate this with @SafeVarargs, because + // it's in an interface. so that's why a warning from + // javac appears in the checkfile. + String genericVar(T x, String... args); +} diff --git a/test/files/run/t8918-unary-ids.check b/test/files/run/t8918-unary-ids.check index 92f02371c7..b1f16ed56a 100644 --- a/test/files/run/t8918-unary-ids.check +++ b/test/files/run/t8918-unary-ids.check @@ -5,3 +5,17 @@ Expected 41 lines, got 39 -Type in expressions to have them evaluated. -Type :help for more information. +@@ -14,4 +12,4 @@ + <console>:1: error: illegal start of simple expression +-- if (true) 1 else 2 +- ^ ++ - if (true) 1 else 2 ++ ^ + +@@ -19,4 +17,4 @@ + <console>:1: error: ';' expected but integer literal found. +-- - 1 +- ^ ++ - - 1 ++ ^ + diff --git a/test/files/run/t9013/Test.java b/test/files/run/t9013/Test.java new file mode 100644 index 0000000000..14152b16ac --- /dev/null +++ b/test/files/run/t9013/Test.java @@ -0,0 +1,20 @@ +import java.util.Comparator; + +public class Test { + public static void main(String[] args) { + ClassImplementsClass c = new ClassImplementsClass(); + + c.x("a", "b", "c"); + c.y("a", "b", "c"); + c.z("a", "b", "c"); + + VarargAbstractClass i = new ClassImplementsClass(); + + i.x("a", "b", "c"); + i.y("a", "b", "c"); + // System.out.println(i.z("a", "b", "c")); // still incurs a LinkageError. + // Perhaps due to Uncurry: + // > for every repeated Java parameter `x: T...' --> x: Array[T], except: + // > if T is an unbounded abstract type, replace --> x: Array[Object] + } +} diff --git a/test/files/run/t9013/test.scala b/test/files/run/t9013/test.scala new file mode 100644 index 0000000000..073f8d086f --- /dev/null +++ b/test/files/run/t9013/test.scala @@ -0,0 +1,18 @@ +import scala.annotation.varargs + +abstract class VarargAbstractClass[T] { + @varargs + def x(els: String*): Int + + @varargs + def y(els: String*): Int + + @varargs + def z(els: T*): Int +} +class ClassImplementsClass extends VarargAbstractClass[String] { + + override def x(els: String*): Int = els.length + override def y(els: String*): Int = els.length + override def z(els: String*): Int = els.length +} diff --git a/test/files/run/t9114.scala b/test/files/run/t9114.scala new file mode 100644 index 0000000000..656a5c7d8d --- /dev/null +++ b/test/files/run/t9114.scala @@ -0,0 +1,31 @@ +import annotation.unchecked + +class Test { + trait Two[A, B] + type One[A] = Two[A,A] + class View extends One[Any] + + def checkAny(x: Some[One[Any]]) = x match { // okay + case Some(_: View) => true + case _ => false + } + def checkAbstract[A](x: Some[One[A]]) = x match { // okay + case Some(_: View) => true + case _ => false + } + + def checkExistential(x: Some[One[_]]) = x match { + case Some(_: View) => true // compiler crash + case _ => false + } +} + +object Test { + def main(args: Array[String]): Unit = { + val t1 = new Test + val t2 = new Test + assert(t1.checkAny(Some(new t1.View))) + assert(t1.checkAbstract(Some(new t1.View))) + assert(t1.checkExistential(Some(new t1.View))) + } +} diff --git a/test/files/run/t9170.scala b/test/files/run/t9170.scala index 87471fb129..cb7971235f 100644 --- a/test/files/run/t9170.scala +++ b/test/files/run/t9170.scala @@ -48,8 +48,8 @@ object Y { def f[A](a: => A): Int at line 12 and def f[A](a: => Either[Exception,A]): Int at line 13 have same type after erasure: (a: Function0)Int - def f[A](a: => Either[Exception, A]) = 2 - ^ + def f[A](a: => Either[Exception, A]) = 2 + ^ scala> :quit""" } diff --git a/test/files/run/t9880-9881.check b/test/files/run/t9880-9881.check new file mode 100644 index 0000000000..36513e249a --- /dev/null +++ b/test/files/run/t9880-9881.check @@ -0,0 +1,36 @@ + +scala> // import in various ways + +scala> import java.util.Date +import java.util.Date + +scala> import scala.util._ +import scala.util._ + +scala> import scala.reflect.runtime.{universe => ru} +import scala.reflect.runtime.{universe=>ru} + +scala> import ru.TypeTag +import ru.TypeTag + +scala> + +scala> // show the imports + +scala> :imports + 1) import java.lang._ (...) + 2) import scala._ (...) + 3) import scala.Predef._ (...) + 4) import java.util.Date (...) + 5) import scala.util._ (...) + 6) import scala.reflect.runtime.{universe=>ru} (...) + 7) import ru.TypeTag (...) + +scala> + +scala> // should be able to define this class with the imports above + +scala> class C[T](date: Date, rand: Random, typeTag: TypeTag[T]) +defined class C + +scala> :quit diff --git a/test/files/run/t9880-9881.scala b/test/files/run/t9880-9881.scala new file mode 100644 index 0000000000..0268c8c32c --- /dev/null +++ b/test/files/run/t9880-9881.scala @@ -0,0 +1,29 @@ +import scala.tools.partest.ReplTest +import scala.tools.nsc.Settings + +object Test extends ReplTest { + + override def transformSettings(s: Settings): Settings = { + s.Yreplclassbased.value = true + s + } + + lazy val normalizeRegex = """(import\s.*)\(.*\)""".r + + override def normalize(s: String): String = normalizeRegex.replaceFirstIn(s, "$1(...)") + + def code = + """ + |// import in various ways + |import java.util.Date + |import scala.util._ + |import scala.reflect.runtime.{universe => ru} + |import ru.TypeTag + | + |// show the imports + |:imports + | + |// should be able to define this class with the imports above + |class C[T](date: Date, rand: Random, typeTag: TypeTag[T]) + """.stripMargin +} diff --git a/test/junit/scala/collection/IndexedSeqTest.scala b/test/junit/scala/collection/IndexedSeqTest.scala new file mode 100644 index 0000000000..a33849e60b --- /dev/null +++ b/test/junit/scala/collection/IndexedSeqTest.scala @@ -0,0 +1,578 @@ +package scala.collection + +import org.junit.Test +import org.junit.Ignore +import org.junit.Assert.{assertEquals, _} +import org.junit.runner.RunWith +import org.junit.runners.JUnit4 + +// with the Ant JUnit runner, it's necessary to @Ignore the abstract +// classes here, or JUnit tries to instantiate them. the annotations +// can be removed when this is merged forward (TODO 2.12.x) + +/** + * base class for testing common methods on a various implementations + * + * @tparam T the collection type + * @tparam E the element type + */ +@RunWith(classOf[JUnit4]) +@Ignore +abstract class IndexedTest[T, E] { + + protected def size = 10 + + /** + * create a new instance of the test data with known values + */ + protected def underTest(size: Int): T + + /** + * returns the value of the data that is expected to be present int the original data at index {{{index}}} + * This is conceptully the same as the normal apply operation but unavaialbe due to the base types of T not supporting apply + * + * @param index the index to use for the returned value + * @return the value at the specified index + */ + protected def expectedValueAtIndex(index: Int): E + /** + * check some simple indexed access + */ + @Test def checkIndexedAccess: Unit = { + val test = underTest(size) + for (i <- 0 until size) { + assertEquals(s" at index $i", expectedValueAtIndex(i), get(test, i)) + } + } + + /** + * check simple equallity of the initial data. + * More a test of the infra that we use in this est than a full test of equallity + */ + @Test def checkEquals: Unit = { + val test1 = underTest(size) + val test2 = underTest(size) + doAssertEquals("", test1, test2) + assertNotSame(test1, test2) + expectSameContent("basic equallity", false, test1, test2, 0, size) + } + + protected def expectSameContent(txt: String, canBeSame:Boolean, orig: T, test: T, offset: Int, len: Int): Unit = { + val txtAndState = s"$txt canBeSame $canBeSame isMutableContent $isMutableContent isTakeAllSame $isTakeAllSame offset $offset len $len length(test) ${length(test)}" + val isValidSame = canBeSame && !isMutableContent && offset == 0 && len == size + if (isValidSame && isTakeAllSame) + assertSame(txtAndState, orig, test) + else + assertNotSame(txtAndState, orig, test) + assertSame(txtAndState, len, length(test)) + for (i <- 0 until len) { + assertEquals(s" $txtAndState $i $offset $len", expectedValueAtIndex(i + offset), get(test, i)) + } + } + + /** + * check the operation of {{{take}}} when the parameter is less than the size of the test data + */ + @Test def checkTakeNormal: Unit = { + val orig = underTest(size) + for (len <- 0 until size) { + val taken = take(orig, len) + expectSameContent(s" len $len", true, orig, taken, 0, len) + } + } + + /** + * check the operation of {{{slice}}} within the bounds of the source + */ + @Test def checkSliceNormal: Unit = { + val orig = underTest(size) + for ( + from <- 0 until size; + to <- from until size) { + + val sliced = slice(orig, from, to) + expectSameContent(s"from $from, to $to", true, orig, sliced, from, to - from) + } + } + + /** + * check the operation of {{{take}}} works for size of 0 + * There is a special case tha for some implementations empty will be a singleton + */ + @Test def checkTakeEmpty: Unit = { + val orig = underTest(size) + val empty1 = take(orig, 0) + val empty2 = take(orig, 0) + assertEquals(0, length(empty1)) + if (isEmptyConstant) assertSame(empty1, empty2) + } + + /** + * check the operation of {{{slice}}} works for size of 0 + * There is a special case tha for some implementations empty will be a singleton + */ + @Test def checkSliceEmpty: Unit = { + val orig = underTest(size) + for (start <- 0 until size) { + val empty1 = slice(orig, start, start) + val empty2 = slice(orig, start, start) + assertEquals(s"start $start", 0, length(empty1)) + if (isEmptyConstant) assertSame(s"start $start", empty1, empty2) + } + } + + /** + * check the operation of {{{take}}} works for the entire content + * There is a special case that for some immutable implementations they can share the result + */ + @Test def checkTakeAll: Unit = { + val orig = underTest(size) + val all = take(orig, size) + assertEquals(size, length(all)) + expectSameContent("take all", true, orig, all, 0, size) + if (isMutableContent) + assertNotSame(orig, all) + else if (isTakeAllSame) + assertSame(orig, all) + } + + /** + * check the operation of {{{slice}}} works for the entire content + * There is a special case that for some immutable implementations they can share the result + */ + @Test def checkSliceAll: Unit = { + val orig = underTest(size) + val all = slice(orig, 0, size) + assertEquals(size, length(all)) + expectSameContent("", true, orig, all, 0, size) + if (isMutableContent) + assertNotSame(orig, all) + else if (isTakeAllSame) + assertSame(orig, all) + } + + /** + * check that take operates appropriately for negative values + * take and slice should be lenient and silently ignore any data outside valid ranges + */ + @Test def checkTakeNeg: Unit = { + val orig = underTest(size) + val e = take(orig, 0) + for (len <- List(-1, -10, -99, Int.MinValue)) { + val empty = take(orig, len) + assertEquals(s"len $len", 0, length(empty)) + if (isEmptyConstant) assertSame(s"len $len", e, empty) + } + } + + /** + * check that take operates appropriately for lengths that exceed the input size + * take and slice should be lenient and silently ignore any data outside valid ranges + */ + @Test def checkTakeTooBig: Unit = { + val orig = underTest(size) + val e = take(orig, 0) + for (len <- List(size + 1, size + 10, Int.MaxValue)) { + val all = take(orig, len) + assertEquals(s"len $len", size, length(all)) + expectSameContent("", true, orig, all, 0, size) + } + } + + /** + * check that slice operates appropriately for negative start point + * take and slice should be lenient and silently ignore any data outside valid ranges + */ + @Test def checkSliceFromNeg: Unit = { + val orig = underTest(size) + for ( + from <- List(-1, -10, -99, Int.MinValue); + to <- List(-1, 0, 1, 5)) { + val start = slice(orig, from, to) + expectSameContent(s"from $from, to $to", true, orig, start, 0, Math.max(0, to)) + } + } + + /** + * check that slice operates appropriately for out of range end values + * take and slice should be lenient and silently ignore any data outside valid ranges + */ + @Test def checkSliceToTooBig: Unit = { + val orig = underTest(size) + for ( + from <- List(-1, -10, -99, Int.MinValue, 0, 1, 5); + to <- List(size + 1, size + 10, Int.MaxValue)) { + val start = slice(orig, from, to) + val realStart = Math.max(0, from) + val realLen = size - realStart + expectSameContent(s"from $from, to $to", true, orig, start, realStart, realLen) + } + } + + /** + * check that slice operates appropriately for negative values start and ends too large + * take and slice should be lenient and silently ignore any data outside valid ranges + */ + @Test def checkSliceFromNegAndToTooBig: Unit = { + val orig = underTest(size) + for ( + from <- List(-1, -10, -99, Int.MinValue); + to <- List(size + 1, size + 10, Int.MaxValue)) { + val all = slice(orig, from, to) + expectSameContent(s"from $from, to $to", true, orig, all, 0, size) + } + } + + protected def intercept[EX <: Exception : Manifest](fn: => Any) { + try { + val res = fn + fail(s"expected exception was not thrown: $res") + } catch { + case failed: AssertionError => throw failed + case e: Exception if manifest[EX].runtimeClass.isAssignableFrom(e.getClass) => + } + } + + //accessors + //the length of underTest + def length(underTest: T): Int + + //the value at index i of underTest + def get(underTest: T, i: Int): E + + def slice(underTest: T, from: Int, to: Int): T + + def take(underTest: T, size: Int): T + + //behaviour + /** is an empty value the same JVM instance */ + def isEmptyConstant: Boolean + + /** is a take / slice that results in all the data returned return this + * This is only relevant if !isMutableContent + */ + def isTakeAllSame: Boolean + + /** is the content of the collection mutable. + * If mutable there is not data sharing allowed by take/slice, if immutable then data sharing is possible + * and tested based on isTakeAllSame + */ + def isMutableContent: Boolean + + //helpers + //delegate equals check for support arrays + def doAssertEquals(txt: String, expected: T, actual: T) + +} +package IndexedTestImpl { + import java.lang.reflect.{Array => jlArray} + import java.lang.{Boolean => jlBoolean} + import java.lang.{Byte => jlByte} + import java.lang.{Short => jlShort} + import java.lang.{Integer => jlInt} + import java.lang.{Long => jlLong} + import java.lang.{Float => jlFloat} + import java.lang.{Double => jlDouble} + import java.lang.{Character => jlChar} + + import scala.collection.immutable.{StringLike, StringOps, WrappedString} + import scala.collection.mutable + import scala.runtime.BoxedUnit + trait DataProvider[E] { + protected def expectedValueAtIndex(index: Int): E = { + val someNumber = index + jlInt.bitCount(index) + toType(someNumber) + } + + protected def toType(n: Int): E + } + trait StringTestData extends DataProvider [String] { + def toType(n: Int) = n.toString + } + trait ByteTestData extends DataProvider [Byte] { + def toType(n: Int) = n.toByte + } + trait ShortTestData extends DataProvider [Short] { + def toType(n: Int) = n.toShort + } + trait IntTestData extends DataProvider [Int] { + def toType(n: Int) = n + } + trait LongTestData extends DataProvider [Long] { + def toType(n: Int) = n + } + trait FloatTestData extends DataProvider [Float] { + def toType(n: Int) = n + } + trait DoubleTestData extends DataProvider [Double] { + def toType(n: Int) = n + } + trait CharTestData extends DataProvider [Char] { + def toType(n: Int)= (n+64).toChar + } + trait BooleanTestData extends DataProvider [Boolean] { + def toType(n: Int)= (n & 0) == 0 + } + trait UnitTestData extends DataProvider [BoxedUnit] { + def toType(n: Int)= if ((n & 0) == 0) null else BoxedUnit.UNIT + } + + @Ignore + abstract class ArrayTest[E] ( + //the object or primitive type of the array + val TYPE: Class[_]) extends IndexedTest[Array[E], E]{ + override final def length(underTest: Array[E]) = underTest.length + + override def get(underTest: Array[E], i: Int) = underTest(i) + + override def slice(underTest: Array[E], from: Int, to: Int) = underTest.slice(from, to) + + override def take(underTest: Array[E], size: Int) = underTest.take(size) + + override def isEmptyConstant = false + + override def isMutableContent = true + + override def isTakeAllSame = false + + override def doAssertEquals(txt: String, expected: Array[E], actual: Array[E]): Unit = { + assertEquals(txt, expected.mkString("'"), actual.mkString("'")) + } + + override def underTest(size: Int): Array[E] = { + val res = jlArray.newInstance(TYPE, size) + for (i <- 0 until size) { + jlArray.set(res, i, expectedValueAtIndex(i)) + } + res.asInstanceOf[Array[E]] + } + } + + + @Ignore + abstract class WrappedArrayTest[E]( + //the object or primitive type of the array + val TYPE: Class[_]) extends IndexedTest[mutable.WrappedArray[E], E] with DataProvider[E]{ + import mutable.WrappedArray + override final def length(underTest: WrappedArray[E]) = underTest.length + + override def get(underTest: WrappedArray[E], i: Int) = underTest(i) + + override def slice(underTest: WrappedArray[E], from: Int, to: Int) = underTest.slice(from, to) + + override def take(underTest: WrappedArray[E], size: Int) = underTest.take(size) + + override def isEmptyConstant = false + + override def isMutableContent = true + + override def isTakeAllSame = false + + override def doAssertEquals(txt: String, expected: WrappedArray[E], actual: WrappedArray[E]): Unit = { + assertEquals(txt, expected.mkString("'"), actual.mkString("'")) + } + + override def underTest(size: Int): WrappedArray[E] = { + val res = jlArray.newInstance(TYPE, size) + for (i <- 0 until size) { + jlArray.set(res, i, expectedValueAtIndex(i)) + } + WrappedArray.make(res.asInstanceOf[Array[E]]) + } + } + + //construct the data using java as much as possible to avoid invalidating the test + + @Ignore + abstract class MutableIndexedSeqTest[T <: mutable.Seq[E], E] extends IndexedTest[T, E] with DataProvider[E]{ + override final def length(underTest: T) = underTest.length + + override def get(underTest: T, i: Int) = underTest(i) + + override def slice(underTest: T, from: Int, to: Int) = underTest.slice(from, to).asInstanceOf[T] + + override def take(underTest: T, size: Int) = underTest.take(size).asInstanceOf[T] + + override def isEmptyConstant = false + + override def isMutableContent = true + + override def isTakeAllSame = true + + override def doAssertEquals(txt: String, expected: T, actual: T): Unit = { + assertEquals(txt, expected, actual) + } + + def createEmpty(size: Int) : T + + override protected def underTest(size: Int): T = { + val res:T = createEmpty(size) + for (i <- 0 until size) + res(i) = expectedValueAtIndex(i) + res + } + + } + @Ignore + abstract class ImmutableIndexedSeqTest[T <: SeqLike[E, T], E] extends IndexedTest[T, E] with DataProvider[E] { + override final def length(underTest: T) = underTest.length + + override def get(underTest: T, i: Int) = underTest(i) + + override def slice(underTest: T, from: Int, to: Int) = underTest.slice(from, to) + + override def take(underTest: T, size: Int) = underTest.take(size) + + override def isEmptyConstant = false + + override def isMutableContent = false + + override def isTakeAllSame = true + + override def doAssertEquals(txt: String, expected: T, actual: T): Unit = { + assertEquals(txt, expected, actual) + } + + } + @Ignore + abstract class StringOpsBaseTest extends IndexedTest[StringOps, Char] with DataProvider[Char] { + override final def length(underTest: StringOps) = underTest.length + + override def get(underTest: StringOps, i: Int) = underTest(i) + + override def slice(underTest: StringOps, from: Int, to: Int) = underTest.slice(from, to) + + override def take(underTest: StringOps, size: Int) = underTest.take(size) + + override def isEmptyConstant = false + + override def isMutableContent = false + + override def isTakeAllSame = false + + override def doAssertEquals(txt: String, expected: StringOps, actual: StringOps): Unit = { + assertEquals(txt, expected, actual) + } + + } + + class BooleanArrayTest extends ArrayTest[Boolean](jlBoolean.TYPE) with BooleanTestData + class ByteArrayTest extends ArrayTest[Byte](jlByte.TYPE) with ByteTestData + class ShortArrayTest extends ArrayTest[Short](jlShort.TYPE) with ShortTestData + class IntArrayTest extends ArrayTest[Int](jlInt.TYPE) with IntTestData + class LongArrayTest extends ArrayTest[Long](jlLong.TYPE) with LongTestData + class DoubleArrayTest extends ArrayTest[Double](jlDouble.TYPE) with DoubleTestData + class FloatArrayTest extends ArrayTest[Float](jlFloat.TYPE) with FloatTestData + class CharArrayTest extends ArrayTest[Char](jlChar.TYPE) with CharTestData + class UnitArrayTest extends ArrayTest[BoxedUnit](null) with UnitTestData { + override def underTest(size: Int): Array[BoxedUnit] = { + val res = new Array[Unit](size) + for (i <- 0 until size) { + jlArray.set(res, i, expectedValueAtIndex(i)) + } + res.asInstanceOf[Array[BoxedUnit]] + } + } + class RefArrayTest extends ArrayTest[String](classOf[String]) with StringTestData + + class BooleanWrappedArrayTest extends WrappedArrayTest[Boolean](jlBoolean.TYPE) with BooleanTestData + class ByteWrappedArrayTest extends WrappedArrayTest[Byte](jlByte.TYPE) with ByteTestData + class ShortWrappedArrayTest extends WrappedArrayTest[Short](jlShort.TYPE) with ShortTestData + class IntWrappedArrayTest extends WrappedArrayTest[Int](jlInt.TYPE) with IntTestData + class LongWrappedArrayTest extends WrappedArrayTest[Long](jlLong.TYPE) with LongTestData + class DoubleWrappedArrayTest extends WrappedArrayTest[Double](jlDouble.TYPE) with DoubleTestData + class FloatWrappedArrayTest extends WrappedArrayTest[Float](jlFloat.TYPE) with FloatTestData + class CharWrappedArrayTest extends WrappedArrayTest[Char](jlChar.TYPE) with CharTestData + class UnitWrappedArrayTest extends WrappedArrayTest[BoxedUnit](null) with UnitTestData { + import mutable.WrappedArray + override def underTest(size: Int): WrappedArray[BoxedUnit] = { + val res = new Array[Unit](size) + for (i <- 0 until size) { + jlArray.set(res, i, expectedValueAtIndex(i)) + } + WrappedArray.make(res.asInstanceOf[Array[Unit]]) + } + } + class RefWrappedArrayTest extends WrappedArrayTest[String](classOf[String]) with StringTestData + + class ListBufferTest extends MutableIndexedSeqTest[mutable.ListBuffer[String], String] with StringTestData { + import mutable.ListBuffer + override def createEmpty(size: Int): ListBuffer[String] = { + val res = new ListBuffer[String] + for (i <- 0 until size) + res += expectedValueAtIndex(i) + res + } + } + class ArraySeqTest extends MutableIndexedSeqTest[mutable.ArraySeq[String], String] with StringTestData { + import mutable.ArraySeq + override def createEmpty(size: Int): ArraySeq[String] = { + val res = new ArraySeq[String](size) + for (i <- 0 until size) + res (i) = expectedValueAtIndex(i) + res + } + } + class ArrayBufferTest extends MutableIndexedSeqTest[mutable.ArrayBuffer[String], String] with StringTestData { + import mutable.ArrayBuffer + override def createEmpty(size: Int): ArrayBuffer[String] = { + val res = new ArrayBuffer[String](size) + for (i <- 0 until size) + res += expectedValueAtIndex(i) + res + } + } + class ListTest extends ImmutableIndexedSeqTest[List[String], String] with StringTestData { + + override protected def underTest(size: Int): List[String] = { + var res:List[String] = Nil + var index = size-1 + while (index >= 0) { + res = expectedValueAtIndex(index) :: res + index -= 1 + } + res + } + } + class StringBuilderTest extends MutableIndexedSeqTest[StringBuilder, Char] with CharTestData { + + override def createEmpty(size: Int): StringBuilder = new StringBuilder(size) + + override protected def underTest(size: Int): StringBuilder = { + var res = createEmpty(size) + for (i <- 0 until size) + res += expectedValueAtIndex(i) + res + } + } + class StringOpsTest extends StringOpsBaseTest with CharTestData { + + override protected def underTest(size: Int): StringOps = { + var res = new StringBuilder(size) + for (i <- 0 until size) + res += expectedValueAtIndex(i) + res.toString + } + } + class WrappedStringTest extends ImmutableIndexedSeqTest[WrappedString, Char] with CharTestData { + + override def isTakeAllSame: Boolean = false + + override protected def underTest(size: Int): WrappedString = { + var res = new StringBuilder(size) + for (i <- 0 until size) + res += expectedValueAtIndex(i) + new WrappedString(res.toString) + } + } + class VectorTest extends ImmutableIndexedSeqTest[Vector[String], String] with StringTestData { + + override protected def underTest(size: Int): Vector[String] = { + var res = Vector.newBuilder[String] + for (i <- 0 until size) + res += expectedValueAtIndex(i) + res.result() + } + } + +} diff --git a/test/junit/scala/reflect/internal/NamesTest.scala b/test/junit/scala/reflect/internal/NamesTest.scala index 549c10abed..d6182e7cca 100644 --- a/test/junit/scala/reflect/internal/NamesTest.scala +++ b/test/junit/scala/reflect/internal/NamesTest.scala @@ -92,4 +92,29 @@ class NamesTest { assert(h1 string_== h2) assert(h1 string_== h1y) } + + @Test + def pos(): Unit = { + def check(nameString: String, sub: String) = { + val name = TermName(nameString) + val javaResult = name.toString.indexOf(sub) match { case -1 => name.length case x => x } + val nameResult = name.pos(sub) + assertEquals(javaResult, nameResult) + if (sub.length == 1) { + val nameResultChar = name.pos(sub.head) + assertEquals(javaResult, nameResultChar) + } + } + + check("a", "a") // was "String index out of range: 1 + check("a", "b") + check("a", "ab") + check("a", "ba") + check("ab", "a") + check("ab", "b") + check("ab", "ab") + check("ab", "ba") + check("", "x") + check("", "xy") + } } diff --git a/test/junit/scala/tools/nsc/classpath/JrtClassPathTest.scala b/test/junit/scala/tools/nsc/classpath/JrtClassPathTest.scala new file mode 100644 index 0000000000..2c3c5134da --- /dev/null +++ b/test/junit/scala/tools/nsc/classpath/JrtClassPathTest.scala @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2014 Contributor. All rights reserved. + */ +package scala.tools.nsc.classpath + +import org.junit.Assert._ +import org.junit.Test +import org.junit.runner.RunWith +import org.junit.runners.JUnit4 + +import scala.tools.nsc.Settings +import scala.tools.nsc.backend.jvm.AsmUtils +import scala.tools.nsc.util.ClassPath +import scala.tools.util.PathResolver + +@RunWith(classOf[JUnit4]) +class JrtClassPathTest { + + @Test def lookupJavaClasses(): Unit = { + val specVersion = scala.util.Properties.javaSpecVersion + // Run the test using the JDK8 or 9 provider for rt.jar depending on the platform the test is running on. + val cp: ClassPath = + if (specVersion == "" || specVersion == "1.8") { + val settings = new Settings() + val resolver = new PathResolver(settings) + val elements = new ClassPathFactory(settings).classesInPath(resolver.Calculated.javaBootClassPath) + AggregateClassPath(elements) + } + else JrtClassPath().get + + assertEquals(Nil, cp.classes("")) + assertTrue(cp.packages("java").toString, cp.packages("java").exists(_.name == "java.lang")) + assertTrue(cp.classes("java.lang").exists(_.name == "Object")) + val jl_Object = cp.classes("java.lang").find(_.name == "Object").get + assertEquals("java/lang/Object", AsmUtils.classFromBytes(jl_Object.file.toByteArray).name) + assertTrue(cp.list("java.lang").packages.exists(_.name == "java.lang.annotation")) + assertTrue(cp.list("java.lang").classesAndSources.exists(_.name == "Object")) + assertTrue(cp.findClass("java.lang.Object").isDefined) + assertTrue(cp.findClassFile("java.lang.Object").isDefined) + } +} diff --git a/test/junit/scala/tools/nsc/interpreter/ScriptedTest.scala b/test/junit/scala/tools/nsc/interpreter/ScriptedTest.scala index 01d17110d6..e9f1336623 100644 --- a/test/junit/scala/tools/nsc/interpreter/ScriptedTest.scala +++ b/test/junit/scala/tools/nsc/interpreter/ScriptedTest.scala @@ -96,7 +96,7 @@ class ScriptedTest { } @Test def `on compile error`(): Unit = { val engine = scripted - val err = "not found: value foo in def f = foo at line number 11 at column number 16" + val err = "not found: value foo in def f = foo at line number 11 at column number 9" assertThrows[ScriptException](engine.compile("def f = foo"), _ == err) } } diff --git a/test/scalacheck/duration.scala b/test/scalacheck/duration.scala index 89cb9ff955..fc861b886a 100644 --- a/test/scalacheck/duration.scala +++ b/test/scalacheck/duration.scala @@ -32,7 +32,10 @@ object DurationTest extends Properties("Division of Duration by Long") { val genClose = for { a <- weightedLong if a != 0 - b <- choose(Long.MaxValue / a - 10, Long.MaxValue / a + 10) + val center = Long.MaxValue / a + b <- + if (center - 10 < center + 10) choose(center - 10, center + 10) + else choose(center + 10, center - 10) // deal with overflow if abs(a) == 1 } yield (a, b) val genBorderline = diff --git a/versions.properties b/versions.properties index 26e8324c44..f767dfab7b 100644 --- a/versions.properties +++ b/versions.properties @@ -21,7 +21,7 @@ scala-swing.version.number=2.0.0 scala-swing.version.osgi=2.0.0 jline.version=2.14.3 # this one is shaded and embedded in scala-compiler.jar -scala-asm.version=5.1.0-scala-1 +scala-asm.version=5.1.0-scala-2 # external modules, used internally (not shipped) partest.version.number=1.1.0 |