summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CONTRIBUTING.md74
-rw-r--r--README.md193
-rw-r--r--build.number6
-rwxr-xr-xbuild.xml7
-rw-r--r--scripts/common153
-rwxr-xr-xscripts/jobs/integrate/bootstrap563
-rwxr-xr-xscripts/jobs/integrate/ide32
-rwxr-xr-xscripts/jobs/validate/publish-core44
-rwxr-xr-xscripts/jobs/validate/test17
-rw-r--r--scripts/readproperties.awk39
-rw-r--r--scripts/repositories-scala-release7
-rw-r--r--spec/03-types.md4
-rw-r--r--spec/04-basic-declarations-and-definitions.md2
-rw-r--r--spec/05-classes-and-objects.md2
-rw-r--r--spec/06-expressions.md19
-rw-r--r--spec/08-pattern-matching.md2
-rw-r--r--spec/09-top-level-definitions.md2
-rw-r--r--src/actors/scala/actors/Actor.scala2
-rw-r--r--src/actors/scala/actors/LinkedQueue.java2
-rw-r--r--src/actors/scala/actors/remote/Proxy.scala2
-rw-r--r--src/actors/scala/actors/threadpool/AbstractCollection.java2
-rw-r--r--src/actors/scala/actors/threadpool/ExecutorCompletionService.java2
-rw-r--r--src/actors/scala/actors/threadpool/locks/ReentrantReadWriteLock.java4
-rw-r--r--src/asm/scala/tools/asm/Label.java2
-rw-r--r--src/asm/scala/tools/asm/tree/analysis/Analyzer.java4
-rw-r--r--src/asm/scala/tools/asm/tree/analysis/Interpreter.java14
-rw-r--r--src/asm/scala/tools/asm/util/Printer.java18
-rw-r--r--src/compiler/scala/tools/ant/Scalac.scala2
-rw-r--r--src/compiler/scala/tools/nsc/Global.scala4
-rw-r--r--src/compiler/scala/tools/nsc/PhaseAssembly.scala2
-rwxr-xr-xsrc/compiler/scala/tools/nsc/ast/parser/MarkupParsers.scala7
-rw-r--r--src/compiler/scala/tools/nsc/backend/icode/GenICode.scala4
-rw-r--r--src/compiler/scala/tools/nsc/backend/icode/Primitives.scala2
-rw-r--r--src/compiler/scala/tools/nsc/backend/icode/analysis/TypeFlowAnalysis.scala4
-rw-r--r--src/compiler/scala/tools/nsc/backend/jvm/AsmUtils.scala70
-rw-r--r--src/compiler/scala/tools/nsc/backend/jvm/BCodeAsmCommon.scala28
-rw-r--r--src/compiler/scala/tools/nsc/backend/jvm/BCodeBodyBuilder.scala2
-rw-r--r--src/compiler/scala/tools/nsc/backend/jvm/BCodeHelpers.scala22
-rw-r--r--src/compiler/scala/tools/nsc/backend/jvm/BCodeIdiomatic.scala4
-rw-r--r--src/compiler/scala/tools/nsc/backend/jvm/BCodeSkelBuilder.scala2
-rw-r--r--src/compiler/scala/tools/nsc/backend/jvm/BCodeSyncAndTry.scala2
-rw-r--r--src/compiler/scala/tools/nsc/backend/jvm/BTypes.scala198
-rw-r--r--src/compiler/scala/tools/nsc/backend/jvm/BTypesFromSymbols.scala158
-rw-r--r--src/compiler/scala/tools/nsc/backend/jvm/CoreBTypes.scala8
-rw-r--r--src/compiler/scala/tools/nsc/backend/jvm/GenASM.scala42
-rw-r--r--src/compiler/scala/tools/nsc/backend/jvm/GenBCode.scala2
-rw-r--r--src/compiler/scala/tools/nsc/backend/jvm/opt/ByteCodeRepository.scala112
-rw-r--r--src/compiler/scala/tools/nsc/backend/jvm/opt/LocalOpt.scala22
-rw-r--r--src/compiler/scala/tools/nsc/backend/jvm/opt/OptimizerReporting.scala24
-rw-r--r--src/compiler/scala/tools/nsc/backend/opt/ConstantOptimization.scala4
-rw-r--r--src/compiler/scala/tools/nsc/backend/opt/DeadCodeElimination.scala2
-rw-r--r--src/compiler/scala/tools/nsc/backend/opt/Inliners.scala2
-rw-r--r--src/compiler/scala/tools/nsc/classpath/FlatClassPath.scala4
-rw-r--r--src/compiler/scala/tools/nsc/settings/ScalaSettings.scala7
-rw-r--r--src/compiler/scala/tools/nsc/settings/Warnings.scala13
-rw-r--r--src/compiler/scala/tools/nsc/symtab/SymbolLoaders.scala2
-rw-r--r--src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala4
-rw-r--r--src/compiler/scala/tools/nsc/transform/Constructors.scala2
-rw-r--r--src/compiler/scala/tools/nsc/transform/Delambdafy.scala14
-rw-r--r--src/compiler/scala/tools/nsc/transform/Erasure.scala22
-rw-r--r--src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala2
-rw-r--r--src/compiler/scala/tools/nsc/transform/Flatten.scala4
-rw-r--r--src/compiler/scala/tools/nsc/transform/LambdaLift.scala7
-rw-r--r--src/compiler/scala/tools/nsc/transform/OverridingPairs.scala2
-rw-r--r--src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala3
-rw-r--r--src/compiler/scala/tools/nsc/transform/patmat/Logic.scala236
-rw-r--r--src/compiler/scala/tools/nsc/transform/patmat/MatchAnalysis.scala223
-rw-r--r--src/compiler/scala/tools/nsc/transform/patmat/MatchOptimization.scala8
-rw-r--r--src/compiler/scala/tools/nsc/transform/patmat/MatchTranslation.scala11
-rw-r--r--src/compiler/scala/tools/nsc/transform/patmat/MatchTreeMaking.scala20
-rw-r--r--src/compiler/scala/tools/nsc/transform/patmat/PatternMatching.scala43
-rw-r--r--src/compiler/scala/tools/nsc/transform/patmat/ScalacPatternExpanders.scala4
-rw-r--r--src/compiler/scala/tools/nsc/transform/patmat/Solving.scala509
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/ContextErrors.scala2
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Contexts.scala10
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Implicits.scala4
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Infer.scala2
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Namers.scala2
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/NamesDefaults.scala2
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/PatternTypers.scala2
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala2
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Typers.scala44
-rwxr-xr-xsrc/compiler/scala/tools/nsc/util/DocStrings.scala2
-rw-r--r--src/eclipse/README.md23
-rw-r--r--src/intellij-14/scala.ipr.SAMPLE16
-rwxr-xr-xsrc/intellij-14/setup.sh3
-rw-r--r--src/intellij/scala-lang.ipr.SAMPLE1
-rw-r--r--src/intellij/test-osgi.iml.SAMPLE23
-rw-r--r--src/intellij/test/files/neg/virtpatmat_exhaust_big.check7
-rw-r--r--src/intellij/test/files/neg/virtpatmat_exhaust_big.flags1
-rw-r--r--src/intellij/test/files/neg/virtpatmat_exhaust_big.scala32
-rw-r--r--src/intellij/test/files/pos/virtpatmat_exhaust_big.scala34
-rw-r--r--src/interactive/scala/tools/nsc/interactive/Global.scala10
-rw-r--r--src/interactive/scala/tools/nsc/interactive/Pickler.scala6
-rw-r--r--src/library/scala/Enumeration.scala3
-rw-r--r--src/library/scala/Option.scala4
-rw-r--r--src/library/scala/collection/GenSeqLike.scala2
-rw-r--r--src/library/scala/collection/IterableLike.scala3
-rw-r--r--src/library/scala/collection/Iterator.scala6
-rwxr-xr-xsrc/library/scala/collection/LinearSeqOptimized.scala4
-rw-r--r--src/library/scala/collection/SeqViewLike.scala2
-rw-r--r--src/library/scala/collection/immutable/HashSet.scala6
-rw-r--r--src/library/scala/collection/immutable/Stream.scala2
-rw-r--r--src/library/scala/collection/immutable/StringLike.scala31
-rw-r--r--src/library/scala/collection/immutable/Vector.scala2
-rw-r--r--src/library/scala/collection/mutable/ArrayBuffer.scala13
-rw-r--r--src/library/scala/collection/mutable/BitSet.scala3
-rw-r--r--src/library/scala/collection/mutable/DoubleLinkedList.scala2
-rw-r--r--src/library/scala/collection/mutable/DoubleLinkedListLike.scala4
-rw-r--r--src/library/scala/collection/mutable/IndexedSeqView.scala2
-rw-r--r--src/library/scala/collection/mutable/LinkedHashMap.scala1
-rw-r--r--src/library/scala/collection/mutable/LinkedHashSet.scala1
-rw-r--r--src/library/scala/collection/mutable/LinkedList.scala2
-rw-r--r--src/library/scala/collection/mutable/LinkedListLike.scala2
-rw-r--r--src/library/scala/collection/mutable/LongMap.scala2
-rw-r--r--src/library/scala/collection/mutable/MapLike.scala2
-rw-r--r--src/library/scala/collection/mutable/MutableList.scala17
-rw-r--r--src/library/scala/collection/mutable/OpenHashMap.scala2
-rw-r--r--src/library/scala/collection/package.scala2
-rw-r--r--src/library/scala/collection/parallel/ParIterableLike.scala2
-rw-r--r--src/library/scala/collection/parallel/package.scala2
-rw-r--r--src/library/scala/concurrent/Future.scala2
-rw-r--r--src/library/scala/concurrent/SyncVar.scala4
-rw-r--r--src/library/scala/concurrent/package.scala74
-rw-r--r--src/library/scala/io/Source.scala17
-rw-r--r--src/library/scala/io/StdIn.scala2
-rw-r--r--src/library/scala/language.scala10
-rw-r--r--src/library/scala/languageFeature.scala10
-rw-r--r--src/library/scala/math/BigDecimal.scala2
-rw-r--r--src/library/scala/math/Ordering.scala5
-rw-r--r--src/library/scala/runtime/MethodCache.scala2
-rw-r--r--src/library/scala/runtime/ScalaRunTime.scala2
-rw-r--r--src/library/scala/sys/process/package.scala2
-rw-r--r--src/manual/scala/man1/Command.scala2
-rw-r--r--src/manual/scala/man1/scalac.scala2
-rw-r--r--src/partest-extras/scala/tools/partest/BytecodeTest.scala2
-rw-r--r--src/partest-extras/scala/tools/partest/instrumented/Profiler.java2
-rw-r--r--src/reflect/scala/reflect/api/Liftables.scala2
-rw-r--r--src/reflect/scala/reflect/api/Mirrors.scala4
-rw-r--r--src/reflect/scala/reflect/api/Names.scala4
-rw-r--r--src/reflect/scala/reflect/api/Symbols.scala2
-rw-r--r--src/reflect/scala/reflect/api/Trees.scala2
-rw-r--r--src/reflect/scala/reflect/internal/BaseTypeSeqs.scala4
-rw-r--r--src/reflect/scala/reflect/internal/Definitions.scala7
-rw-r--r--src/reflect/scala/reflect/internal/Mirrors.scala2
-rw-r--r--src/reflect/scala/reflect/internal/Names.scala4
-rw-r--r--src/reflect/scala/reflect/internal/Positions.scala2
-rw-r--r--src/reflect/scala/reflect/internal/Printers.scala3
-rw-r--r--src/reflect/scala/reflect/internal/StdAttachments.scala4
-rw-r--r--src/reflect/scala/reflect/internal/StdNames.scala1
-rw-r--r--src/reflect/scala/reflect/internal/Symbols.scala16
-rw-r--r--src/reflect/scala/reflect/internal/TreeGen.scala2
-rw-r--r--src/reflect/scala/reflect/internal/TreeInfo.scala4
-rw-r--r--src/reflect/scala/reflect/internal/Trees.scala20
-rw-r--r--src/reflect/scala/reflect/internal/Types.scala12
-rw-r--r--src/reflect/scala/reflect/internal/Variances.scala2
-rw-r--r--src/reflect/scala/reflect/internal/annotations/uncheckedBounds.scala2
-rw-r--r--src/reflect/scala/reflect/internal/pickling/ByteCodecs.scala4
-rw-r--r--src/reflect/scala/reflect/internal/tpe/FindMembers.scala2
-rw-r--r--src/reflect/scala/reflect/internal/tpe/TypeConstraints.scala2
-rw-r--r--src/reflect/scala/reflect/internal/util/WeakHashSet.scala8
-rw-r--r--src/reflect/scala/reflect/macros/Enclosures.scala2
-rw-r--r--src/reflect/scala/reflect/macros/Universe.scala2
-rw-r--r--src/reflect/scala/reflect/runtime/JavaMirrors.scala2
-rw-r--r--src/reflect/scala/reflect/runtime/JavaUniverseForce.scala1
-rw-r--r--src/reflect/scala/reflect/runtime/SynchronizedSymbols.scala8
-rw-r--r--src/repl/scala/tools/nsc/interpreter/AbstractOrMissingHandler.scala2
-rw-r--r--src/repl/scala/tools/nsc/interpreter/ILoop.scala24
-rw-r--r--src/repl/scala/tools/nsc/interpreter/IMain.scala2
-rw-r--r--src/repl/scala/tools/nsc/interpreter/InteractiveReader.scala1
-rw-r--r--src/repl/scala/tools/nsc/interpreter/JavapClass.scala6
-rw-r--r--src/repl/scala/tools/nsc/interpreter/LoopCommands.scala2
-rw-r--r--src/repl/scala/tools/nsc/interpreter/Power.scala2
-rw-r--r--src/scaladoc/scala/tools/ant/Scaladoc.scala2
-rw-r--r--src/scaladoc/scala/tools/nsc/doc/html/resource/lib/diagrams.js2
-rw-r--r--src/scaladoc/scala/tools/nsc/doc/model/Entity.scala2
-rw-r--r--test/benchmarks/src/scala/collection/parallel/benchmarks/Bench.scala2
-rw-r--r--test/files/jvm/innerClassAttribute/Test.scala29
-rw-r--r--test/files/jvm/serialization-new.check2
-rw-r--r--test/files/jvm/serialization.check2
-rw-r--r--test/files/jvm/t8582.check6
-rw-r--r--test/files/jvm/t8582.scala4
-rw-r--r--test/files/jvm/t9044.scala6
-rw-r--r--test/files/neg/literate_existentials.scala2
-rw-r--r--test/files/neg/structural.scala10
-rw-r--r--test/files/neg/t6582_exhaust_big.check7
-rw-r--r--test/files/neg/t6582_exhaust_big.flags1
-rw-r--r--test/files/neg/t6582_exhaust_big.scala32
-rw-r--r--test/files/neg/t7623.check21
-rw-r--r--test/files/neg/t7623.flags1
-rw-r--r--test/files/neg/t7623.scala38
-rw-r--r--test/files/neg/t9041.check4
-rw-r--r--test/files/neg/t9041.scala17
-rw-r--r--test/files/neg/t9093.check6
-rw-r--r--test/files/neg/t9093.scala5
-rw-r--r--test/files/pos/patmat-suppress.flags1
-rw-r--r--test/files/pos/patmat-suppress.scala159
-rw-r--r--test/files/pos/t4070.scala2
-rw-r--r--test/files/pos/t5154.scala9
-rw-r--r--test/files/pos/t6582_exhaust_big.scala33
-rw-r--r--test/files/pos/t7459a.scala18
-rw-r--r--test/files/pos/t7459b.scala12
-rw-r--r--test/files/pos/t7459c.scala18
-rw-r--r--test/files/pos/t7459d.scala8
-rw-r--r--test/files/pos/t7704.scala10
-rw-r--r--test/files/pos/t8828.scala2
-rw-r--r--test/files/pos/t8999.flags1
-rw-r--r--test/files/pos/t8999.scala271
-rw-r--r--test/files/pos/t9050.scala13
-rw-r--r--test/files/pos/t9086.scala8
-rw-r--r--test/files/pos/t9123.flags1
-rw-r--r--test/files/pos/t9123.scala10
-rw-r--r--test/files/pos/t9135.scala16
-rw-r--r--test/files/presentation/visibility/src/Completions.scala4
-rw-r--r--test/files/res/t9089.check4
-rw-r--r--test/files/res/t9089.res2
-rw-r--r--test/files/res/t9089/A.scala1
-rw-r--r--test/files/run/applydynamic_sip.scala2
-rw-r--r--test/files/run/bitsets.check1
-rw-r--r--test/files/run/icode-reader-dead-code.check8
-rw-r--r--test/files/run/t5313.scala2
-rw-r--r--test/files/run/t6114.scala2
-rw-r--r--test/files/run/t6502.check8
-rw-r--r--test/files/run/t6502.scala70
-rw-r--r--test/files/run/t7459a.scala14
-rw-r--r--test/files/run/t7459b-optimize.flags1
-rw-r--r--test/files/run/t7459b-optimize.scala21
-rw-r--r--test/files/run/t7459b.scala21
-rw-r--r--test/files/run/t7459c.scala16
-rw-r--r--test/files/run/t7459d.scala15
-rw-r--r--test/files/run/t7459f.scala12
-rw-r--r--test/files/run/t7965.scala54
-rw-r--r--test/files/run/t8253.scala2
-rw-r--r--test/files/run/t9030.scala19
-rw-r--r--test/files/run/t9097.scala34
-rw-r--r--test/files/scalacheck/nan-ordering.scala16
-rw-r--r--test/files/scalacheck/parallel-collections/ParallelIterableCheck.scala2
-rw-r--r--test/instrumented/library/scala/runtime/ScalaRunTime.scala2
-rw-r--r--test/junit/scala/StringContextTest.scala15
-rw-r--r--test/junit/scala/collection/IterableViewLikeTest.scala1
-rw-r--r--test/junit/scala/collection/TraversableOnceTest.scala8
-rw-r--r--test/junit/scala/collection/immutable/StringLikeTest.scala37
-rw-r--r--test/junit/scala/collection/immutable/VectorTest.scala20
-rw-r--r--test/junit/scala/collection/mutable/ArrayBufferTest.scala36
-rw-r--r--test/junit/scala/collection/mutable/LinkedHashMapTest.scala25
-rw-r--r--test/junit/scala/collection/mutable/LinkedHashSetTest.scala25
-rw-r--r--test/junit/scala/collection/mutable/MutableListTest.scala37
-rw-r--r--test/junit/scala/io/SourceTest.scala86
-rw-r--r--test/junit/scala/math/OrderingTest.scala61
-rw-r--r--test/junit/scala/reflect/internal/PrintersTest.scala2
-rw-r--r--test/junit/scala/tools/nsc/backend/jvm/BTypesTest.scala2
-rw-r--r--test/junit/scala/tools/nsc/backend/jvm/opt/BTypesFromClassfileTest.scala95
-rw-r--r--test/junit/scala/tools/nsc/backend/jvm/opt/MethodLevelOpts.scala2
-rw-r--r--test/junit/scala/tools/nsc/symtab/StdNamesTest.scala2
-rw-r--r--test/junit/scala/tools/nsc/symtab/SymbolTableTest.scala5
-rw-r--r--test/junit/scala/tools/nsc/transform/patmat/SolvingTest.scala555
-rw-r--r--test/junit/scala/tools/testing/AssertThrowsTest.scala2
-rw-r--r--test/junit/scala/tools/testing/AssertUtil.scala59
-rw-r--r--test/junit/scala/tools/testing/AssertUtilTest.scala21
-rw-r--r--test/pending/jvm/cf-attributes.scala2
-rw-r--r--test/pending/jvm/timeout.scala2
-rw-r--r--test/scaladoc/resources/SI-3314-diagrams.scala2
-rw-r--r--test/scaladoc/resources/implicit-inheritance-override.scala2
-rw-r--r--test/scaladoc/resources/implicits-ambiguating-res.scala2
-rw-r--r--test/scaladoc/resources/implicits-shadowing-res.scala2
-rw-r--r--test/scaladoc/scalacheck/HtmlFactoryTest.scala2
-rw-r--r--versions.properties10
267 files changed, 4989 insertions, 1005 deletions
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 1c05b4fd6b..e9505c26df 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -1,66 +1,52 @@
-# Scala Project & Developer Guidelines
+# Welcome! Thank you for contributing to Scala!
+We follow the standard GitHub [fork & pull](https://help.github.com/articles/using-pull-requests/#fork--pull) approach to pull requests. Just fork the official repo, develop in a branch, and submit a PR!
-These guidelines are meant to be a living document that should be changed and adapted as needed. We encourage changes that make it easier to achieve our goals in an efficient way.
+You're always welcome to submit your PR straight away and start the discussion (without reading the rest of this wonderful doc, or the `READMEnot^H^H^H.md`). The goal of these notes is to make your experience contributing to Scala as smooth and pleasant as possible. We're happy to guide you through the process once you've submitted your PR.
-## General Workflow
+## The Scala Community
+Last year, you -- the Scala community -- matched the core team at EPFL in number of commits contributed to Scala 2.11, doubling the percentage of commits from outside EPFL/Typesafe since 2.10. Excellent work! (The split is roughly 25/25/50 for you/epfl/typesafe. By the way, the team at Typesafe is: @adriaanm, @gkossakowski, @lrytz and @retronym.)
-This is the process for committing code to the Scala project. There are of course exceptions to these rules, for example minor changes to comments and documentation, fixing a broken build etc.
+We are super happy about this, and are eager to make your experience contributing to Scala productive and satisfying, so that we can keep up this growth. We can't do this alone (nor do we want to)!
-1. Make sure you have signed the [Scala CLA](http://typesafe.com/contribute/cla/scala), if not, sign it.
-2. Before starting to work on a feature or a fix, it's good practice to ensure that:
- 1. There is a ticket for your work in the project's issue tracker. If not, create it first (perhaps given a thumbs up from the scala-internals mailing list first).
- 2. The ticket has been discussed and prioritized by the team.
-3. You should always perform your work in its own Git branch. The branch should be given a descriptive name that explains its intent. Some teams also like adding the ticket number and/or the [GitHub](http://github.com) user ID to the branch name, these details is up to each of the individual teams. (See below for more details on branch naming.)
-4. When the feature or fix is completed you should open a [Pull Request](https://help.github.com/articles/using-pull-requests) on GitHub.
-5. The Pull Request should be reviewed by other maintainers (as many as feasible/practical). Note that a reviewer can also be an outside contributor-- members of Typesafe and independent contributors are encouraged to participate in the review process. It is not a closed process. Please try to avoid conflict of interest -- the spirit of the review process is to evenly distribute the understanding of our code base across its maintainers as well as to load balance quality assurance. Assigning a review to a "sure win" reviewer is not a good long-term solution.
-6. After the review, you should resolve issues brought up by the reviewers as needed (pushing a new commit to address reviewers' comments), iterating until the reviewers give their thumbs up, the "LGTM" (acronym for "Looks Good To Me").
-7. Once the code has passed review the Pull Request can be merged into the distribution.
+This is why we're collecting these notes on how to contribute, and we hope you'll share your experience to improve the process for the next contributor! (Feel free to send a PR for this note, send your thoughts to scala-internals, or tweet about it to @adriaanm.)
-## Pull Request Requirements
+## What kind of PR are you submitting?
-First, please have a look at and follow the [Pull Request Policy](https://github.com/scala/scala/wiki/Pull-Request-Policy) for guidelines on submitting a pull request to the Scala project.
+Regardless of the nature of your Pull Request, we have to ask you to sign the [Scala CLA](http://typesafe.com/contribute/cla/scala), to protect the OSS nature of the code base.
-In order for a Pull Request to be considered, it has to meet these requirements:
+### Documentation
+Whether you finally decided you couldn't stand that annoying typo anymore, you fixed the outdated code sample in some comment, or you wrote a nice, comprehensive, overview for an under-documented package, some docs for a class or the specifics about a method, your documentation improvement is very much appreciated, and we will do our best to fasttrack it.
-1. Live up to the current code standard:
- - Not violate [DRY](http://programmer.97things.oreilly.com/wiki/index.php/Don%27t_Repeat_Yourself).
- - [Boy Scout Rule](http://programmer.97things.oreilly.com/wiki/index.php/The_Boy_Scout_Rule) should be applied.
-2. Tests are of paramount importance.
-3. The code must be well documented in the project's standard documentation format (see the ‘Documentation’ section below).
+You can make these changes directly in your browser in GitHub, or follow the same process as for code. Up to you!
-If *all* of these requirements are not met then the code should **not** be merged into the distribution, and need not even be reviewed.
+For bigger documentation changes, you may want to poll the (scala-internals) mailing list first, to quickly gauge whether others support the direction you're taking, so there won't be any surprises when it comes to reviewing your PR.
-## Documentation
+### Code
+For bigger changes, we do recommend announcing your intentions on scala-internals first, to avoid duplicated effort, or spending a lot of time reworking something we are not able to change at this time in the release cycle, for example.
-All contributed code should come accompanied with documentation. Pull requests containing undocumented code will not be accepted. Both user-facing Scaladoc comments, as well as committer-facing internal documentation (i.e. important design decisions that other maintainers should know about should be placed inline with line comments `//`) should be accompanying all contributed code where possible.
+The kind of code we can accept depends on the life cycle for the release you're targeting. The current maintenance release (2.11.x) cannot break source/binary compatibility, which means public APIs cannot change. It also means we are reluctant to change, e.g., type inference or implicit search, as this can have unforeseen consequences for source compatibility.
+#### Bug Fix
-## Work In Progress
+Prefix your commit title with "SI-NNNN", where https://issues.scala-lang.org/browse/SI-NNNN tracks the bug you're fixing. We also recommend naming your branch after the Jira ticket number.
-It is ok to work on a public feature branch in the GitHub repository. Something that can sometimes be useful for early feedback etc. If so, then it is preferable to name the branch accordingly. This can be done by either prefixing the name with ``wip-`` as in ‘Work In Progress’, or use hierarchical names like ``wip/..``, ``feature/..`` or ``topic/..``. Either way is fine as long as it is clear that it is work in progress and not ready for merge. This work can temporarily have a lower standard. However, to be merged into master it will have to go through the regular process outlined above, with Pull Request, review etc..
+Please make sure the Jira ticket's fix version corresponds to the upcoming milestone for the branch your PR targets (the CI automation will automatically assign the milestone after you open the PR).
-Also, to facilitate both well-formed commits and working together, the ``wip`` and ``feature``/``topic`` identifiers also have special meaning. Any branch labelled with ``wip`` is considered “git-unstable” and may be rebased and have its history rewritten. Any branch with ``feature``/``topic`` in the name is considered “stable” enough for others to depend on when a group is working on a feature.
+#### Enhancement or New Feature
-## Creating Commits And Writing Commit Messages
+For longer-running development, likely required for this category of code contributions, we suggest you include "topic" or "wip" in your branch name, to indicate that this is work in progress, and that others should be prepared to rebase if they branch off your branch.
-Follow these guidelines when creating public commits and writing commit messages.
+Any language change (including bug fixes) must be accompanied by the relevant updates to the spec, which lives in the same repository for this reason.
-1. If your work spans multiple local commits (for example; if you do safe point commits while working in a feature branch or work in a branch for long time doing merges/rebases etc.) then please do not commit it all but rewrite the history by squashing the commits into one large commit which is accompanied by a detailed commit message for (as discussed in the following sections). For more info, see the article: [Git Workflow](http://sandofsky.com/blog/git-workflow.html). Additionally, every commit should be able to be used in isolation-- that is, each commit must build and pass all tests.
-2. The first line should be a descriptive sentence about what the commit is doing. It should be possible to fully understand what the commit does by just reading this single line. It is **not ok** to only list the ticket number, type "minor fix" or similar. If the commit has a corresponding ticket, include a reference to the ticket number, prefixed with "SI-", at the beginning of the first line followed by the title of the ticket, assuming that it aptly and concisely summarizes the commit in a single line. If the commit is a small fix, then you are done. If not, go to 3.
-3. Following the single line description (ideally no more than 70 characters long) should be a blank line followed by an enumerated list with the details of the commit.
-4. Add keywords for your commit (depending on the degree of automation we reach, the list may change over time):
- * ``Review by @githubuser`` - will notify the reviewer via GitHub. Everyone is encouraged to give feedback, however. (Remember that @-mentions will result in notifications also when pushing to a WIP branch, so please only include this in your commit message when you're ready for your pull request to be reviewed. Alternatively, you may request a review in the pull request's description.)
- * ``Fix/Fixing/Fixes/Close/Closing/Refs #ticket`` - if you want to mark the ticket as fixed in the issue tracker (Assembla understands this).
- * ``backport to _branch name_`` - if the fix needs to be cherry-picked to another branch (like 2.9.x, 2.10.x, etc)
+A new language feature requires a SIP (Scala Improvement Process) proposal. For more details on submitting SIPs, see [how to submit a SIP](http://docs.scala-lang.org/sips/sip-submission.html).
-Example:
+#### Summary
- SI-4032 Implicit conversion visibility affected by presence of "this"
+1. We require regression tests for bug fixes. New features and enhancements must be supported by a respectable test suite.
+2. Documentation. Yep! Also required :-)
+3. Please follow these standard code standards, though in moderation (scouts quickly learn to let sleeping dogs lie):
+ - Not violate [DRY](http://programmer.97things.oreilly.com/wiki/index.php/Don%27t_Repeat_Yourself).
+ - [Boy Scout Rule](http://programmer.97things.oreilly.com/wiki/index.php/The_Boy_Scout_Rule) should be applied.
- - Details 1
- - Details 2
- - Details 3
+Please also have a look at our [Pull Request Policy](https://github.com/scala/scala/wiki/Pull-Request-Policy), as well as the [Scala Hacker Guide](http://www.scala-lang.org/contribute/hacker-guide.html) by @xeno-by.
-## The Scala Improvement Process
-A new language feature requires a SIP (Scala Improvement Process) proposal. Note that significant additions to the standard library are also considered candidates for a SIP proposal.
-For more details on submitting SIPs, see [how to submit a SIP](http://docs.scala-lang.org/sips/sip-submission.html).
diff --git a/README.md b/README.md
index fdc989228c..d04197891c 100644
--- a/README.md
+++ b/README.md
@@ -1,8 +1,189 @@
-This is the repository for the [Scala Programming Language](http://www.scala-lang.org).
+# Welcome!
+This is the official repository for the [Scala Programming Language](http://www.scala-lang.org).
- - [Report an issue](https://issues.scala-lang.org);
- - [Read about the development of the compiler and the standard library](http://docs.scala-lang.org/scala/);
- - [Check our Jenkins status](https://scala-webapps.epfl.ch/jenkins/);
+To contribute to the Scala Standard Library, Scala Compiler and Scala Language Specification, please send us a [pull request](https://help.github.com/articles/using-pull-requests/#fork--pull) from your fork of this repository! We do have to ask you to sign the [Scala CLA](http://typesafe.com/contribute/cla/scala) before we can merge any of your work into our code base, to protect its open source nature.
+
+For more information on building and developing the core of Scala, read on! Please also check out our [guidelines for contributing](CONTRIBUTING.md).
+
+We're still using Jira for issue reporting, so please [report any issues](https://issues.scala-lang.org) over there.
+(We would love to start using GitHub Issues, but we're too resource-constrained to take on this migration right now.)
+
+# Get in touch!
+If you need some help with your PR at any time, please feel free to @-mention anyone from the list below (or simply `@scala/team-core-scala`), and we will do our best to help you out:
+
+ | username | talk to me about... |
+--------------------------------------------------------------------------------------------------|----------------------------------------------------------------|---------------------------------------------------|
+ <img src="https://avatars.githubusercontent.com/adriaanm" height="50px" title="Adriaan Moors"/> | [`@adriaanm`](https://github.com/adriaanm) | anything (type checker, pattern matcher, CI,...) |
+ <img src="https://avatars.githubusercontent.com/gkossakowski" height="50px" title="Grzegorz Kossakowski"/> | [`@gkossakowski`](https://github.com/gkossakowski) | infrastructure, incremental compilation, back-end |
+ <img src="https://avatars.githubusercontent.com/retronym" height="50px" title="Jason Zaugg"/> | [`@retronym`](https://github.com/retronym) | Java 8 lambdas, tricky bug detective work |
+ <img src="https://avatars.githubusercontent.com/Ichoran" height="50px" title="Rex Kerr"/> | [`@Ichoran`](https://github.com/Ichoran) | the collections library, performance |
+ <img src="https://avatars.githubusercontent.com/lrytz" height="50px" title="Lukas Rytz"/> | [`@lrytz`](https://github.com/lrytz) | optimizer, named & default arguments |
+ <img src="https://avatars.githubusercontent.com/dickwall" height="50px" title="Dick Wall"/> | [`@dickwall`](https://github.com/dickwall) | process & documentation |
+ <img src="https://avatars.githubusercontent.com/VladUreche" height="50px" title="Vlad Ureche"/> | [`@VladUreche`](https://github.com/VladUreche) | specialization & the scaladoc tool |
+ <img src="https://avatars.githubusercontent.com/densh" height="50px" title="Denys Shabalin"/> | [`@densh`](https://github.com/densh) | quasiquotes, parser, string interpolators, macros in standard library |
+ <img src="https://avatars.githubusercontent.com/xeno-by" height="50px" title="Eugene Burmako"/> | [`@xeno-by`](https://github.com/xeno-by) | macros and reflection |
+
+
+PS: If you have some spare time to help out around here, we would be delighted to add your name to this list!
+
+# Handy Links
+ - [A wealth of documentation](http://docs.scala-lang.org)
+ - [Scala CI](https://scala-ci.typesafe.com/)
+ - [Scala CI at EPFL](https://scala-webapps.epfl.ch/jenkins)
- [Download the latest nightly](https://scala-webapps.epfl.ch/jenkins/job/scala-nightly-main-master/ws/dists/latest/*zip*/latest.zip);
- - ... and contribute right here! Please, first read our [policy](http://docs.scala-lang.org/scala/pull-request-policy.html), our [development guidelines](CONTRIBUTING.md),
-and [sign the contributor's license agreement](http://typesafe.com/contribute/cla/scala).
+ - Scala mailing lists:
+ - [Compiler and standard library development](https://groups.google.com/group/scala-internals)
+ - [Users of Scala](https://groups.google.com/group/scala-user)
+ - [Scala language discussion](https://groups.google.com/group/scala-language)
+ - [Scala Improvement Process](https://groups.google.com/group/scala-sips)
+ - [Debate](https://groups.google.com/group/scala-debate)
+ - [Announcements](https://groups.google.com/group/scala-announce)
+
+# Repository structure
+
+```
+scala/
++--build.xml The main Ant build script, see also under src/build.
++--pull-binary-libs.sh Pulls binary artifacts from remote repository.
++--lib/ Pre-compiled libraries for the build.
++--src/ All sources.
+ +---/library Scala Standard Library.
+ +---/reflect Scala Reflection.
+ +---/compiler Scala Compiler.
+ +---/eclipse Eclipse project files.
+ +---/intellij-14 IntelliJ project templates.
++--scripts/ Scripts for the CI jobs (including building releases)
++--test/ The Scala test suite.
++--build/ [Generated] Build products output directory for ant.
++--dist/ [Generated] The destination folder for Scala distributions.
+```
+
+# How we roll
+
+## Requirements
+
+You'll need a Java SDK (6 or newer), Apache Ant (version 1.8.0 or above), and curl (for `./pull-binary-libs.sh`).
+
+## Git Hygiene
+
+As git history is forever, we take great pride in the quality of the commits we merge into the repository. The title of your commit will be read hundreds (of thousands? :-)) of times, so it pays off to spend just a little bit more time to polish it, making it descriptive and concise. Please take a minute to read the advice [most projects agree on](https://github.com/erlang/otp/wiki/Writing-good-commit-messages), and stick to 50-60 characters for the first line, wrapping subsequent ones at 80 (at most).
+
+When not sure how to formulate your commit message, imagine you're writing a bullet item for the next release notes, or describing what the commit does to the code base (use active verbs in the present tense). When your commit title is featured in the next release notes, it will be read by a lot of curious Scala users, looking for the latest improvements. Satisfy their thirst for information with as few words as possible! Also, a commit should convey clearly to your (future) fellow contributors what it does to the code base.
+
+Writing the commit message is a great sanity check that the commit is of the right size. If it does too many things, the description will be unwieldy and tedious to write. Chop it up (`git add -u --patch` and `git rebase` are your friends) and simplify!
+
+To pinpoint bugs, we often use git bisect, which is only effective when we can count on each commit building (and passing the test suite). Thus, the CI bot enforces this. Please rebase your development history into a sensible list of self-contained commits that tell the story of your bug fix or improvement. Carve them up so that the riskier bits can be reverted independently. Keep changes focussed by splitting out cleanups from refactorings from actual changes to the logic.
+
+This facilitates reviewing: a commit that reformats code can be judged quickly not to affect anything, so we can focus on the meat of the PR. It also helps when merging between long-running branches, reducing conflicts (or providing at least a limited scope for each one).
+
+Please do not @mention anyone in the commit message -- that's what the PR description and comments are for. Every time a commit is shuffled through github (in a merge in some fork, say), every @mention results in an email to that person (the core team treats them as personal email, straight to their inbox, so please don't flood us :-)).
+
+
+## Reviews
+
+Please consider nominating a reviewer for your PR in the PR's description or a comment. If unsure, not to worry -- the core team will assign one for you.
+
+Your reviewer is also your mentor, who will help you rework your PR so that it meets our requirements. We strive to give timely feedback, and apologize for those times when we are overwhelmed by the volume of contributions. Please feel free to ping us. You are entitled to regular progress updates and at least a quick assessment of feasibility of a bigger PR.
+
+To help you plan your contributions, we communicate our plans on a regular basis on scala-internals, and deadlines are tracked as due dates for [GitHub milestones](https://github.com/scala/scala/milestones).
+
+## Reviewing
+
+Once you've gained some experience with the code base and the process, the logical next step is to offers reviews for others's contributions. The main goal of this whole process, in the end, is to ensure the health of the Scala project by improving the quality of the code base, the documentation, as well as this process itself. Thank you for doing your part!
+
+### Tips & Tricks
+Once the `publish-core` task has completed on a commit, you can try it out in sbt as follows:
+
+```
+$ sbt
+
+> set resolvers += "pr" at "http://private-repo.typesafe.com/typesafe/scala-pr-validation-snapshots/"
+> set scalaVersion := "<milestone>-<sha7>-SNAPSHOT"
+> console
+```
+
+Here, `<milestone>` is the milestone targeted by the PR (e.g., 2.11.6), and `<sha7>` is the 7-character sha (the format used by GitHub on the web).
+
+## IDE Setup
+### Eclipse
+Download the [Scala IDE bundle](http://scala-ide.org/download/sdk.html). It comes preconfigured for optimal performance.
+
+ - Run `ant init` to download some necessary jars.
+ - Import the project (in `src/eclipse`) via `File` → `Import Existing Projects into Workspace`. Check all projects and click ok.
+
+For important details on building, debugging and file encodings, please see [the excellent tutorial on scala-ide.org](http://scala-ide.org/docs/tutorials/scalac-trunk/index.html) and the included README.md in src/eclipse.
+
+### IntelliJ 14
+Use the latest IntelliJ IDEA release and install the Scala plugin from within the IDE.
+
+The following steps are required to use IntelliJ IDEA on Scala trunk
+ - Run `ant init`. This will download some JARs to `./build/deps`, which are included in IntelliJ's classpath.
+ - Run src/intellij-14/setup.sh
+ - Open ./src/intellij-14/scala.ipr in IntelliJ
+ - File, Project Settings, Project, SDK. Create an SDK entry named "1.6" containing the Java 1.6 SDK.
+ (You may use a later SDK for local development, but the CI will verify against Java 6.)
+
+Compilation within IDEA is performed in "-Dlocker.skip=1" mode: the sources are built
+directly using the STARR compiler (which is downloaded from maven, according to `starr.version` in `versions.properties`).
+
+
+## Building with Ant
+
+NOTE: we are working on migrating the build to sbt.
+
+Run `ant build-opt` to build an optimized version of the compiler.
+Verify your build using `ant test-opt`.
+
+The Scala build system is based on Apache Ant. Most required pre-compiled
+libraries are part of the repository (in 'lib/'). The following however is
+assumed to be installed on the build machine:
+
+
+### Tips and tricks
+
+Here are some common commands. Most ant targets offer a `-opt` variant that runs under `-optimise` (CI runs the -optimize variant).
+
+ - `./pull-binary-libs.sh` [downloads](http://typesafe.artifactoryonline.com/typesafe) all binary artifacts associated with this commit.
+ - `ant -p` prints out information about the commonly used ant targets.
+ - `ant` or `ant build`: A quick compilation (to build/quick) of your changes using the locker compiler.
+
+A typical debug cycle incrementally builds quick, then uses it to compile and run the file
+`sandbox/test.scala` as follows:
+
+ - `ant && build/quick/bin/scalac -d sandbox sandbox/test.scala && build/quick/bin/scala -cp sandbox Test`
+
+We typically alias `build/quick/bin/scalac -d sandbox` to `qsc` and `build/quick/bin/scala -cp sandbox` to `qs` in our shell.
+
+`ant test-opt` tests that your code is working and fit to be committed:
+
+ - Runs the test suite and bootstrapping test on quick.
+ - You can run the suite only (skipping strap) with 'ant test.suite'.
+
+`ant docs` generates the HTML documentation for the library from the sources using the scaladoc tool in quick.
+Note: on most machines this requires more heap than is allocate by default. You can adjust the parameters with ANT_OPTS. Example command line:
+
+```
+ANT_OPTS = "-Xms512M -Xmx2048M -Xss1M -XX:MaxPermSize=128M" ant docs
+```
+
+ - `ant dist` builds a distribution in 'dists/latest'.
+ - `ant all.clean` Removes all build files and all distributions.
+
+### Bootstrapping concepts
+NOTE: This is somewhat outdated, but the ideas still hold.
+
+In order to guarantee the bootstrapping of the Scala compiler, the ant build
+compiles Scala in layers. Each layer is a complete compiled Scala compiler and library.
+A superior layer is always compiled by the layer just below it. Here is a short
+description of the four layers that the build uses, from bottom to top:
+
+ - `starr`: the stable reference Scala release. We use an official version of Scala (specified by `starr.version` in `versions.properties`), downloaded from maven central.
+ - `locker`: the local reference which is compiled by starr and is the work compiler in a typical development cycle. Add `locker.skip=true` to `build.properties` to skip this step and speed up development when you're not changing code generation. In any case, after it has been built once, it is “frozen” in this state. Updating it to fit the current source code must be explicitly requested (`ant locker.unlock`).
+ - `quick`: the layer which is incrementally built when testing changes in the compiler or library. This is considered an actual new version when locker is up-to-date in relation to the source code.
+ - `strap`: a test layer used to check stability of the build.
+
+For each layer, the Scala library is compiled first and the compiler next.
+That means that any changes in the library can immediately be used in the
+compiler without an intermediate build. On the other hand, if building the
+library requires changes in the compiler, a new locker must be built if
+bootstrapping is still possible, or a new starr if it is not.
diff --git a/build.number b/build.number
index dc85ecb777..5f8ed6d6b6 100644
--- a/build.number
+++ b/build.number
@@ -1,9 +1,9 @@
#Tue Sep 11 19:21:09 CEST 2007
version.major=2
version.minor=11
-version.patch=5
+version.patch=6
# This is the -N part of a version. if it's 0, it's dropped from maven versions.
version.bnum=0
-# Note: To build a release run ant with -Dbuild.release=true
-# To build an RC, run ant with -Dmaven.version.suffix=-RCN
+# To build a release, see scripts/jobs/scala-release-2.11.x-build
+# (normally run by the eponymous job on scala-ci.typesafe.com). \ No newline at end of file
diff --git a/build.xml b/build.xml
index 02b98e66d8..f8e44c6f5c 100755
--- a/build.xml
+++ b/build.xml
@@ -280,7 +280,7 @@ TODO:
<!-- Pax runner -->
<property name="pax.exam.version" value="3.5.0"/><!-- Last version which supports Java 6 -->
- <property name="osgi.felix.version" value="4.0.3"/>
+ <property name="osgi.felix.version" value="4.4.0"/>
<property name="osgi.equinox.version" value="3.7.1"/>
<artifact:dependencies pathId="pax.exam.classpath" filesetId="pax.exam.fileset">
<dependency groupId="org.ops4j.pax.exam" artifactId="pax-exam-container-native" version="${pax.exam.version}">
@@ -294,6 +294,7 @@ TODO:
<dependency groupId="ch.qos.logback" artifactId="logback-classic" version="1.1.2"/>
<dependency groupId="junit" artifactId="junit" version="${junit.version}"/>
</artifact:dependencies>
+ <copy-deps project="pax.exam"/>
<artifact:dependencies pathId="osgi.framework.felix">
<dependency groupId="org.apache.felix" artifactId="org.apache.felix.framework" version="${osgi.felix.version}"/>
@@ -1375,8 +1376,8 @@ TODO:
</target>
<target name="test.osgi" depends="test.osgi.comp">
- <if><isset property="has.java8"/><then>
- <echo message="Skipping OSGi JUnit tests on Java 8. See SI-8642"/>
+ <if><isset property="test.osgi.skip"/><then>
+ <echo message="Skipping OSGi JUnit tests"/>
</then><else>
<echo message="Running OSGi JUnit tests. Output in ${build-osgi.dir}"/>
<stopwatch name="test.osgi.timer"/>
diff --git a/scripts/common b/scripts/common
new file mode 100644
index 0000000000..b075469379
--- /dev/null
+++ b/scripts/common
@@ -0,0 +1,153 @@
+# This is for forcibly stopping the job from a subshell (see test
+# below).
+trap "exit 1" TERM
+export TOP_PID=$$
+set -e
+
+# Known problems : does not fare well with interrupted, partial
+# compilations. We should perhaps have a multi-dependency version
+# of do_i_have below
+
+LOGGINGDIR="$WORKSPACE/logs"
+mkdir -p $LOGGINGDIR
+
+unset SBT_HOME
+SBT_HOME="$WORKSPACE/.sbt"
+mkdir -p $SBT_HOME
+IVY_CACHE="$WORKSPACE/.ivy2"
+mkdir -p $IVY_CACHE
+rm -rf $IVY_CACHE/cache/org.scala-lang
+
+# temp dir where all 'non-build' operation are performed
+TMP_ROOT_DIR=$(mktemp -d -t pr-scala.XXXX)
+TMP_DIR="${TMP_ROOT_DIR}/tmp"
+mkdir "${TMP_DIR}"
+
+
+# detect sed version and how to enable extended regexes
+SEDARGS="-n$(if (echo "a" | sed -nE "s/a/b/" &> /dev/null); then echo E; else echo r; fi)"
+
+
+
+# :docstring test:
+# Usage: test <argument ..>
+# Executes <argument ..>, logging the launch of the command to the
+# main log file, and kills global script execution with the TERM
+# signal if the commands ends up failing.
+# DO NOT USE ON FUNCTIONS THAT DECLARE VARIABLES,
+# AS YOU'LL BE RUNNING IN A SUBSHELL AND VARIABLE DECLARATIONS WILL BE LOST
+# :end docstring:
+
+function test() {
+ echo "### $@"
+ "$@"
+ status=$?
+ if [ $status -ne 0 ]; then
+ say "### ERROR with $1"
+ kill -s TERM $TOP_PID
+ fi
+}
+
+# :docstring say:
+# Usage: say <argument ..>
+# Prints <argument ..> to both console and the main log file.
+# :end docstring:
+
+function say(){
+ (echo "$@") | tee -a $LOGGINGDIR/compilation-$SCALADATE-$SCALAHASH.log
+}
+
+# General debug logging
+# $* - message
+function debug () {
+ echo "----- $*"
+}
+
+function parseScalaProperties(){
+ propFile="$baseDir/$1"
+ if [ ! -f $propFile ]; then
+ echo "Property file $propFile not found."
+ exit 1
+ else
+ awk -f "$scriptsDir/readproperties.awk" "$propFile" > "$propFile.sh"
+ . "$propFile.sh" # yeah yeah, not that secure, improvements welcome (I tried, but bash made me cry again)
+ fi
+}
+
+
+## TAKEN FROM UBER-BUILD, except that it "returns" (via $RES) true/false
+# Check if an artifact is available
+# $1 - groupId
+# $2 - artifacId
+# $3 - version
+# $4 - extra repository to look in (optional)
+# return value in $RES
+function checkAvailability () {
+ pushd "${TMP_DIR}"
+ rm -rf *
+
+# pom file for the test project
+ cat > pom.xml << EOF
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <groupId>com.typesafe</groupId>
+ <artifactId>typesafeDummy</artifactId>
+ <packaging>war</packaging>
+ <version>1.0-SNAPSHOT</version>
+ <name>Dummy</name>
+ <url>http://127.0.0.1</url>
+ <dependencies>
+ <dependency>
+ <groupId>$1</groupId>
+ <artifactId>$2</artifactId>
+ <version>$3</version>
+ </dependency>
+ </dependencies>
+ <repositories>
+ <repository>
+ <id>sonatype.snapshot</id>
+ <name>Sonatype maven snapshot repository</name>
+ <url>https://oss.sonatype.org/content/repositories/snapshots</url>
+ <snapshots>
+ <updatePolicy>daily</updatePolicy>
+ </snapshots>
+ </repository>
+EOF
+
+ if [ -n "$4" ]
+ then
+# adds the extra repository
+ cat >> pom.xml << EOF
+ <repository>
+ <id>extrarepo</id>
+ <name>extra repository</name>
+ <url>$4</url>
+ </repository>
+EOF
+ fi
+
+ cat >> pom.xml << EOF
+ </repositories>
+</project>
+EOF
+
+ set +e
+ mvn "${MAVEN_ARGS[@]}" compile &> "${TMP_DIR}/mvn.log"
+ RES=$?
+ # Quiet the maven, but allow diagnosing problems.
+ grep -i downloading "${TMP_DIR}/mvn.log"
+ grep -i exception "${TMP_DIR}/mvn.log"
+ grep -i error "${TMP_DIR}/mvn.log"
+ set -e
+
+# log the result
+ if [ ${RES} == 0 ]
+ then
+ debug "$1:$2:jar:$3 found !"
+ RES=true
+ else
+ debug "$1:$2:jar:$3 not found !"
+ RES=false
+ fi
+ popd
+}
diff --git a/scripts/jobs/integrate/bootstrap b/scripts/jobs/integrate/bootstrap
new file mode 100755
index 0000000000..46d610018c
--- /dev/null
+++ b/scripts/jobs/integrate/bootstrap
@@ -0,0 +1,563 @@
+#!/bin/bash -e
+# TODO: different scripts for the different phases -- usually we don't need to bootstrap the modules,
+# since we can use the previous version of scala for STARR as well as for compiling the modules (assuming it's binary compatible)
+# We should move away from the complicated bootstrap and set up our release schedule so we always have a previous build that satisfies these criteria.
+# (Potentially trivially, by splitting up this script, and publishing locker as if it were a real release.)
+
+# requirements:
+# sbtCmd must point to sbt from sbt-extras (this is the standard on the Scala jenkins, so we only support that one)
+# - ~/.sonatype-curl that consists of user = USER:PASS
+# - ~/.m2/settings.xml with credentials for sonatype
+ # <server>
+ # <id>private-repo</id>
+ # <username>jenkinside</username>
+ # <password></password>
+ # </server>
+# - ~/.credentials (for sonatype)
+ # realm=Sonatype Nexus Repository Manager
+ # host=oss.sonatype.org
+ # user=lamp
+ # password=
+# - ~/.credentials-private-repo for private-repo.typesafe.com, as follows:
+ # realm=Artifactory Realm
+ # host=private-repo.typesafe.com
+ # user=jenkinside
+ # password=
+# - ~/.sbt/0.13/plugins/gpg.sbt with:
+# addSbtPlugin("com.typesafe.sbt" % "sbt-pgp" % "0.8.1")
+
+# Modus operandi:
+#
+# Determine Scala version as:
+#
+# $SCALA_VER_BASE$SCALA_VER_SUFFIX (if former variable is set)
+# By parsing the tag (if HEAD is tagged as v$base$suffix)
+# By parsing build.number for the base version, suffixing with -$sha-nightly
+# Serialize these versions to jenkins.properties, which are passed downstream to scala-release-2.11.x-dist.
+# This also removes the need to tag scala/scala-dist (not possible for nightlies, still encouraged for releases, but not a hard requirement).
+#
+# Determine Module Versions
+#
+# When running in "versions.properties" mode (the default), derive tags from these versions and build, publishing only those modules that are not available yet.
+# Otherwise, build HEAD for all modules, derive a -nightly version for them.
+# Bootstrap:
+#
+# Build minimal core of Scala as this version (aka locker), publish to private-repo
+# Build modules required to bootstrap, publish to private-repo
+# Build Scala using the previously built core and bootstrap modules, publish to private-repo This overwrites the minimal core on private-repo
+# Stage to sonatype (unless building a -nightly release):
+#
+# Stage this Scala build on sonatype
+# Rebuild modules with this Scala build, and stage them on sonatype as well
+# This script can be run in multiple modes. It is design to work without any input,
+# so that it could be run in Travis CI. In that mode, it'll build a release when
+# the current HEAD of the checkout in $WORKSPACE is tagged, and stage to sonatype. Otherwise,
+# it'll build a nightly.
+#
+# Since the nightlies are intended to be a drop in replacement, all modules are built with the
+# full Scala version as their binary version, so that you can just set scalaVersion to the
+# nightly's sha-derived version and be good to go.
+#
+# The other way to trigger a release is by setting the SCALA_VER_BASE env var.
+#
+# By default, we build the versions of the modules as specified by versions.properties
+# (as specified in the HEAD commit). Set moduleVersioning to something random
+# to trigger building HEAD of each module, generating a fresh -$(git describe)-nightly version for each.
+#
+# PS: set publishToSonatype to anything but "yes" to avoid publishing to sonatype
+# (publishing only done when $WORKSPACE checkout's HEAD is tagged / SCALA_VER_BASE is set.)
+
+
+# set to something besides the default to build nightly snapshots of the modules instead of some tagged version
+moduleVersioning=${moduleVersioning-"versions.properties"}
+
+publishPrivateTask=${publishPrivateTask-"publish"}
+publishSonatypeTaskCore=${publishSonatypeTaskCore-"publish-signed"}
+publishSonatypeTaskModules=${publishSonatypeTaskModules-"publish-signed"}
+publishLockerPrivateTask=${publishLockerPrivateTask-$publishPrivateTask} # set to "init" to speed up testing of the script (if you already built locker before)
+
+sbtCmd=${sbtCmd-sbt} # TESTING (this is a marker for defaults to change when testing locally: should be sbtx on my mac)
+
+# 0.13.5 does not respect "set every scalaVersion", see
+# https://github.com/scala/scala-parser-combinators/pull/27
+sbtCmd="$sbtCmd -sbt-version 0.13.2"
+
+forceRebuild=${forceRebuild-no}
+
+# publishToSonatype
+# set to anything but "yes" to avoid publishing to sonatype
+# overridden to "no" when no SCALA_VER_BASE is passed and HEAD is not tagged with a valid version tag
+#
+
+antBuildTask="${antBuildTask-nightly}" # TESTING leave empty to avoid the sanity check (don't set it to "init" because ant will croak)
+clean="clean" # TESTING leave empty to speed up testing
+
+
+
+baseDir=${WORKSPACE-`pwd`}
+scriptsDir="$baseDir/scripts"
+. $scriptsDir/common
+
+# we must change ivy home to get a fresh ivy cache, otherwise we get half-bootstrapped scala
+# rm it in case it existed (and there's no ivy2-shadow, which indicates we're running in a TESTING environment)...
+# we don't nuke the whole ws since that clobbers the git clones needlessly
+[[ -d $baseDir/ivy2-shadow ]] || rm -rf $baseDir/ivy2
+mkdir -p $baseDir/ivy2
+
+rm -rf $baseDir/resolutionScratch_
+mkdir -p $baseDir/resolutionScratch_
+
+# repo used to publish "locker" scala to (to start the bootstrap)
+privateCred="private-repo"
+privateRepo="http://private-repo.typesafe.com/typesafe/scala-release-temp/"
+
+##### git
+gfxd() {
+ git clean -fxd # TESTING
+}
+
+update() {
+ [[ -d $baseDir ]] || mkdir -p $baseDir
+ cd $baseDir
+
+ if [ ! -d $baseDir/$2 ]; then git clone "https://github.com/$1/$2.git"; fi
+
+ cd $2
+
+ git fetch --tags "https://github.com/$1/$2.git"
+ (git fetch "https://github.com/$1/$2.git" $3 && git checkout -q FETCH_HEAD) #|| git checkout -q $3 # || fallback is for local testing on tag
+ git reset --hard
+}
+
+##### sonatype interface
+
+stApi="https://oss.sonatype.org/service/local"
+
+function st_curl(){
+ curl -H "Content-Type: application/json" -H "accept: application/json,application/vnd.siesta-error-v1+json,application/vnd.siesta-validation-errors-v1+json" -K ~/.sonatype-curl -s -o - $@
+}
+
+function st_stagingReposOpen() {
+ st_curl "$stApi/staging/profile_repositories" | jq '.data[] | select(.profileName == "org.scala-lang") | select(.type == "open")'
+}
+
+function st_stagingRepoDrop() {
+ repo=$1
+ message=$2
+ echo "{\"data\":{\"description\":\"$message\",\"stagedRepositoryIds\":[\"$repo\"]}}" | st_curl -X POST -d @- "$stApi/staging/bulk/drop"
+}
+
+function st_stagingRepoClose() {
+ repo=$1
+ message=$2
+ echo "{\"data\":{\"description\":\"$message\",\"stagedRepositoryIds\":[\"$repo\"]}}" | st_curl -X POST -d @- "$stApi/staging/bulk/close"
+}
+
+
+# ARGH trying to get this to work on multiple versions of sbt-extras...
+# the old version (on jenkins, and I don't want to upgrade for risk of breaking other builds) honors -sbt-dir
+# the new version of sbt-extras ignores sbt-dir, so we pass it in as -Dsbt.global.base
+# need to set sbt-dir to one that has the gpg.sbt plugin config
+sbtArgs="-no-colors -ivy $baseDir/ivy2 -Dsbt.override.build.repos=true -Dsbt.repository.config=$scriptsDir/repositories-scala-release -Dsbt.global.base=$HOME/.sbt/0.13 -sbt-dir $HOME/.sbt/0.13"
+
+sbtBuild() {
+ echo "### sbtBuild: "$sbtCmd $sbtArgs "${scalaVersionTasks[@]}" "${publishTasks[@]}" "$@"
+ $sbtCmd $sbtArgs "${scalaVersionTasks[@]}" "${publishTasks[@]}" "$@" >> $baseDir/logs/builds 2>&1
+}
+
+sbtResolve() {
+ cd $baseDir/resolutionScratch_
+ touch build.sbt
+ cross=${4-binary} # Disabled / binary / full
+ echo "### sbtResolve: $sbtCmd $sbtArgs " "${scalaVersionTasks[@]}" "\"$1\" % \"$2\" % \"$3\" cross CrossVersion.$cross"
+ $sbtCmd $sbtArgs "${scalaVersionTasks[@]}" \
+ "set libraryDependencies := Seq(\"$1\" % \"$2\" % \"$3\" cross CrossVersion.$cross)" \
+ 'show update' >> $baseDir/logs/resolution 2>&1
+}
+
+# Oh boy... can't use scaladoc to document scala-xml/scala-parser-combinators
+# if scaladoc depends on the same version of scala-xml/scala-parser-combinators.
+# Even if that version is available through the project's resolvers, sbt won't look past this project.
+# SOOOOO, we set the version to a dummy (-DOC), generate documentation,
+# then set the version to the right one and publish (which won't re-gen the docs).
+# Also tried publish-local without docs using 'set publishArtifact in (Compile, packageDoc) := false' and republishing, no dice.
+
+# Each buildModule() function is invoked twice: first to build against locker and publish to private-repo, then
+# to build against the release and publish to sonatype (or publish-local if publishToSonatype is not "yes").
+# In the second round, sbtResolve is always true: the module will be found in the private-repo!
+# Therefore, if MODULE_BUILT is "yes" (in the second round), we know that we need to build (and publish) the
+# module again.
+#
+# Note: we tried an alternative solution in which sbtResolve would not look at private-repo, but that fails. For example,
+# scala-xml depends on scala-library, so sbt tries to find the scala-library of the version that we are currently building,
+# which exists only in private-repo.
+
+buildXML() {
+ if [ "$XML_BUILT" != "yes" ] && [ "$forceRebuild" != "yes" ] && ( sbtResolve "org.scala-lang.modules" "scala-xml" $XML_VER )
+ then echo "Found scala-xml $XML_VER; not building."
+ else
+ update scala scala-xml "$XML_REF" && gfxd
+ sbtBuild 'set version := "'$XML_VER'-DOC"' $clean doc 'set version := "'$XML_VER'"' test "${buildTasks[@]}"
+ XML_BUILT="yes" # ensure the module is built and published when buildXML is invoked for the second time, see comment above
+ fi
+}
+
+buildParsers() {
+ if [ "$PARSERS_BUILT" != "yes" ] && [ "$forceRebuild" != "yes" ] && ( sbtResolve "org.scala-lang.modules" "scala-parser-combinators" $PARSERS_VER )
+ then echo "Found scala-parser-combinators $PARSERS_VER; not building."
+ else
+ update scala scala-parser-combinators "$PARSERS_REF" && gfxd
+ sbtBuild 'set version := "'$PARSERS_VER'-DOC"' $clean doc 'set version := "'$PARSERS_VER'"' test "${buildTasks[@]}"
+ PARSERS_BUILT="yes"
+ fi
+}
+
+buildPartest() {
+ if [ "$PARTEST_BUILT" != "yes" ] && [ "$forceRebuild" != "yes" ] && ( sbtResolve "org.scala-lang.modules" "scala-partest" $PARTEST_VER )
+ then echo "Found scala-partest $PARTEST_VER; not building."
+ else
+ update scala scala-partest "$PARTEST_REF" && gfxd
+ sbtBuild 'set version :="'$PARTEST_VER'"' 'set VersionKeys.scalaXmlVersion := "'$XML_VER'"' 'set VersionKeys.scalaCheckVersion := "'$SCALACHECK_VER'"' $clean test "${buildTasks[@]}"
+ PARTEST_BUILT="yes"
+ fi
+}
+
+# buildPartestIface() {
+# if [ "$forceRebuild" != "yes" ] && ( sbtResolve "org.scala-lang.modules" "scala-partest-interface" $PARTEST_IFACE_VER )
+# then echo "Found scala-partest-interface $PARTEST_IFACE_VER; not building."
+# else
+# update scala scala-partest-interface "$PARTEST_IFACE_REF" && gfxd
+# sbtBuild 'set version :="'$PARTEST_IFACE_VER'"' $clean "${buildTasks[@]}"
+# fi
+# }
+
+buildContinuations() {
+ if [ "$CONT_PLUG_BUILT" != "yes" ] && [ "$forceRebuild" != "yes" ] && ( sbtResolve "org.scala-lang.plugins" "scala-continuations-plugin" $CONTINUATIONS_VER full )
+ then echo "Found scala-continuations-plugin $CONTINUATIONS_VER; not building."
+ else
+ update scala scala-continuations $CONTINUATIONS_REF && gfxd
+
+ $sbtCmd $sbtArgs 'project plugin' "${scalaVersionTasks[@]}" "${publishTasks[@]}" \
+ 'set version := "'$CONTINUATIONS_VER'"' $clean "compile:package" test "${buildTasks[@]}" # https://github.com/scala/scala-continuations/pull/4
+ CONT_PLUG_BUILT="yes"
+ fi
+
+ if [ "$CONT_LIB_BUILT" != "yes" ] && [ "$forceRebuild" != "yes" ] && ( sbtResolve "org.scala-lang.plugins" "scala-continuations-library" $CONTINUATIONS_VER )
+ then echo "Found scala-continuations-library $CONTINUATIONS_VER; not building."
+ else
+ update scala scala-continuations $CONTINUATIONS_REF && gfxd
+ $sbtCmd $sbtArgs 'project library' "${scalaVersionTasks[@]}" "${publishTasks[@]}" \
+ 'set version := "'$CONTINUATIONS_VER'"' $clean test "${buildTasks[@]}"
+ CONT_LIB_BUILT="yes"
+ fi
+}
+
+buildSwing() {
+ if [ "$SWING_BUILT" != "yes" ] && [ "$forceRebuild" != "yes" ] && ( sbtResolve "org.scala-lang.modules" "scala-swing" $SWING_VER )
+ then echo "Found scala-swing $SWING_VER; not building."
+ else
+ update scala scala-swing "$SWING_REF" && gfxd
+ sbtBuild 'set version := "'$SWING_VER'"' $clean test "${buildTasks[@]}"
+ SWING_BUILT="yes"
+ fi
+}
+
+buildActorsMigration(){
+ if [ "$ACTORS_MIGRATION_BUILT" != "yes" ] && [ "$forceRebuild" != "yes" ] && ( sbtResolve "org.scala-lang" "scala-actors-migration" $ACTORS_MIGRATION_VER )
+ then echo "Found scala-actors-migration $ACTORS_MIGRATION_VER; not building."
+ else
+ update scala actors-migration "$ACTORS_MIGRATION_REF" && gfxd
+ # not running tests because
+ # [error] Test scala.actors.migration.NestedReact.testNestedReactAkka failed: java.util.concurrent.TimeoutException: Futures timed out after [20 seconds]
+ sbtBuild 'set version := "'$ACTORS_MIGRATION_VER'"' 'set VersionKeys.continuationsVersion := "'$CONTINUATIONS_VER'"' $clean "${buildTasks[@]}"
+ ACTORS_MIGRATION_BUILT="yes"
+ fi
+}
+
+buildScalacheck(){
+ if [ "$SCALACHECK_BUILT" != "yes" ] && [ "$forceRebuild" != "yes" ] && ( sbtResolve "org.scalacheck" "scalacheck" $SCALACHECK_VER )
+ then echo "Found scalacheck $SCALACHECK_VER; not building."
+ else
+ update rickynils scalacheck $SCALACHECK_REF && gfxd
+ sbtBuild 'set version := "'$SCALACHECK_VER'"' 'set VersionKeys.scalaParserCombinatorsVersion := "'$PARSERS_VER'"' $clean $publishPrivateTask # test times out NOTE: never published to sonatype
+ SCALACHECK_BUILT="yes"
+ fi
+}
+
+# build modules, using ${buildTasks[@]} (except for Scalacheck, which is hard-coded to publish to private-repo)
+buildModules() {
+ buildXML
+ buildParsers
+ buildContinuations
+ buildSwing
+ buildActorsMigration
+ buildScalacheck
+ buildPartest
+ # buildPartestIface
+}
+
+
+## BUILD STEPS:
+
+determineScalaVersion() {
+ cd $WORKSPACE
+ parseScalaProperties "versions.properties"
+
+ if [ -z "$SCALA_VER_BASE" ]; then
+ echo "No SCALA_VER_BASE specified."
+
+ scalaTag=$(git describe --exact-match ||:)
+
+ SCALA_BINARY_VER=${SCALA_BINARY_VER-"$scala_binary_version"}
+
+ if [ -z "$scalaTag" ]
+ then
+ echo "No tag found, building nightly snapshot."
+ parseScalaProperties "build.number"
+ SCALA_VER_BASE="$version_major.$version_minor.$version_patch"
+ SCALA_VER_SUFFIX="-$(git rev-parse --short HEAD)-nightly"
+ SCALADOC_SOURCE_LINKS_VER=$(git rev-parse HEAD)
+
+ # TODO: publish nightly snapshot using this script
+ publishToSonatype="no"
+ echo "repo_ref=2.11.x" >> $baseDir/jenkins.properties # for the -dist downstream jobs that build the actual archives
+ else
+ echo "HEAD is tagged as $scalaTag."
+ # borrowed from https://github.com/cloudflare/semver_bash/blob/master/semver.sh
+ local RE='v*\([0-9]*\)[.]\([0-9]*\)[.]\([0-9]*\)\([0-9A-Za-z-]*\)' # don't change this to make it more accurate, it's not worth it
+ SCALA_VER_BASE="$(echo $scalaTag | sed -e "s#$RE#\1.\2.\3#")"
+ SCALA_VER_SUFFIX="$(echo $scalaTag | sed -e "s#$RE#\4#")"
+ SCALADOC_SOURCE_LINKS_VER=$scalaTag
+
+ if [ "$SCALA_VER_BASE" == "$scalaTag" ]; then
+ echo "Could not parse version $scalaTag"
+ exit 1
+ fi
+ publishToSonatype=${publishToSonatype-"yes"} # unless forced previously, publish
+ fi
+ else
+ publishToSonatype=${publishToSonatype-"yes"} # unless forced previously, publish
+ # if version base/suffix are provided, we assume a corresponding tag exists for the scaladoc source links
+ SCALADOC_SOURCE_LINKS_VER="v$SCALA_VER_BASE$SCALA_VER_SUFFIX"
+ fi
+
+ SCALA_VER="$SCALA_VER_BASE$SCALA_VER_SUFFIX"
+ echo "version=$SCALA_VER" >> $baseDir/jenkins.properties
+ echo "sbtDistVersionOverride=-Dproject.version=$SCALA_VER" >> $baseDir/jenkins.properties
+
+ # We don't override the scala binary version: when running in -nightly + versions.properties versioning mode,
+ # we intend to be a drop-in replacement -- all you need to do is change the Scala version
+ # In order to override this, add 'set every scalaBinaryVersion := "'$SCALA_BINARY_VER'"',
+ # which, when used with pre-release Scala version numbers, will require tweaking at the sbt usage site as well.
+ scalaVersionTasks=('set every scalaVersion := "'$SCALA_VER'"')
+
+ echo "Building Scala $SCALA_VER."
+}
+
+deriveVersion() {
+ update $1 $2 $3 &> /dev/null
+ echo "$(git describe --match=v* | cut -dv -f2)-nightly"
+}
+
+deriveVersionAnyTag() {
+ update $1 $2 $3 &> /dev/null
+ echo "$(git describe | cut -dv -f2)-nightly"
+}
+
+# determineScalaVersion must have been called
+deriveModuleVersions() {
+ if [ "$moduleVersioning" == "versions.properties" ]
+ then
+ # use versions.properties as defaults when no version specified on command line
+ XML_VER=${XML_VER-$scala_xml_version_number}
+ PARSERS_VER=${PARSERS_VER-$scala_parser_combinators_version_number}
+ CONTINUATIONS_VER=${CONTINUATIONS_VER-$scala_continuations_plugin_version_number}
+ SWING_VER=${SWING_VER-$scala_swing_version_number}
+ ACTORS_MIGRATION_VER=${ACTORS_MIGRATION_VER-$actors_migration_version_number}
+ PARTEST_VER=${PARTEST_VER-$partest_version_number}
+ SCALACHECK_VER=${SCALACHECK_VER-$scalacheck_version_number}
+
+ # If a _VER was not specified, the corresponding _REF will be non-empty by now (as specified, or HEAD)
+ XML_REF=${XML_REF-"v$XML_VER"}
+ PARSERS_REF=${PARSERS_REF-"v$PARSERS_VER"}
+ CONTINUATIONS_REF=${CONTINUATIONS_REF-"v$CONTINUATIONS_VER"}
+ SWING_REF=${SWING_REF-"v$SWING_VER"}
+ ACTORS_MIGRATION_REF=${ACTORS_MIGRATION_REF-"v$ACTORS_MIGRATION_VER"}
+ PARTEST_REF=${PARTEST_REF-"v$PARTEST_VER"}
+ # PARTEST_IFACE_REF=${PARTEST_IFACE_REF-"v$PARTEST_IFACE_VER"}
+ SCALACHECK_REF=${SCALACHECK_REF-"$SCALACHECK_VER"}
+ else
+ XML_VER=${XML_VER-$(deriveVersion scala scala-xml "$XML_REF")}
+ PARSERS_VER=${PARSERS_VER-$(deriveVersion scala scala-parser-combinators "$PARSERS_REF")}
+ CONTINUATIONS_VER=${CONTINUATIONS_VER-$(deriveVersion scala scala-continuations "$CONTINUATIONS_REF")}
+ SWING_VER=${SWING_VER-$(deriveVersion scala scala-swing "$SWING_REF")}
+ ACTORS_MIGRATION_VER=${ACTORS_MIGRATION_VER-$(deriveVersion scala actors-migration "$ACTORS_MIGRATION_REF")}
+ PARTEST_VER=${PARTEST_VER-$(deriveVersion scala scala-partest "$PARTEST_REF")}
+ SCALACHECK_VER=${SCALACHECK_VER-$(deriveVersionAnyTag rickynils scalacheck "$SCALACHECK_REF")}
+
+ XML_REF=${XML_REF-"HEAD"}
+ PARSERS_REF=${PARSERS_REF-"HEAD"}
+ CONTINUATIONS_REF=${CONTINUATIONS_REF-"HEAD"}
+ SWING_REF=${SWING_REF-"HEAD"}
+ ACTORS_MIGRATION_REF=${ACTORS_MIGRATION_REF-"HEAD"}
+ PARTEST_REF=${PARTEST_REF-"HEAD"}
+ # PARTEST_IFACE_REF=${PARTEST_IFACE_REF-"HEAD"}
+ SCALACHECK_REF=${SCALACHECK_REF-"HEAD"}
+ fi
+
+ echo "Module versions (versioning strategy: $moduleVersioning):"
+ echo "ACTORS_MIGRATION = $ACTORS_MIGRATION_VER at $ACTORS_MIGRATION_REF"
+ echo "CONTINUATIONS = $CONTINUATIONS_VER at $CONTINUATIONS_REF"
+ echo "PARSERS = $PARSERS_VER at $PARSERS_REF"
+ echo "PARTEST = $PARTEST_VER at $PARTEST_REF"
+ echo "SCALACHECK = $SCALACHECK_VER at $SCALACHECK_REF"
+ echo "SWING = $SWING_VER at $SWING_REF"
+ echo "XML = $XML_VER at $XML_REF"
+
+ # PARTEST_IFACE_VER=${PARTEST_IFACE_VER-$(deriveVersion scala scala-partest-interface "$PARTEST_IFACE_REF")}
+}
+
+constructUpdatedModuleVersions() {
+ updatedModuleVersions=()
+
+ # force the new module versions for building the core. these may be different from the values in versions.properties,
+ # either because the variables (XML_VER) were provided, or because we're building the modules from HEAD.
+ # in the common case, the values are the same as in versions.properties.
+ updatedModuleVersions=("${updatedModuleVersions[@]}" "-Dactors-migration.version.number=$ACTORS_MIGRATION_VER")
+ updatedModuleVersions=("${updatedModuleVersions[@]}" "-Dscala-continuations-library.version.number=$CONTINUATIONS_VER")
+ updatedModuleVersions=("${updatedModuleVersions[@]}" "-Dscala-continuations-plugin.version.number=$CONTINUATIONS_VER")
+ updatedModuleVersions=("${updatedModuleVersions[@]}" "-Dscala-parser-combinators.version.number=$PARSERS_VER")
+ updatedModuleVersions=("${updatedModuleVersions[@]}" "-Dscala-swing.version.number=$SWING_VER")
+ updatedModuleVersions=("${updatedModuleVersions[@]}" "-Dscala-xml.version.number=$XML_VER")
+
+ updatedModuleVersions=("${updatedModuleVersions[@]}" "-Dpartest.version.number=$PARTEST_VER")
+ updatedModuleVersions=("${updatedModuleVersions[@]}" "-Dscalacheck.version.number=$SCALACHECK_VER")
+
+ # allow overriding the akka-actors and jline version using a jenkins build parameter
+ if [ ! -z "$AKKA_ACTOR_VER" ]; then updatedModuleVersions=("${updatedModuleVersions[@]}" "-Dakka-actor.version.number=$AKKA_ACTOR_VER"); fi
+ if [ ! -z "$JLINE_VER" ] ; then updatedModuleVersions=("${updatedModuleVersions[@]}" "-Djline.version=$JLINE_VER"); fi
+
+ if [ ! -z "$SCALA_BINARY_VER" ]; then updatedModuleVersions=("${updatedModuleVersions[@]}" "-Dscala.binary.version=$SCALA_BINARY_VER"); fi
+ if [ ! -z "$SCALA_FULL_VER" ] ; then updatedModuleVersions=("${updatedModuleVersions[@]}" "-Dscala.full.version=$SCALA_FULL_VER"); fi
+}
+
+# build locker (scala + modules) and quick, publishing everything to private-repo
+bootstrap() {
+ echo "### Bootstrapping"
+
+ cd $WORKSPACE
+
+ #### LOCKER
+
+ echo "### Building locker"
+
+ # for bootstrapping, publish core (or at least smallest subset we can get away with)
+ # so that we can build modules with this version of Scala and publish them locally
+ # must publish under $SCALA_VER so that the modules will depend on this (binary) version of Scala
+ # publish more than just core: partest needs scalap
+ # in sabbus lingo, the resulting Scala build will be used as starr to build the released Scala compiler
+ ant -Dmaven.version.number=$SCALA_VER\
+ -Dremote.snapshot.repository=NOPE\
+ -Dremote.release.repository=$privateRepo\
+ -Drepository.credentials.id=$privateCred\
+ -Dscalac.args.optimise=-optimise\
+ -Ddocs.skip=1\
+ -Dlocker.skip=1\
+ $publishLockerPrivateTask >> $baseDir/logs/builds 2>&1
+
+
+ echo "### Building modules using locker"
+
+ # build, test and publish modules with this core
+ # publish to our internal repo (so we can resolve the modules in the scala build below)
+ # we only need to build the modules necessary to build Scala itself
+ # since the version of locker and quick are the same
+ publishTasks=('set credentials += Credentials(Path.userHome / ".credentials-private-repo")' "set every publishTo := Some(\"private-repo\" at \"$privateRepo\")")
+ buildTasks=($publishPrivateTask)
+ buildModules
+
+ constructUpdatedModuleVersions
+
+ #### QUICK
+
+ echo "### Bootstrapping Scala using locker"
+
+ # # TODO: close all open staging repos so that we can be reaonably sure the only open one we see after publishing below is ours
+ # # the ant call will create a new one
+ #
+ # Rebuild Scala with these modules so that all binary versions are consistent.
+ # Update versions.properties to new modules.
+ # Sanity check: make sure the Scala test suite passes / docs can be generated with these modules.
+ # don't skip locker (-Dlocker.skip=1), or stability will fail
+ # overwrite "locker" version of scala at private-repo with bootstrapped version
+ cd $baseDir
+ rm -rf build/ # must leave everything else in $baseDir for downstream jobs
+
+ ant -Dstarr.version=$SCALA_VER\
+ -Dextra.repo.url=$privateRepo\
+ -Dmaven.version.suffix=$SCALA_VER_SUFFIX\
+ ${updatedModuleVersions[@]} \
+ -Dupdate.versions=1\
+ -Dscaladoc.git.commit=$SCALADOC_SOURCE_LINKS_VER\
+ -Dremote.snapshot.repository=NOPE\
+ -Dremote.release.repository=$privateRepo\
+ -Drepository.credentials.id=$privateCred\
+ -Dscalac.args.optimise=-optimise\
+ $antBuildTask $publishPrivateTask
+
+ # clear ivy cache (and to be sure, local as well), so the next round of sbt builds sees the fresh scala
+ rm -rf $baseDir/ivy2
+
+ # TODO: create PR with following commit (note that release will have been tagged already)
+ # git commit versions.properties -m"Bump versions.properties for $SCALA_VER."
+}
+
+# assumes we just bootstrapped, and current directory is $baseDir
+# publishes locker to sonatype, then builds modules again (those for which version numbers were provided),
+# and publishes those to sonatype as well
+# finally, the staging repos are closed
+publishSonatype() {
+ # stage to sonatype, along with all modules -Dmaven.version.suffix/-Dbuild.release not necessary,
+ # since we're just publishing an existing build
+ echo "### Publishing core to sonatype"
+ ant -Dmaven.version.number=$SCALA_VER $publishSonatypeTaskCore
+
+ echo "### Publishing modules to sonatype"
+ # build/test/publish scala core modules to sonatype (this will start a new staging repo)
+ # (was hoping we could make everything go to the same staging repo, but it's not timing that causes two staging repos to be opened)
+ # NOTE: only publish those for which versions are set
+ # test and publish to sonatype, assuming you have ~/.sbt/0.13/sonatype.sbt and ~/.sbt/0.13/plugin/gpg.sbt
+ publishTasks=('set credentials += Credentials(Path.userHome / ".credentials-sonatype")' "set pgpPassphrase := Some(Array.empty)")
+ buildTasks=($publishSonatypeTaskModules)
+ buildModules
+
+ open=$(st_stagingReposOpen)
+ allOpenUrls=$(echo $open | jq '.repositoryURI' | tr -d \")
+ allOpen=$(echo $open | jq '.repositoryId' | tr -d \")
+
+ echo "Closing open repos: $allOpen"
+
+ for repo in $allOpen; do st_stagingRepoClose $repo; done
+
+ echo "Closed sonatype staging repos: $allOpenUrls."
+}
+
+
+#### MAIN
+
+determineScalaVersion
+
+deriveModuleVersions
+
+bootstrap
+
+if [ "$publishToSonatype" == "yes" ]
+ then publishSonatype
+ else # build modules one more time, just to mimic the regular build as much when running as nightly
+ echo "### Rebuilding modules with quick, publishing to $baseDir/ivy/local"
+ buildTasks=(publish-local)
+ # buildScalacheck always uses publishPrivateTask (not buildTasks). we override it to avoid publishing to private-repo.
+ publishPrivateTask="publish-local"
+ forceRebuild="yes"
+ buildModules
+fi
diff --git a/scripts/jobs/integrate/ide b/scripts/jobs/integrate/ide
new file mode 100755
index 0000000000..5c1e6199e3
--- /dev/null
+++ b/scripts/jobs/integrate/ide
@@ -0,0 +1,32 @@
+#!/bin/bash -e
+# requires checkout: root is a scala checkout with which to integrate (actually, only required file is versions.properties, as documented below)
+# requires env: scalaVersion (specifies binary already built from above checkout), WORKSPACE (provided by jenkins), repo_ref (HEAD of the scala checkout),
+# requires files: $baseDir/versions.properties (from checkout -- defines version numbers for modules used to build scala for dbuild...)
+
+# TODO: remove when integration is up and running
+if [ "woele$_scabot_last" != "woele1" ]; then echo "Scabot didn't mark this as last commit -- skipping."; exit 0; fi
+
+baseDir=${WORKSPACE-`pwd`}
+uberBuildUrl=${uberBuildUrl-"https://github.com/scala-ide/uber-build.git"}
+uberBuildConfig=${uberBuildConfig-"validator.conf"} # TODO: backport to 2.10.x: uberBuildConfig="validator-2.10.conf"
+
+uberBuildDir="$baseDir/uber-build/"
+
+cd $baseDir
+if [[ -d $uberBuildDir ]]; then
+ ( cd $uberBuildDir && git fetch $uberBuildUrl HEAD && git checkout -f FETCH_HEAD && git clean -fxd )
+else
+ git clone $uberBuildUrl
+fi
+
+echo "maven.version.number=$scalaVersion" >> versions.properties
+
+# pass prRepoUrl in, which uber-build passes along to dbuild (in sbt-builds-for-ide)
+# the "-P pr-scala" maven arg accomplishes the same thing for maven (directly used in uber-build)
+BASEDIR="$baseDir" prRepoUrl="$prRepoUrl" MAVEN_ARGS="-P pr-scala"\
+ $uberBuildDir/uber-build.sh $uberBuildDir/config/$uberBuildConfig $repo_ref $scalaVersion
+
+# uber-build puts its local repo under target/m2repo
+# wipe the org/scala-lang part, which otherwise just keeps
+# growing and growing due to the -$sha-SNAPSHOT approach
+[[ -d $baseDir/target/m2repo/org/scala-lang ]] && rm -rf $baseDir/target/m2repo/org/scala-lang
diff --git a/scripts/jobs/validate/publish-core b/scripts/jobs/validate/publish-core
new file mode 100755
index 0000000000..9dff5a34b0
--- /dev/null
+++ b/scripts/jobs/validate/publish-core
@@ -0,0 +1,44 @@
+#!/bin/bash -e
+# This script publishes the core of Scala to maven for use as locker downstream,
+# and saves the relevant properties used in its build artifacts, versions.properties.
+# (This means we'll use locker instead of quick downstream in dbuild.
+# The only downside is that backend improvements don't improve compiler performance itself until they are in STARR).
+# The version is suffixed with "-${sha:0:7}-SNAPSHOT"
+
+baseDir=${WORKSPACE-`pwd`}
+scriptsDir="$baseDir/scripts"
+. $scriptsDir/common
+
+case $prDryRun in
+ yep)
+ echo "DRY RUN"
+ mkdir -p build/pack ; mkdir -p dists/maven/latest
+ ;;
+ *)
+ sha=$(git rev-parse HEAD) # TODO: warn if $repo_ref != $sha (we shouldn't do PR validation using symbolic gitrefs)
+ echo "sha/repo_ref == $sha/$repo_ref ?"
+
+ parseScalaProperties build.number
+
+ ./pull-binary-libs.sh
+ # "noyoudont" is there juuuust in case
+ antDeployArgs="-Dmaven.version.suffix=\"-${sha:0:7}-SNAPSHOT\" -Dremote.snapshot.repository=$prRepoUrl -Drepository.credentials.id=pr-scala -Dremote.release.repository=noyoudont"
+
+ echo ">>> Getting Scala version number."
+ ant -q $antDeployArgs init
+ parseScalaProperties buildcharacter.properties # produce maven_version_number
+
+ echo ">>> Checking availability of Scala ${maven_version_number} in $prRepoUrl."
+ checkAvailability "org.scala-lang" "scala-library" "${maven_version_number}" $prRepoUrl; libraryAvailable=$RES
+ checkAvailability "org.scala-lang" "scala-reflect" "${maven_version_number}" $prRepoUrl; reflectAvailable=$RES
+ checkAvailability "org.scala-lang" "scala-compiler" "${maven_version_number}" $prRepoUrl; compilerAvailable=$RES
+
+ if $libraryAvailable && $reflectAvailable && $compilerAvailable; then
+ echo "Scala core already built!"
+ else
+ ant $antDeployArgs $antBuildArgs publish-opt-nodocs
+ fi
+
+ mv buildcharacter.properties jenkins.properties # parsed by the jenkins job
+ ;;
+esac
diff --git a/scripts/jobs/validate/test b/scripts/jobs/validate/test
new file mode 100755
index 0000000000..c1c02c80cb
--- /dev/null
+++ b/scripts/jobs/validate/test
@@ -0,0 +1,17 @@
+#!/bin/bash -e
+
+case $prDryRun in
+ yep)
+ echo "DRY RUN"
+ ;;
+ *)
+ ./pull-binary-libs.sh
+
+ # build quick using STARR built upstream, as specified by scalaVersion
+ # (in that sense it's locker, since it was built with starr by that upstream job)
+ ant -Dstarr.version=$scalaVersion \
+ -Dscalac.args.optimise=-optimise \
+ -Dlocker.skip=1 -Dstarr.use.released=1 -Dextra.repo.url=$prRepoUrl \
+ $testExtraArgs ${testTarget-test.core docs.done}
+ ;;
+esac \ No newline at end of file
diff --git a/scripts/readproperties.awk b/scripts/readproperties.awk
new file mode 100644
index 0000000000..96da94775b
--- /dev/null
+++ b/scripts/readproperties.awk
@@ -0,0 +1,39 @@
+# Adapted from http://stackoverflow.com/questions/1682442/reading-java-properties-file-from-bash/2318840#2318840
+BEGIN {
+ FS="=";
+ n="";
+ v="";
+ c=0; # Not a line continuation.
+}
+/^\#/ { # The line is a comment. Breaks line continuation.
+ c=0;
+ next;
+}
+/\\$/ && (c==0) && (NF>=2) { # Name value pair with a line continuation...
+ e=index($0,"=");
+ n=substr($0,1,e-1);
+ v=substr($0,e+1,length($0) - e - 1); # Trim off the backslash.
+ c=1; # Line continuation mode.
+ next;
+}
+/^[^\\]+\\$/ && (c==1) { # Line continuation. Accumulate the value.
+ v= "" v substr($0,1,length($0)-1);
+ next;
+}
+((c==1) || (NF>=2)) && !/^[^\\]+\\$/ { # End of line continuation, or a single line name/value pair
+ if (c==0) { # Single line name/value pair
+ e=index($0,"=");
+ n=substr($0,1,e-1);
+ v=substr($0,e+1,length($0) - e);
+ } else { # Line continuation mode - last line of the value.
+ c=0; # Turn off line continuation mode.
+ v= "" v $0;
+ }
+ # Make sure the name is a legal shell variable name
+ gsub(/[^A-Za-z0-9_]/,"_",n);
+ # Silently drop everything that might confuse bash.
+ gsub(/[\n\r\\\t'"\$!]/,"",v);
+ print "export " n "=\"" v "\" || echo \"Failed to set " n "\""; # don't make bash crap out when a property could not be parsed
+ n = "";
+ v = "";
+}
diff --git a/scripts/repositories-scala-release b/scripts/repositories-scala-release
new file mode 100644
index 0000000000..00538a08ff
--- /dev/null
+++ b/scripts/repositories-scala-release
@@ -0,0 +1,7 @@
+[repositories]
+ plugins: http://dl.bintray.com/sbt/sbt-plugin-releases/, [organisation]/[module]/(scala_[scalaVersion]/)(sbt_[sbtVersion]/)[revision]/[type]s/[artifact](-[classifier]).[ext]
+ private-repo: http://private-repo.typesafe.com/typesafe/scala-release-temp/
+ typesafe-ivy-releases: http://repo.typesafe.com/typesafe/ivy-releases/, [organization]/[module]/[revision]/[type]s/[artifact](-[classifier]).[ext], bootOnly
+ sbt-plugin-releases: http://scalasbt.artifactoryonline.com/scalasbt/sbt-plugin-releases, [organization]/[module]/(scala_[scalaVersion]/)(sbt_[sbtVersion]/)[revision]/[type]s/[artifact](-[classifier]).[ext]
+ maven-central
+ local \ No newline at end of file
diff --git a/spec/03-types.md b/spec/03-types.md
index d067d45ab2..5658e15f44 100644
--- a/spec/03-types.md
+++ b/spec/03-types.md
@@ -167,8 +167,8 @@ SimpleType ::= SimpleType TypeArgs
TypeArgs ::= ‘[’ Types ‘]’
```
-A parameterized type $T[ U_1 , \ldots , U_n ]$ consists of a type
-designator $T$ and type parameters $U_1 , \ldots , U_n$ where
+A parameterized type $T[ T_1 , \ldots , T_n ]$ consists of a type
+designator $T$ and type parameters $T_1 , \ldots , T_n$ where
$n \geq 1$. $T$ must refer to a type constructor which takes $n$ type
parameters $a_1 , \ldots , a_n$.
diff --git a/spec/04-basic-declarations-and-definitions.md b/spec/04-basic-declarations-and-definitions.md
index aca1c63d22..65d79dd5f4 100644
--- a/spec/04-basic-declarations-and-definitions.md
+++ b/spec/04-basic-declarations-and-definitions.md
@@ -631,7 +631,7 @@ For every parameter $p_{i,j}$ with a default argument a method named
expression. Here, $n$ denotes the parameter's position in the method
declaration. These methods are parametrized by the type parameter clause
`[$\mathit{tps}\,$]` and all value parameter clauses
-`($\mathit{ps}_1$)$\ldots$($\mathit{ps}_{i-1}$)` preceeding $p_{i,j}$.
+`($\mathit{ps}_1$)$\ldots$($\mathit{ps}_{i-1}$)` preceding $p_{i,j}$.
The `$f\$$default$\$$n` methods are inaccessible for
user programs.
diff --git a/spec/05-classes-and-objects.md b/spec/05-classes-and-objects.md
index ef854b2abb..fd20d6ae2c 100644
--- a/spec/05-classes-and-objects.md
+++ b/spec/05-classes-and-objects.md
@@ -128,7 +128,7 @@ consists of the following steps.
occurrence in the linearization.
- Finally the statement sequence $\mathit{stats}\,$ is evaluated.
-###### Delayed Initializaton
+###### Delayed Initialization
The initialization code of an object or class (but not a trait) that follows
the superclass
constructor invocation and the mixin-evaluation of the template's base
diff --git a/spec/06-expressions.md b/spec/06-expressions.md
index afd1492744..133ec3c8e5 100644
--- a/spec/06-expressions.md
+++ b/spec/06-expressions.md
@@ -410,6 +410,19 @@ The final result of the transformation is a block of the form
}
```
+### Signature Polymorphic Methods
+
+For invocations of signature polymorphic methods of the target platform `$f$($e_1 , \ldots , e_m$)`,
+the invoked function has a different method type `($p_1$:$T_1 , \ldots , p_n$:$T_n$)$U$` at each call
+site. The parameter types `$T_ , \ldots , T_n$` are the types of the argument expressions
+`$e_1 , \ldots , e_m$` and `$U$` is the expected type at the call site. If the expected type is
+undefined then `$U$` is `scala.AnyRef`. The parameter names `$p_1 , \ldots , p_n$` are fresh.
+
+###### Note
+
+On the Java platform version 7 and later, the methods `invoke` and `invokeExact` in class
+`java.lang.invoke.MethodHandle` are signature polymorphic.
+
## Method Values
```ebnf
@@ -666,7 +679,7 @@ followed by operators starting with ``|`', etc.
There's one exception to this rule, which concerns
[_assignment operators_](#assignment-operators).
-The precedence of an assigment operator is the same as the one
+The precedence of an assignment operator is the same as the one
of simple assignment `(=)`. That is, it is lower than the
precedence of any other operator.
@@ -1109,7 +1122,7 @@ is `scala.Nothing`.
## Try Expressions
```ebnf
-Expr1 ::= `try' `{' Block `}' [`catch' `{' CaseClauses `}']
+Expr1 ::= `try' (`{' Block `}' | Expr) [`catch' `{' CaseClauses `}']
[`finally' Expr]
```
@@ -1761,7 +1774,7 @@ trait Dynamic {
```
Assume a selection of the form $e.x$ where the type of $e$ conforms to `scala.Dynamic`.
-Further assuming the selection is not followed by any function arguments, such an expression can be rewitten under the conditions given [here](#implicit-conversions) to:
+Further assuming the selection is not followed by any function arguments, such an expression can be rewritten under the conditions given [here](#implicit-conversions) to:
```scala
$e$.applyDynamic("$x$")
diff --git a/spec/08-pattern-matching.md b/spec/08-pattern-matching.md
index 3538457b5c..e75bddc096 100644
--- a/spec/08-pattern-matching.md
+++ b/spec/08-pattern-matching.md
@@ -609,7 +609,7 @@ case class If[T](c: Term[Boolean],
There are terms to represent numeric literals, incrementation, a zero
test, and a conditional. Every term carries as a type parameter the
-type of the expression it representes (either `Int` or `Boolean`).
+type of the expression it represents (either `Int` or `Boolean`).
A type-safe evaluator for such terms can be written as follows.
diff --git a/spec/09-top-level-definitions.md b/spec/09-top-level-definitions.md
index 847fab548d..e3185d8b7d 100644
--- a/spec/09-top-level-definitions.md
+++ b/spec/09-top-level-definitions.md
@@ -159,7 +159,7 @@ The `main` method of a program can be directly defined in the
object, or it can be inherited. The scala library defines a special class
`scala.App` whose body acts as a `main` method.
An objects $m$ inheriting from this class is thus a program,
-which executes the initializaton code of the object $m$.
+which executes the initialization code of the object $m$.
###### Example
The following example will create a hello world program by defining
diff --git a/src/actors/scala/actors/Actor.scala b/src/actors/scala/actors/Actor.scala
index 75160fa18f..293335f720 100644
--- a/src/actors/scala/actors/Actor.scala
+++ b/src/actors/scala/actors/Actor.scala
@@ -205,7 +205,7 @@ object Actor extends Combinators {
* Actions in `f` have to contain the rest of the computation of `self`,
* as this method will never return.
*
- * A common method of continuting the computation is to send a message
+ * A common method of continuing the computation is to send a message
* to another actor:
* {{{
* react {
diff --git a/src/actors/scala/actors/LinkedQueue.java b/src/actors/scala/actors/LinkedQueue.java
index 796f428cf5..3f7b93c386 100644
--- a/src/actors/scala/actors/LinkedQueue.java
+++ b/src/actors/scala/actors/LinkedQueue.java
@@ -22,7 +22,7 @@ package scala.actors;
* and takes when the queue is not empty.
* Normally a put and a take can proceed simultaneously.
* (Although it does not allow multiple concurrent puts or takes.)
- * This class tends to perform more efficently than
+ * This class tends to perform more efficiently than
* other Channel implementations in producer/consumer
* applications.
* <p>[<a href="http://gee.cs.oswego.edu/dl/classes/EDU/oswego/cs/dl/util/concurrent/intro.html"> Introduction to this package. </a>]
diff --git a/src/actors/scala/actors/remote/Proxy.scala b/src/actors/scala/actors/remote/Proxy.scala
index 9949b36181..2cb03544f2 100644
--- a/src/actors/scala/actors/remote/Proxy.scala
+++ b/src/actors/scala/actors/remote/Proxy.scala
@@ -84,7 +84,7 @@ private[remote] class Proxy(node: Node, name: Symbol, @transient var kernel: Net
}
// Proxy is private[remote], but these classes are public and use it in a public
-// method signature. That makes the only method they have non-overriddable.
+// method signature. That makes the only method they have non-overridable.
// So I made them final, which seems appropriate anyway.
final class LinkToFun extends Function2[AbstractActor, Proxy, Unit] with Serializable {
diff --git a/src/actors/scala/actors/threadpool/AbstractCollection.java b/src/actors/scala/actors/threadpool/AbstractCollection.java
index f3dc1e1292..195a0064ab 100644
--- a/src/actors/scala/actors/threadpool/AbstractCollection.java
+++ b/src/actors/scala/actors/threadpool/AbstractCollection.java
@@ -1,6 +1,6 @@
/*
* Written by Dawid Kurzyniec, based on public domain code written by Doug Lea
- * and publictly available documentation, and released to the public domain, as
+ * and publicly available documentation, and released to the public domain, as
* explained at http://creativecommons.org/licenses/publicdomain
*/
diff --git a/src/actors/scala/actors/threadpool/ExecutorCompletionService.java b/src/actors/scala/actors/threadpool/ExecutorCompletionService.java
index 9a4a4fb71c..02e9bbe297 100644
--- a/src/actors/scala/actors/threadpool/ExecutorCompletionService.java
+++ b/src/actors/scala/actors/threadpool/ExecutorCompletionService.java
@@ -135,7 +135,7 @@ public class ExecutorCompletionService implements CompletionService {
* @param completionQueue the queue to use as the completion queue
* normally one dedicated for use by this service. This queue is
* treated as unbounded -- failed attempted <tt>Queue.add</tt>
- * operations for completed taskes cause them not to be
+ * operations for completed tasks cause them not to be
* retrievable.
* @throws NullPointerException if executor or completionQueue are <tt>null</tt>
*/
diff --git a/src/actors/scala/actors/threadpool/locks/ReentrantReadWriteLock.java b/src/actors/scala/actors/threadpool/locks/ReentrantReadWriteLock.java
index 437af77c7a..914d242100 100644
--- a/src/actors/scala/actors/threadpool/locks/ReentrantReadWriteLock.java
+++ b/src/actors/scala/actors/threadpool/locks/ReentrantReadWriteLock.java
@@ -20,13 +20,13 @@ import scala.actors.threadpool.helpers.*;
*
* <p>The order of entry
* to the read and write lock is unspecified, subject to reentrancy
- * constraints. A nonfair lock that is continously contended may
+ * constraints. A nonfair lock that is continuously contended may
* indefinitely postpone one or more reader or writer threads, but
* will normally have higher throughput than a fair lock.
* <p>
*
* DEPARTURE FROM java.util.concurrent: this implementation impose
- * a writer-preferrence and thus its acquisition order may be different
+ * a writer-preference and thus its acquisition order may be different
* than in java.util.concurrent.
*
* <li><b>Reentrancy</b>
diff --git a/src/asm/scala/tools/asm/Label.java b/src/asm/scala/tools/asm/Label.java
index 5d5529ce74..c094eba408 100644
--- a/src/asm/scala/tools/asm/Label.java
+++ b/src/asm/scala/tools/asm/Label.java
@@ -545,7 +545,7 @@ public class Label {
}
// ------------------------------------------------------------------------
- // Overriden Object methods
+ // Overridden Object methods
// ------------------------------------------------------------------------
/**
diff --git a/src/asm/scala/tools/asm/tree/analysis/Analyzer.java b/src/asm/scala/tools/asm/tree/analysis/Analyzer.java
index 0134555f10..ff840aabde 100644
--- a/src/asm/scala/tools/asm/tree/analysis/Analyzer.java
+++ b/src/asm/scala/tools/asm/tree/analysis/Analyzer.java
@@ -375,7 +375,7 @@ public class Analyzer<V extends Value> implements Opcodes {
* instruction of the method. The size of the returned array is
* equal to the number of instructions (and labels) of the method. A
* given frame is <tt>null</tt> if the corresponding instruction
- * cannot be reached, or if an error occured during the analysis of
+ * cannot be reached, or if an error occurred during the analysis of
* the method.
*/
public Frame<V>[] getFrames() {
@@ -435,7 +435,7 @@ public class Analyzer<V extends Value> implements Opcodes {
/**
* Creates a control flow graph edge. The default implementation of this
- * method does nothing. It can be overriden in order to construct the
+ * method does nothing. It can be overridden in order to construct the
* control flow graph of a method (this method is called by the
* {@link #analyze analyze} method during its visit of the method's code).
*
diff --git a/src/asm/scala/tools/asm/tree/analysis/Interpreter.java b/src/asm/scala/tools/asm/tree/analysis/Interpreter.java
index 56f4bedc00..00fe6c8bff 100644
--- a/src/asm/scala/tools/asm/tree/analysis/Interpreter.java
+++ b/src/asm/scala/tools/asm/tree/analysis/Interpreter.java
@@ -82,7 +82,7 @@ public abstract class Interpreter<V extends Value> {
* the bytecode instruction to be interpreted.
* @return the result of the interpretation of the given instruction.
* @throws AnalyzerException
- * if an error occured during the interpretation.
+ * if an error occurred during the interpretation.
*/
public abstract V newOperation(AbstractInsnNode insn)
throws AnalyzerException;
@@ -101,7 +101,7 @@ public abstract class Interpreter<V extends Value> {
* @return the result of the interpretation of the given instruction. The
* returned value must be <tt>equal</tt> to the given value.
* @throws AnalyzerException
- * if an error occured during the interpretation.
+ * if an error occurred during the interpretation.
*/
public abstract V copyOperation(AbstractInsnNode insn, V value)
throws AnalyzerException;
@@ -122,7 +122,7 @@ public abstract class Interpreter<V extends Value> {
* the argument of the instruction to be interpreted.
* @return the result of the interpretation of the given instruction.
* @throws AnalyzerException
- * if an error occured during the interpretation.
+ * if an error occurred during the interpretation.
*/
public abstract V unaryOperation(AbstractInsnNode insn, V value)
throws AnalyzerException;
@@ -146,7 +146,7 @@ public abstract class Interpreter<V extends Value> {
* the second argument of the instruction to be interpreted.
* @return the result of the interpretation of the given instruction.
* @throws AnalyzerException
- * if an error occured during the interpretation.
+ * if an error occurred during the interpretation.
*/
public abstract V binaryOperation(AbstractInsnNode insn, V value1, V value2)
throws AnalyzerException;
@@ -167,7 +167,7 @@ public abstract class Interpreter<V extends Value> {
* the third argument of the instruction to be interpreted.
* @return the result of the interpretation of the given instruction.
* @throws AnalyzerException
- * if an error occured during the interpretation.
+ * if an error occurred during the interpretation.
*/
public abstract V ternaryOperation(AbstractInsnNode insn, V value1,
V value2, V value3) throws AnalyzerException;
@@ -185,7 +185,7 @@ public abstract class Interpreter<V extends Value> {
* the arguments of the instruction to be interpreted.
* @return the result of the interpretation of the given instruction.
* @throws AnalyzerException
- * if an error occured during the interpretation.
+ * if an error occurred during the interpretation.
*/
public abstract V naryOperation(AbstractInsnNode insn,
List<? extends V> values) throws AnalyzerException;
@@ -203,7 +203,7 @@ public abstract class Interpreter<V extends Value> {
* @param expected
* the expected return type of the analyzed method.
* @throws AnalyzerException
- * if an error occured during the interpretation.
+ * if an error occurred during the interpretation.
*/
public abstract void returnOperation(AbstractInsnNode insn, V value,
V expected) throws AnalyzerException;
diff --git a/src/asm/scala/tools/asm/util/Printer.java b/src/asm/scala/tools/asm/util/Printer.java
index 4135672c6b..773f129ad9 100644
--- a/src/asm/scala/tools/asm/util/Printer.java
+++ b/src/asm/scala/tools/asm/util/Printer.java
@@ -181,7 +181,7 @@ public abstract class Printer {
*/
public Printer visitClassTypeAnnotation(final int typeRef,
final TypePath typePath, final String desc, final boolean visible) {
- throw new RuntimeException("Must be overriden");
+ throw new RuntimeException("Must be overridden");
}
/**
@@ -264,7 +264,7 @@ public abstract class Printer {
*/
public Printer visitFieldTypeAnnotation(final int typeRef,
final TypePath typePath, final String desc, final boolean visible) {
- throw new RuntimeException("Must be overriden");
+ throw new RuntimeException("Must be overridden");
}
/**
@@ -287,7 +287,7 @@ public abstract class Printer {
* {@link scala.tools.asm.MethodVisitor#visitParameter(String, int)}.
*/
public void visitParameter(String name, int access) {
- throw new RuntimeException("Must be overriden");
+ throw new RuntimeException("Must be overridden");
}
/**
@@ -309,7 +309,7 @@ public abstract class Printer {
*/
public Printer visitMethodTypeAnnotation(final int typeRef,
final TypePath typePath, final String desc, final boolean visible) {
- throw new RuntimeException("Must be overriden");
+ throw new RuntimeException("Must be overridden");
}
/**
@@ -380,7 +380,7 @@ public abstract class Printer {
visitMethodInsn(opcode, owner, name, desc, itf);
return;
}
- throw new RuntimeException("Must be overriden");
+ throw new RuntimeException("Must be overridden");
}
/**
@@ -397,7 +397,7 @@ public abstract class Printer {
visitMethodInsn(opcode, owner, name, desc);
return;
}
- throw new RuntimeException("Must be overriden");
+ throw new RuntimeException("Must be overridden");
}
/**
@@ -457,7 +457,7 @@ public abstract class Printer {
*/
public Printer visitInsnAnnotation(final int typeRef,
final TypePath typePath, final String desc, final boolean visible) {
- throw new RuntimeException("Must be overriden");
+ throw new RuntimeException("Must be overridden");
}
/**
@@ -473,7 +473,7 @@ public abstract class Printer {
*/
public Printer visitTryCatchAnnotation(final int typeRef,
final TypePath typePath, final String desc, final boolean visible) {
- throw new RuntimeException("Must be overriden");
+ throw new RuntimeException("Must be overridden");
}
/**
@@ -491,7 +491,7 @@ public abstract class Printer {
public Printer visitLocalVariableAnnotation(final int typeRef,
final TypePath typePath, final Label[] start, final Label[] end,
final int[] index, final String desc, final boolean visible) {
- throw new RuntimeException("Must be overriden");
+ throw new RuntimeException("Must be overridden");
}
/**
diff --git a/src/compiler/scala/tools/ant/Scalac.scala b/src/compiler/scala/tools/ant/Scalac.scala
index 8905c94eeb..13bf0ef4c6 100644
--- a/src/compiler/scala/tools/ant/Scalac.scala
+++ b/src/compiler/scala/tools/ant/Scalac.scala
@@ -479,7 +479,7 @@ class Scalac extends ScalaMatchingTask with ScalacShared {
/** Tests if a file exists and prints a warning in case it doesn't. Always
* returns the file, even if it doesn't exist.
- * @param file A file to test for existance.
+ * @param file A file to test for existence.
* @return The same file. */
protected def existing(file: File): File = {
if (!file.exists)
diff --git a/src/compiler/scala/tools/nsc/Global.scala b/src/compiler/scala/tools/nsc/Global.scala
index 733664c30a..1c9dbad4dd 100644
--- a/src/compiler/scala/tools/nsc/Global.scala
+++ b/src/compiler/scala/tools/nsc/Global.scala
@@ -234,7 +234,7 @@ class Global(var currentSettings: Settings, var reporter: Reporter)
/** Called by ScalaDocAnalyzer when a doc comment has been parsed. */
def signalParsedDocComment(comment: String, pos: Position) = {
- // TODO: this is all very borken (only works for scaladoc comments, not regular ones)
+ // TODO: this is all very broken (only works for scaladoc comments, not regular ones)
// --> add hooks to parser and refactor Interactive global to handle comments directly
// in any case don't use reporter for parser hooks
reporter.comment(pos, comment)
@@ -1461,7 +1461,7 @@ class Global(var currentSettings: Settings, var reporter: Reporter)
}
- /** Caching member symbols that are def-s in Defintions because they might change from Run to Run. */
+ /** Caching member symbols that are def-s in Definitions because they might change from Run to Run. */
val runDefinitions: definitions.RunDefinitions = new definitions.RunDefinitions
/** Compile list of source files,
diff --git a/src/compiler/scala/tools/nsc/PhaseAssembly.scala b/src/compiler/scala/tools/nsc/PhaseAssembly.scala
index 1eb6c9da2c..e1cfa63960 100644
--- a/src/compiler/scala/tools/nsc/PhaseAssembly.scala
+++ b/src/compiler/scala/tools/nsc/PhaseAssembly.scala
@@ -18,7 +18,7 @@ trait PhaseAssembly {
/**
* Aux datastructure for solving the constraint system
- * The depency graph container with helper methods for node and edge creation
+ * The dependency graph container with helper methods for node and edge creation
*/
private class DependencyGraph {
diff --git a/src/compiler/scala/tools/nsc/ast/parser/MarkupParsers.scala b/src/compiler/scala/tools/nsc/ast/parser/MarkupParsers.scala
index f1517e56a0..96939e616c 100755
--- a/src/compiler/scala/tools/nsc/ast/parser/MarkupParsers.scala
+++ b/src/compiler/scala/tools/nsc/ast/parser/MarkupParsers.scala
@@ -425,11 +425,10 @@ trait MarkupParsers {
if (ch != '/') ts append xPattern // child
else return false // terminate
- case '{' => // embedded Scala patterns
- while (ch == '{') {
- nextch()
+ case '{' if xCheckEmbeddedBlock => // embedded Scala patterns, if not double brace
+ do {
ts ++= xScalaPatterns
- }
+ } while (xCheckEmbeddedBlock)
assert(!xEmbeddedBlock, "problem with embedded block")
case SU =>
diff --git a/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala b/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala
index d9f56b47fa..cf52ad6636 100644
--- a/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala
+++ b/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala
@@ -1077,7 +1077,7 @@ abstract class GenICode extends SubComponent {
()
case (_, UNIT) =>
ctx.bb.emit(DROP(from), pos)
- // otherwise we'd better be doing a primtive -> primitive coercion or there's a problem
+ // otherwise we'd better be doing a primitive -> primitive coercion or there's a problem
case _ if !from.isRefOrArrayType && !to.isRefOrArrayType =>
coerce(from, to)
case _ =>
@@ -1495,7 +1495,7 @@ abstract class GenICode extends SubComponent {
if (!settings.optimise) {
if (l.tpe <:< BoxedNumberClass.tpe) {
if (r.tpe <:< BoxedNumberClass.tpe) platform.externalEqualsNumNum
- else if (r.tpe <:< BoxedCharacterClass.tpe) platform.externalEqualsNumChar
+ else if (r.tpe <:< BoxedCharacterClass.tpe) platform.externalEqualsNumObject // will be externalEqualsNumChar in 2.12, SI-9030
else platform.externalEqualsNumObject
} else platform.externalEquals
} else {
diff --git a/src/compiler/scala/tools/nsc/backend/icode/Primitives.scala b/src/compiler/scala/tools/nsc/backend/icode/Primitives.scala
index f81c42d836..27bf836484 100644
--- a/src/compiler/scala/tools/nsc/backend/icode/Primitives.scala
+++ b/src/compiler/scala/tools/nsc/backend/icode/Primitives.scala
@@ -60,7 +60,7 @@ trait Primitives { self: ICodes =>
// type : (buf,el) => buf
// range: lf,rg <- { BOOL, Ix, Ux, Rx, REF, STR }
- // jvm : It should call the appropiate 'append' method on StringBuffer
+ // jvm : It should call the appropriate 'append' method on StringBuffer
case class StringConcat(el: TypeKind) extends Primitive
/** Signals the beginning of a series of concatenations.
diff --git a/src/compiler/scala/tools/nsc/backend/icode/analysis/TypeFlowAnalysis.scala b/src/compiler/scala/tools/nsc/backend/icode/analysis/TypeFlowAnalysis.scala
index 676ee12683..b0ad5bdaf9 100644
--- a/src/compiler/scala/tools/nsc/backend/icode/analysis/TypeFlowAnalysis.scala
+++ b/src/compiler/scala/tools/nsc/backend/icode/analysis/TypeFlowAnalysis.scala
@@ -332,13 +332,13 @@ abstract class TypeFlowAnalysis {
`remainingCALLs` also caches info about the typestack just before the callsite, so as to spare computing them again at inlining time.
Besides caching, a further optimization involves skipping those basic blocks whose in-flow and out-flow isn't needed anyway (as explained next).
- A basic block lacking a callsite in `remainingCALLs`, when visisted by the standard algorithm, won't cause any inlining.
+ A basic block lacking a callsite in `remainingCALLs`, when visited by the standard algorithm, won't cause any inlining.
But as we know from the way type-flows are computed, computing the in- and out-flow for a basic block relies in general on those of other basic blocks.
In detail, we want to focus on that sub-graph of the CFG such that control flow may reach a remaining candidate callsite.
Those basic blocks not in that subgraph can be skipped altogether. That's why:
- `forwardAnalysis()` in `MTFAGrowable` now checks for inclusion of a basic block in `relevantBBs`
- same check is performed before adding a block to the worklist, and as part of choosing successors.
- The bookkeeping supporting on-the-fly pruning of irrelevant blocks requires overridding most methods of the dataflow-analysis.
+ The bookkeeping supporting on-the-fly pruning of irrelevant blocks requires overriding most methods of the dataflow-analysis.
The rest of the story takes place in Inliner, which does not visit all of the method's basic blocks but only on those represented in `remainingCALLs`.
diff --git a/src/compiler/scala/tools/nsc/backend/jvm/AsmUtils.scala b/src/compiler/scala/tools/nsc/backend/jvm/AsmUtils.scala
index 7269910af6..75aa0fc984 100644
--- a/src/compiler/scala/tools/nsc/backend/jvm/AsmUtils.scala
+++ b/src/compiler/scala/tools/nsc/backend/jvm/AsmUtils.scala
@@ -5,10 +5,11 @@
package scala.tools.nsc.backend.jvm
-import scala.tools.asm.tree.{AbstractInsnNode, ClassNode, MethodNode}
-import java.io.PrintWriter
+import scala.tools.asm.tree.{InsnList, AbstractInsnNode, ClassNode, MethodNode}
+import java.io.{StringWriter, PrintWriter}
import scala.tools.asm.util.{TraceClassVisitor, TraceMethodVisitor, Textifier}
import scala.tools.asm.ClassReader
+import scala.collection.convert.decorateAsScala._
object AsmUtils {
@@ -36,19 +37,12 @@ object AsmUtils {
def traceMethod(mnode: MethodNode): Unit = {
println(s"Bytecode for method ${mnode.name}")
- val p = new Textifier
- val tracer = new TraceMethodVisitor(p)
- mnode.accept(tracer)
- val w = new PrintWriter(System.out)
- p.print(w)
- w.flush()
+ println(textify(mnode))
}
def traceClass(cnode: ClassNode): Unit = {
println(s"Bytecode for class ${cnode.name}")
- val w = new PrintWriter(System.out)
- cnode.accept(new TraceClassVisitor(w))
- w.flush()
+ println(textify(cnode))
}
def traceClass(bytes: Array[Byte]): Unit = traceClass(readClass(bytes))
@@ -59,8 +53,56 @@ object AsmUtils {
node
}
- def instructionString(instruction: AbstractInsnNode): String = instruction.getOpcode match {
- case -1 => instruction.toString
- case op => scala.tools.asm.util.Printer.OPCODES(op)
+ /**
+ * Returns a human-readable representation of the cnode ClassNode.
+ */
+ def textify(cnode: ClassNode): String = {
+ val trace = new TraceClassVisitor(new PrintWriter(new StringWriter))
+ cnode.accept(trace)
+ val sw = new StringWriter
+ val pw = new PrintWriter(sw)
+ trace.p.print(pw)
+ sw.toString
}
+
+ /**
+ * Returns a human-readable representation of the code in the mnode MethodNode.
+ */
+ def textify(mnode: MethodNode): String = {
+ val trace = new TraceClassVisitor(new PrintWriter(new StringWriter))
+ mnode.accept(trace)
+ val sw = new StringWriter
+ val pw = new PrintWriter(sw)
+ trace.p.print(pw)
+ sw.toString
+ }
+
+ /**
+ * Returns a human-readable representation of the given instruction.
+ */
+ def textify(insn: AbstractInsnNode): String = {
+ val trace = new TraceMethodVisitor(new Textifier)
+ insn.accept(trace)
+ val sw = new StringWriter
+ val pw = new PrintWriter(sw)
+ trace.p.print(pw)
+ sw.toString.trim
+ }
+
+ /**
+ * Returns a human-readable representation of the given instruction sequence.
+ */
+ def textify(insns: Iterator[AbstractInsnNode]): String = {
+ val trace = new TraceMethodVisitor(new Textifier)
+ insns.foreach(_.accept(trace))
+ val sw: StringWriter = new StringWriter
+ val pw: PrintWriter = new PrintWriter(sw)
+ trace.p.print(pw)
+ sw.toString.trim
+ }
+
+ /**
+ * Returns a human-readable representation of the given instruction sequence.
+ */
+ def textify(insns: InsnList): String = textify(insns.iterator().asScala)
}
diff --git a/src/compiler/scala/tools/nsc/backend/jvm/BCodeAsmCommon.scala b/src/compiler/scala/tools/nsc/backend/jvm/BCodeAsmCommon.scala
index 328ec8a033..a5f33aa786 100644
--- a/src/compiler/scala/tools/nsc/backend/jvm/BCodeAsmCommon.scala
+++ b/src/compiler/scala/tools/nsc/backend/jvm/BCodeAsmCommon.scala
@@ -162,4 +162,32 @@ final class BCodeAsmCommon[G <: Global](val global: G) {
assoc.collectFirst {
case (`nme`.value, LiteralAnnotArg(Constant(value: Symbol))) => value
}).flatten.getOrElse(AnnotationRetentionPolicyClassValue)
+
+ def implementedInterfaces(classSym: Symbol): List[Symbol] = {
+ // Additional interface parents based on annotations and other cues
+ def newParentForAnnotation(ann: AnnotationInfo): Option[Type] = ann.symbol match {
+ case RemoteAttr => Some(RemoteInterfaceClass.tpe)
+ case _ => None
+ }
+
+ def isInterfaceOrTrait(sym: Symbol) = sym.isInterface || sym.isTrait
+
+ val allParents = classSym.info.parents ++ classSym.annotations.flatMap(newParentForAnnotation)
+
+ // We keep the superClass when computing minimizeParents to eliminate more interfaces.
+ // Example: T can be eliminated from D
+ // trait T
+ // class C extends T
+ // class D extends C with T
+ val interfaces = erasure.minimizeParents(allParents) match {
+ case superClass :: ifs if !isInterfaceOrTrait(superClass.typeSymbol) =>
+ ifs
+ case ifs =>
+ // minimizeParents removes the superclass if it's redundant, for example:
+ // trait A
+ // class C extends Object with A // minimizeParents removes Object
+ ifs
+ }
+ interfaces.map(_.typeSymbol)
+ }
}
diff --git a/src/compiler/scala/tools/nsc/backend/jvm/BCodeBodyBuilder.scala b/src/compiler/scala/tools/nsc/backend/jvm/BCodeBodyBuilder.scala
index daf36ce374..062daa4eac 100644
--- a/src/compiler/scala/tools/nsc/backend/jvm/BCodeBodyBuilder.scala
+++ b/src/compiler/scala/tools/nsc/backend/jvm/BCodeBodyBuilder.scala
@@ -1225,7 +1225,7 @@ abstract class BCodeBodyBuilder extends BCodeSkelBuilder {
val equalsMethod: Symbol = {
if (l.tpe <:< BoxedNumberClass.tpe) {
if (r.tpe <:< BoxedNumberClass.tpe) platform.externalEqualsNumNum
- else if (r.tpe <:< BoxedCharacterClass.tpe) platform.externalEqualsNumChar
+ else if (r.tpe <:< BoxedCharacterClass.tpe) platform.externalEqualsNumObject // will be externalEqualsNumChar in 2.12, SI-9030
else platform.externalEqualsNumObject
} else platform.externalEquals
}
diff --git a/src/compiler/scala/tools/nsc/backend/jvm/BCodeHelpers.scala b/src/compiler/scala/tools/nsc/backend/jvm/BCodeHelpers.scala
index 806d4b277c..8d1c37532e 100644
--- a/src/compiler/scala/tools/nsc/backend/jvm/BCodeHelpers.scala
+++ b/src/compiler/scala/tools/nsc/backend/jvm/BCodeHelpers.scala
@@ -791,32 +791,28 @@ abstract class BCodeHelpers extends BCodeIdiomatic with BytecodeWriters {
assert(moduleClass.companionClass == NoSymbol, moduleClass)
innerClassBufferASM.clear()
this.cunit = cunit
- val moduleName = internalName(moduleClass) // + "$"
- val mirrorName = moduleName.substring(0, moduleName.length() - 1)
- val flags = (asm.Opcodes.ACC_SUPER | asm.Opcodes.ACC_PUBLIC | asm.Opcodes.ACC_FINAL)
+ val bType = mirrorClassClassBType(moduleClass)
val mirrorClass = new asm.tree.ClassNode
mirrorClass.visit(
classfileVersion,
- flags,
- mirrorName,
+ bType.info.flags,
+ bType.internalName,
null /* no java-generic-signature */,
ObjectReference.internalName,
EMPTY_STRING_ARRAY
)
- if (emitSource) {
- mirrorClass.visitSource("" + cunit.source,
- null /* SourceDebugExtension */)
- }
+ if (emitSource)
+ mirrorClass.visitSource("" + cunit.source, null /* SourceDebugExtension */)
- val ssa = getAnnotPickle(mirrorName, moduleClass.companionSymbol)
+ val ssa = getAnnotPickle(bType.internalName, moduleClass.companionSymbol)
mirrorClass.visitAttribute(if (ssa.isDefined) pickleMarkerLocal else pickleMarkerForeign)
emitAnnotations(mirrorClass, moduleClass.annotations ++ ssa)
- addForwarders(isRemote(moduleClass), mirrorClass, mirrorName, moduleClass)
+ addForwarders(isRemote(moduleClass), mirrorClass, bType.internalName, moduleClass)
- innerClassBufferASM ++= classBTypeFromSymbol(moduleClass).info.memberClasses
+ innerClassBufferASM ++= bType.info.nestedClasses
addInnerClassesASM(mirrorClass, innerClassBufferASM.toList)
mirrorClass.visitEnd()
@@ -932,7 +928,7 @@ abstract class BCodeHelpers extends BCodeIdiomatic with BytecodeWriters {
constructor.visitMaxs(0, 0) // just to follow protocol, dummy arguments
constructor.visitEnd()
- innerClassBufferASM ++= classBTypeFromSymbol(cls).info.memberClasses
+ innerClassBufferASM ++= classBTypeFromSymbol(cls).info.nestedClasses
addInnerClassesASM(beanInfoClass, innerClassBufferASM.toList)
beanInfoClass.visitEnd()
diff --git a/src/compiler/scala/tools/nsc/backend/jvm/BCodeIdiomatic.scala b/src/compiler/scala/tools/nsc/backend/jvm/BCodeIdiomatic.scala
index d58368b19d..c3db28151b 100644
--- a/src/compiler/scala/tools/nsc/backend/jvm/BCodeIdiomatic.scala
+++ b/src/compiler/scala/tools/nsc/backend/jvm/BCodeIdiomatic.scala
@@ -271,7 +271,7 @@ abstract class BCodeIdiomatic extends SubComponent {
assert(from != BOOL && to != BOOL, s"inconvertible types : $from -> $to")
// We're done with BOOL already
- from match {
+ (from: @unchecked) match {
// using `asm.Type.SHORT` instead of `BType.SHORT` because otherwise "warning: could not emit switch for @switch annotated match"
@@ -361,7 +361,7 @@ abstract class BCodeIdiomatic extends SubComponent {
assert(elem.isNonVoidPrimitiveType)
val rand = {
// using `asm.Type.SHORT` instead of `BType.SHORT` because otherwise "warning: could not emit switch for @switch annotated match"
- elem match {
+ (elem: @unchecked) match {
case BOOL => Opcodes.T_BOOLEAN
case BYTE => Opcodes.T_BYTE
case SHORT => Opcodes.T_SHORT
diff --git a/src/compiler/scala/tools/nsc/backend/jvm/BCodeSkelBuilder.scala b/src/compiler/scala/tools/nsc/backend/jvm/BCodeSkelBuilder.scala
index 03bc32061b..142c901c21 100644
--- a/src/compiler/scala/tools/nsc/backend/jvm/BCodeSkelBuilder.scala
+++ b/src/compiler/scala/tools/nsc/backend/jvm/BCodeSkelBuilder.scala
@@ -118,7 +118,7 @@ abstract class BCodeSkelBuilder extends BCodeHelpers {
addClassFields()
- innerClassBufferASM ++= classBTypeFromSymbol(claszSymbol).info.memberClasses
+ innerClassBufferASM ++= classBTypeFromSymbol(claszSymbol).info.nestedClasses
gen(cd.impl)
addInnerClassesASM(cnode, innerClassBufferASM.toList)
diff --git a/src/compiler/scala/tools/nsc/backend/jvm/BCodeSyncAndTry.scala b/src/compiler/scala/tools/nsc/backend/jvm/BCodeSyncAndTry.scala
index 7c95b7fc3b..b94208c1a5 100644
--- a/src/compiler/scala/tools/nsc/backend/jvm/BCodeSyncAndTry.scala
+++ b/src/compiler/scala/tools/nsc/backend/jvm/BCodeSyncAndTry.scala
@@ -284,7 +284,7 @@ abstract class BCodeSyncAndTry extends BCodeBodyBuilder {
* ------
*/
- // a note on terminology: this is not "postHandlers", despite appearences.
+ // a note on terminology: this is not "postHandlers", despite appearances.
// "postHandlers" as in the source-code view. And from that perspective, both (3.A) and (3.B) are invisible implementation artifacts.
if (hasFinally) {
nopIfNeeded(startTryBody)
diff --git a/src/compiler/scala/tools/nsc/backend/jvm/BTypes.scala b/src/compiler/scala/tools/nsc/backend/jvm/BTypes.scala
index 53ac5bfdc7..a9bce82acd 100644
--- a/src/compiler/scala/tools/nsc/backend/jvm/BTypes.scala
+++ b/src/compiler/scala/tools/nsc/backend/jvm/BTypes.scala
@@ -8,16 +8,35 @@ package backend.jvm
import scala.tools.asm
import asm.Opcodes
+import scala.tools.asm.tree.{InnerClassNode, ClassNode}
+import opt.ByteCodeRepository
+import scala.collection.convert.decorateAsScala._
/**
- * The BTypes component defines The BType class hierarchy. BTypes encapsulates all type information
- * that is required after building the ASM nodes. This includes optimizations, geneartion of
+ * The BTypes component defines The BType class hierarchy. BTypes encapsulate all type information
+ * that is required after building the ASM nodes. This includes optimizations, generation of
* InnerClass attributes and generation of stack map frames.
*
* This representation is immutable and independent of the compiler data structures, hence it can
* be queried by concurrent threads.
*/
abstract class BTypes {
+ import BTypes.InternalName
+
+ // Some core BTypes are required here, in class BType, where no Global instance is available.
+ // The Global is only available in the subclass BTypesFromSymbols. We cannot depend on the actual
+ // implementation (CoreBTypesProxy) here because it has members that refer to global.Symbol.
+ val coreBTypes: CoreBTypesProxyGlobalIndependent[this.type]
+ import coreBTypes._
+
+ /**
+ * Tools for parsing classfiles, used by the inliner.
+ */
+ val byteCodeRepository: ByteCodeRepository
+
+ // Allows to define per-run caches here and in the CallGraph component, which don't have a global
+ def recordPerRunCache[T <: collection.generic.Clearable](cache: T): T
+
/**
* A map from internal names to ClassBTypes. Every ClassBType is added to this map on its
* construction.
@@ -29,30 +48,83 @@ abstract class BTypes {
* Concurrent because stack map frames are computed when in the class writer, which might run
* on multiple classes concurrently.
*/
- protected val classBTypeFromInternalNameMap: collection.concurrent.Map[String, ClassBType]
+ val classBTypeFromInternalName: collection.concurrent.Map[InternalName, ClassBType] = recordPerRunCache(collection.concurrent.TrieMap.empty[InternalName, ClassBType])
/**
- * The string represented by the `offset` / `length` values of a ClassBType, see comment of that
- * class.
+ * Parse the classfile for `internalName` and construct the [[ClassBType]].
*/
- protected def internalNameString(offset: Int, lenght: Int): String
+ def classBTypeFromParsedClassfile(internalName: InternalName): ClassBType = {
+ classBTypeFromClassNode(byteCodeRepository.classNode(internalName))
+ }
/**
- * Obtain a previously constructed ClassBType for a given internal name.
+ * Construct the [[ClassBType]] for a parsed classfile.
*/
- def classBTypeFromInternalName(internalName: String) = classBTypeFromInternalNameMap(internalName)
+ def classBTypeFromClassNode(classNode: ClassNode): ClassBType = {
+ classBTypeFromInternalName.getOrElse(classNode.name, {
+ setClassInfo(classNode, ClassBType(classNode.name))
+ })
+ }
- // Some core BTypes are required here, in class BType, where no Global instance is available.
- // The Global is only available in the subclass BTypesFromSymbols. We cannot depend on the actual
- // implementation (CoreBTypesProxy) here because it has members that refer to global.Symbol.
- val coreBTypes: CoreBTypesProxyGlobalIndependent[this.type]
- import coreBTypes._
+ private def setClassInfo(classNode: ClassNode, classBType: ClassBType): ClassBType = {
+ val superClass = classNode.superName match {
+ case null =>
+ assert(classNode.name == ObjectReference.internalName, s"class with missing super type: ${classNode.name}")
+ None
+ case superName =>
+ Some(classBTypeFromParsedClassfile(superName))
+ }
+
+ val interfaces: List[ClassBType] = classNode.interfaces.asScala.map(classBTypeFromParsedClassfile)(collection.breakOut)
+
+ val flags = classNode.access
+
+ /**
+ * Find all nested classes of classNode. The innerClasses attribute contains all nested classes
+ * that are declared inside classNode or used in the bytecode of classNode. So some of them are
+ * nested in some other class than classNode, and we need to filter them.
+ *
+ * For member classes, innerClassNode.outerName is defined, so we compare that to classNode.name.
+ *
+ * For local and anonymous classes, innerClassNode.outerName is null. Such classes are required
+ * to have an EnclosingMethod attribute declaring the outer class. So we keep those local and
+ * anonymous classes whose outerClass is classNode.name.
+ *
+ */
+ def nestedInCurrentClass(innerClassNode: InnerClassNode): Boolean = {
+ (innerClassNode.outerName != null && innerClassNode.outerName == classNode.name) ||
+ (innerClassNode.outerName == null && byteCodeRepository.classNode(innerClassNode.name).outerClass == classNode.name)
+ }
+
+ val nestedClasses: List[ClassBType] = classNode.innerClasses.asScala.collect({
+ case i if nestedInCurrentClass(i) => classBTypeFromParsedClassfile(i.name)
+ })(collection.breakOut)
+
+ // if classNode is a nested class, it has an innerClass attribute for itself. in this
+ // case we build the NestedInfo.
+ val nestedInfo = classNode.innerClasses.asScala.find(_.name == classNode.name) map {
+ case innerEntry =>
+ val enclosingClass =
+ if (innerEntry.outerName != null) {
+ // if classNode is a member class, the outerName is non-null
+ classBTypeFromParsedClassfile(innerEntry.outerName)
+ } else {
+ // for anonymous or local classes, the outerName is null, but the enclosing class is
+ // stored in the EnclosingMethod attribute (which ASM encodes in classNode.outerClass).
+ classBTypeFromParsedClassfile(classNode.outerClass)
+ }
+ val staticFlag = (innerEntry.access & Opcodes.ACC_STATIC) != 0
+ NestedInfo(enclosingClass, Option(innerEntry.outerName), Option(innerEntry.innerName), staticFlag)
+ }
+ classBType.info = ClassInfo(superClass, interfaces, flags, nestedClasses, nestedInfo)
+ classBType
+ }
/**
- * A BType is either a primitve type, a ClassBType, an ArrayBType of one of these, or a MethodType
+ * A BType is either a primitive type, a ClassBType, an ArrayBType of one of these, or a MethodType
* referring to BTypes.
*/
- /*sealed*/ trait BType { // Not sealed for now due to SI-8546
+ sealed trait BType {
final override def toString: String = this match {
case UNIT => "V"
case BOOL => "Z"
@@ -171,6 +243,9 @@ abstract class BTypes {
assert(other.isRef, s"Cannot compute maxType: $this, $other")
// Approximate `lub`. The common type of two references is always ObjectReference.
ObjectReference
+
+ case _: MethodBType =>
+ throw new AssertionError(s"unexpected method type when computing maxType: $this")
}
/**
@@ -369,7 +444,7 @@ abstract class BTypes {
*
* - Initializer block (JLS 8.6 / 8.7): block of statements in a java class
* - static initializer: executed before constructor body
- * - instance initializer: exectued when class is initialized (instance creation, static
+ * - instance initializer: executed when class is initialized (instance creation, static
* field access, ...)
*
* - A static nested class can be defined as
@@ -540,7 +615,7 @@ abstract class BTypes {
*
* class A {
* void f() { class B {} }
- * static void g() { calss C {} }
+ * static void g() { class C {} }
* }
*
* B has an outer pointer, C doesn't. Both B and C are NOT marked static in the InnerClass table.
@@ -568,28 +643,14 @@ abstract class BTypes {
/**
* A ClassBType represents a class or interface type. The necessary information to build a
* ClassBType is extracted from compiler symbols and types, see BTypesFromSymbols.
- *
- * The `offset` and `length` fields are used to represent the internal name of the class. They
- * are indices into some character array. The internal name can be obtained through the method
- * `internalNameString`, which is abstract in this component. Name creation is assumed to be
- * hash-consed, so if two ClassBTypes have the same internal name, they NEED to have the same
- * `offset` and `length`.
- *
- * The actual implementation in subclass BTypesFromSymbols uses the global `chrs` array from the
- * name table. This representation is efficient because the JVM class name is obtained through
- * `classSymbol.javaBinaryName`. This already adds the necessary string to the `chrs` array,
- * so it makes sense to reuse the same name table in the backend.
- *
- * ClassBType is not a case class because we want a custom equals method, and because the
- * extractor extracts the internalName, which is what you typically need.
*/
- final class ClassBType(val offset: Int, val length: Int) extends RefBType {
+ final case class ClassBType(internalName: InternalName) extends RefBType {
/**
* Write-once variable allows initializing a cyclic graph of infos. This is required for
* nested classes. Example: for the definition `class A { class B }` we have
*
* B.info.nestedInfo.outerClass == A
- * A.info.memberClasses contains B
+ * A.info.nestedClasses contains B
*/
private var _info: ClassInfo = null
@@ -604,7 +665,7 @@ abstract class BTypes {
checkInfoConsistency()
}
- classBTypeFromInternalNameMap(internalName) = this
+ classBTypeFromInternalName(internalName) = this
private def checkInfoConsistency(): Unit = {
// we assert some properties. however, some of the linked ClassBType (members, superClass,
@@ -612,7 +673,7 @@ abstract class BTypes {
// best-effort verification.
def ifInit(c: ClassBType)(p: ClassBType => Boolean): Boolean = c._info == null || p(c)
- def isJLO(t: ClassBType) = t.internalName == "java/lang/Object"
+ def isJLO(t: ClassBType) = t.internalName == ObjectReference.internalName
assert(!ClassBType.isInternalPhantomType(internalName), s"Cannot create ClassBType for phantom type $this")
@@ -627,16 +688,10 @@ abstract class BTypes {
s"Invalid interfaces in $this: ${info.interfaces}"
)
- assert(info.memberClasses.forall(c => ifInit(c)(_.isNestedClass)), info.memberClasses)
+ assert(info.nestedClasses.forall(c => ifInit(c)(_.isNestedClass)), info.nestedClasses)
}
/**
- * The internal name of a class is the string returned by java.lang.Class.getName, with all '.'
- * replaced by '/'. For example "java/lang/String".
- */
- def internalName: String = internalNameString(offset, length)
-
- /**
* @return The class name without the package prefix
*/
def simpleName: String = internalName.split("/").last
@@ -661,8 +716,9 @@ abstract class BTypes {
outerName.orNull,
innerName.orNull,
GenBCode.mkFlags(
- info.flags,
- if (isStaticNestedClass) asm.Opcodes.ACC_STATIC else 0
+ // the static flag in the InnerClass table has a special meaning, see InnerClass comment
+ info.flags & ~Opcodes.ACC_STATIC,
+ if (isStaticNestedClass) Opcodes.ACC_STATIC else 0
) & ClassBType.INNER_CLASSES_FLAGS
)
}
@@ -736,33 +792,10 @@ abstract class BTypes {
} while (fcs == null)
fcs
}
-
- /**
- * Custom equals / hashCode: we only compare the name (offset / length)
- */
- override def equals(o: Any): Boolean = (this eq o.asInstanceOf[Object]) || (o match {
- case c: ClassBType => c.offset == this.offset && c.length == this.length
- case _ => false
- })
-
- override def hashCode: Int = {
- import scala.runtime.Statics
- var acc: Int = -889275714
- acc = Statics.mix(acc, offset)
- acc = Statics.mix(acc, length)
- Statics.finalizeHash(acc, 2)
- }
}
object ClassBType {
/**
- * Pattern matching on a ClassBType extracts the `internalName` of the class.
- */
- def unapply(c: ClassBType): Option[String] =
- if (c == null) None
- else Some(c.internalName)
-
- /**
* Valid flags for InnerClass attribute entry.
* See http://docs.oracle.com/javase/specs/jvms/se8/html/jvms-4.html#jvms-4.7.6
*/
@@ -801,12 +834,12 @@ abstract class BTypes {
* through the superclass.
* @param flags The java flags, obtained through `javaFlags`. Used also to derive
* the flags for InnerClass entries.
- * @param memberClasses Classes nested in this class. Those need to be added to the
+ * @param nestedClasses Classes nested in this class. Those need to be added to the
* InnerClass table, see the InnerClass spec summary above.
* @param nestedInfo If this describes a nested class, information for the InnerClass table.
*/
- case class ClassInfo(superClass: Option[ClassBType], interfaces: List[ClassBType], flags: Int,
- memberClasses: List[ClassBType], nestedInfo: Option[NestedInfo])
+ final case class ClassInfo(superClass: Option[ClassBType], interfaces: List[ClassBType], flags: Int,
+ nestedClasses: List[ClassBType], nestedInfo: Option[NestedInfo])
/**
* Information required to add a class to an InnerClass table.
@@ -820,13 +853,13 @@ abstract class BTypes {
*
* (*) Note that the STATIC flag in ClassInfo.flags, obtained through javaFlags(classSym), is not
* correct for the InnerClass entry, see javaFlags. The static flag in the InnerClass describes
- * a source-level propety: if the class is in a static context (does not have an outer pointer).
+ * a source-level property: if the class is in a static context (does not have an outer pointer).
* This is checked when building the NestedInfo.
*/
- case class NestedInfo(enclosingClass: ClassBType,
- outerName: Option[String],
- innerName: Option[String],
- isStaticNestedClass: Boolean)
+ final case class NestedInfo(enclosingClass: ClassBType,
+ outerName: Option[String],
+ innerName: Option[String],
+ isStaticNestedClass: Boolean)
/**
* This class holds the data for an entry in the InnerClass table. See the InnerClass summary
@@ -839,9 +872,9 @@ abstract class BTypes {
* @param innerName The simple name of the inner class, may be null.
* @param flags The flags for this class in the InnerClass entry.
*/
- case class InnerClassEntry(name: String, outerName: String, innerName: String, flags: Int)
+ final case class InnerClassEntry(name: String, outerName: String, innerName: String, flags: Int)
- case class ArrayBType(componentType: BType) extends RefBType {
+ final case class ArrayBType(componentType: BType) extends RefBType {
def dimension: Int = componentType match {
case a: ArrayBType => 1 + a.dimension
case _ => 1
@@ -853,7 +886,7 @@ abstract class BTypes {
}
}
- case class MethodBType(argumentTypes: List[BType], returnType: BType) extends BType
+ final case class MethodBType(argumentTypes: List[BType], returnType: BType) extends BType
/* Some definitions that are required for the implementation of BTypes. They are abstract because
* initializing them requires information from types / symbols, which is not accessible here in
@@ -873,3 +906,12 @@ abstract class BTypes {
*/
def isCompilingPrimitive: Boolean
}
+
+object BTypes {
+ /**
+ * A marker for strings that represent class internal names.
+ * Ideally the type would be incompatible with String, for example by making it a value class.
+ * But that would create overhead in a Collection[InternalName].
+ */
+ type InternalName = String
+} \ No newline at end of file
diff --git a/src/compiler/scala/tools/nsc/backend/jvm/BTypesFromSymbols.scala b/src/compiler/scala/tools/nsc/backend/jvm/BTypesFromSymbols.scala
index 3b7cbd6392..94f9b585d9 100644
--- a/src/compiler/scala/tools/nsc/backend/jvm/BTypesFromSymbols.scala
+++ b/src/compiler/scala/tools/nsc/backend/jvm/BTypesFromSymbols.scala
@@ -7,10 +7,14 @@ package scala.tools.nsc
package backend.jvm
import scala.tools.asm
+import opt.ByteCodeRepository
+import scala.tools.asm.tree.ClassNode
+import scala.tools.nsc.backend.jvm.opt.ByteCodeRepository.Source
+import BTypes.InternalName
/**
* This class mainly contains the method classBTypeFromSymbol, which extracts the necessary
- * information from a symbol and its type to create the correpsonding ClassBType. It requires
+ * information from a symbol and its type to create the corresponding ClassBType. It requires
* access to the compiler (global parameter).
*
* The mixin CoreBTypes defines core BTypes that are used in the backend. Building these BTypes
@@ -32,20 +36,13 @@ class BTypesFromSymbols[G <: Global](val global: G) extends BTypes {
val coreBTypes = new CoreBTypesProxy[this.type](this)
import coreBTypes._
- final def intializeCoreBTypes(): Unit = {
- coreBTypes.setBTypes(new CoreBTypes[this.type](this))
- }
+ val byteCodeRepository = new ByteCodeRepository(global.classPath, recordPerRunCache(collection.concurrent.TrieMap.empty[InternalName, (ClassNode, Source)]))
- def internalNameString(offset: Int, length: Int) = new String(global.chrs, offset, length)
-
- protected val classBTypeFromInternalNameMap = {
- global.perRunCaches.recordCache(collection.concurrent.TrieMap.empty[String, ClassBType])
+ final def initializeCoreBTypes(): Unit = {
+ coreBTypes.setBTypes(new CoreBTypes[this.type](this))
}
- /**
- * Cache for the method classBTypeFromSymbol.
- */
- private val convertedClasses = perRunCaches.newMap[Symbol, ClassBType]()
+ def recordPerRunCache[T <: collection.generic.Clearable](cache: T): T = perRunCaches.recordCache(cache)
// helpers that need access to global.
// TODO @lry create a separate component, they don't belong to BTypesFromSymbols
@@ -89,13 +86,11 @@ class BTypesFromSymbols[G <: Global](val global: G) extends BTypes {
(classSym != NothingClass && classSym != NullClass),
s"Cannot create ClassBType for special class symbol ${classSym.fullName}")
- convertedClasses.getOrElse(classSym, {
- val internalName = classSym.javaBinaryName.toTypeName
- // We first create and add the ClassBType to the hash map before computing its info. This
- // allows initializing cylic dependencies, see the comment on variable ClassBType._info.
- val classBType = new ClassBType(internalName.start, internalName.length)
- convertedClasses(classSym) = classBType
- setClassInfo(classSym, classBType)
+ val internalName = classSym.javaBinaryName.toString
+ classBTypeFromInternalName.getOrElse(internalName, {
+ // The new ClassBType is added to the map in its constructor, before we set its info. This
+ // allows initializing cyclic dependencies, see the comment on variable ClassBType._info.
+ setClassInfo(classSym, ClassBType(internalName))
})
}
@@ -114,7 +109,7 @@ class BTypesFromSymbols[G <: Global](val global: G) extends BTypes {
val superClass = if (superClassSym == NoSymbol) None
else Some(classBTypeFromSymbol(superClassSym))
- val interfaces = getSuperInterfaces(classSym).map(classBTypeFromSymbol)
+ val interfaces = implementedInterfaces(classSym).map(classBTypeFromSymbol)
val flags = javaFlags(classSym)
@@ -126,25 +121,35 @@ class BTypesFromSymbols[G <: Global](val global: G) extends BTypes {
* code generation, but those duplicates will be eliminated when emitting the InnerClass
* attribute.
*
- * Why doe we need to collect classes into innerClassBufferASM at all? To collect references to
+ * Why do we need to collect classes into innerClassBufferASM at all? To collect references to
* nested classes, but NOT nested in C, that are used within C.
*/
val nestedClassSymbols = {
// The lambdalift phase lifts all nested classes to the enclosing class, so if we collect
// member classes right after lambdalift, we obtain all nested classes, including local and
// anonymous ones.
- val nestedClasses = exitingPhase(currentRun.lambdaliftPhase)(memberClassesOf(classSym))
+ val nestedClasses = {
+ val nested = exitingPhase(currentRun.lambdaliftPhase)(memberClassesOf(classSym))
+ if (isTopLevelModuleClass(classSym)) {
+ // For Java compatibility, member classes of top-level objects are treated as members of
+ // the top-level companion class, see comment below.
+ val members = exitingPickler(memberClassesOf(classSym))
+ nested diff members
+ } else {
+ nested
+ }
+ }
- // If this is a top-level class, and it has a companion object, the member classes of the
- // companion are added as members of the class. For example:
+ // If this is a top-level class, the member classes of the companion object are added as
+ // members of the class. For example:
// class C { }
// object C {
// class D
// def f = { class E }
// }
- // The class D is added as a member of class C. The reason is that the InnerClass attribute
- // for D will containt class "C" and NOT the module class "C$" as the outer class of D.
- // This is done by buildNestedInfo, the reason is Java compatibility, see comment in BTypes.
+ // The class D is added as a member of class C. The reason is: for Java compatibility, the
+ // InnerClass attribute for D has "C" (NOT the module class "C$") as the outer class of D
+ // (done by buildNestedInfo). See comment in BTypes.
// For consistency, the InnerClass entry for D needs to be present in C - to Java it looks
// like D is a member of C, not C$.
val linkedClass = exitingPickler(classSym.linkedClassOfClass) // linkedCoC does not work properly in late phases
@@ -174,75 +179,51 @@ class BTypesFromSymbols[G <: Global](val global: G) extends BTypes {
} else true
})
- val memberClasses = nestedClassSymbolsNoJavaModuleClasses.map(classBTypeFromSymbol)
+ val nestedClasses = nestedClassSymbolsNoJavaModuleClasses.map(classBTypeFromSymbol)
val nestedInfo = buildNestedInfo(classSym)
- classBType.info = ClassInfo(superClass, interfaces, flags, memberClasses, nestedInfo)
+ classBType.info = ClassInfo(superClass, interfaces, flags, nestedClasses, nestedInfo)
classBType
}
- /**
- * All interfaces implemented by a class, except for those inherited through the superclass.
- *
- * TODO @lry share code with GenASM
- */
- private def getSuperInterfaces(classSym: Symbol): List[Symbol] = {
-
- // Additional interface parents based on annotations and other cues
- def newParentForAnnotation(ann: AnnotationInfo): Symbol = ann.symbol match {
- case RemoteAttr => RemoteInterfaceClass
- case _ => NoSymbol
- }
-
- val superInterfaces0: List[Symbol] = classSym.mixinClasses
- val superInterfaces = existingSymbols(superInterfaces0 ++ classSym.annotations.map(newParentForAnnotation)).distinct
-
- assert(!superInterfaces.contains(NoSymbol), s"found NoSymbol among: ${superInterfaces.mkString(", ")}")
- assert(superInterfaces.forall(s => s.isInterface || s.isTrait), s"found non-interface among: ${superInterfaces.mkString(", ")}")
-
- erasure.minimizeInterfaces(superInterfaces.map(_.info)).map(_.typeSymbol)
- }
-
private def buildNestedInfo(innerClassSym: Symbol): Option[NestedInfo] = {
assert(innerClassSym.isClass, s"Cannot build NestedInfo for non-class symbol $innerClassSym")
- val isNested = !innerClassSym.rawowner.isPackageClass
- if (!isNested) None
+ val isTopLevel = innerClassSym.rawowner.isPackageClass
+ if (isTopLevel) None
else {
// See comment in BTypes, when is a class marked static in the InnerClass table.
val isStaticNestedClass = isOriginallyStaticOwner(innerClassSym.originalOwner)
// After lambdalift (which is where we are), the rawowoner field contains the enclosing class.
- val enclosingClassSym = {
- if (innerClassSym.isJavaDefined && innerClassSym.rawowner.isModuleClass) {
- // Example java source: class C { static class D { } }
- // The Scala compiler creates a class and a module symbol for C. Because D is a static
- // nested class, the symbol for D is nested in the module class C (not in the class C).
- // For the InnerClass attribute, we use the class symbol C, which represents the situation
- // in the source code.
-
- // Cannot use innerClassSym.isStatic: this method looks at the owner, which is a package
- // at this pahse (after lambdalift, flatten).
- assert(isOriginallyStaticOwner(innerClassSym.originalOwner), innerClassSym.originalOwner)
-
+ val enclosingClass = {
+ // (1) Example java source: class C { static class D { } }
+ // The Scala compiler creates a class and a module symbol for C. Because D is a static
+ // nested class, the symbol for D is nested in the module class C (not in the class C).
+ // For the InnerClass attribute, we use the class symbol C, which represents the situation
+ // in the source code.
+
+ // (2) Java compatibility. See the big comment in BTypes that summarizes the InnerClass spec.
+ if ((innerClassSym.isJavaDefined && innerClassSym.rawowner.isModuleClass) || // (1)
+ (!isAnonymousOrLocalClass(innerClassSym) && isTopLevelModuleClass(innerClassSym.rawowner))) { // (2)
// phase travel for linkedCoC - does not always work in late phases
- exitingPickler(innerClassSym.rawowner.linkedClassOfClass)
+ exitingPickler(innerClassSym.rawowner.linkedClassOfClass) match {
+ case NoSymbol =>
+ // For top-level modules without a companion class, see doc of mirrorClassClassBType.
+ mirrorClassClassBType(exitingPickler(innerClassSym.rawowner))
+
+ case companionClass =>
+ classBTypeFromSymbol(companionClass)
+ }
+ } else {
+ classBTypeFromSymbol(innerClassSym.rawowner)
}
- else innerClassSym.rawowner
}
- val enclosingClass: ClassBType = classBTypeFromSymbol(enclosingClassSym)
val outerName: Option[String] = {
- if (isAnonymousOrLocalClass(innerClassSym)) {
- None
- } else {
- val outerName = innerClassSym.rawowner.javaBinaryName
- // Java compatibility. See the big comment in BTypes that summarizes the InnerClass spec.
- val outerNameModule = if (isTopLevelModuleClass(innerClassSym.rawowner)) outerName.dropModule
- else outerName
- Some(outerNameModule.toString)
- }
+ if (isAnonymousOrLocalClass(innerClassSym)) None
+ else Some(enclosingClass.internalName)
}
val innerName: Option[String] = {
@@ -255,6 +236,29 @@ class BTypesFromSymbols[G <: Global](val global: G) extends BTypes {
}
/**
+ * For top-level objects without a companion class, the compilere generates a mirror class with
+ * static forwarders (Java compat). There's no symbol for the mirror class, but we still need a
+ * ClassBType (its info.nestedClasses will hold the InnerClass entries, see comment in BTypes).
+ */
+ def mirrorClassClassBType(moduleClassSym: Symbol): ClassBType = {
+ assert(isTopLevelModuleClass(moduleClassSym), s"not a top-level module class: $moduleClassSym")
+ val internalName = moduleClassSym.javaBinaryName.dropModule.toString
+ classBTypeFromInternalName.getOrElse(internalName, {
+ val c = ClassBType(internalName)
+ // class info consistent with BCodeHelpers.genMirrorClass
+ val nested = exitingPickler(memberClassesOf(moduleClassSym)) map classBTypeFromSymbol
+ c.info = ClassInfo(
+ superClass = Some(ObjectReference),
+ interfaces = Nil,
+ flags = asm.Opcodes.ACC_SUPER | asm.Opcodes.ACC_PUBLIC | asm.Opcodes.ACC_FINAL,
+ nestedClasses = nested,
+ nestedInfo = None
+ )
+ c
+ })
+ }
+
+ /**
* True for module classes of package level objects. The backend will generate a mirror class for
* such objects.
*/
diff --git a/src/compiler/scala/tools/nsc/backend/jvm/CoreBTypes.scala b/src/compiler/scala/tools/nsc/backend/jvm/CoreBTypes.scala
index fac3c93be2..246235f395 100644
--- a/src/compiler/scala/tools/nsc/backend/jvm/CoreBTypes.scala
+++ b/src/compiler/scala/tools/nsc/backend/jvm/CoreBTypes.scala
@@ -4,7 +4,7 @@ package backend.jvm
import scala.annotation.switch
/**
- * Core BTypes and some other definitions. The initialization of these definitions requies access
+ * Core BTypes and some other definitions. The initialization of these definitions requires access
* to symbols / types (global).
*
* The symbols used to initialize the ClassBTypes may change from one compiler run to the next. To
@@ -18,11 +18,11 @@ import scala.annotation.switch
*
* The definitions in `CoreBTypes` need to be lazy vals to break an initialization cycle. When
* creating a new instance to assign to the proxy, the `classBTypeFromSymbol` invoked in the
- * constructor will actucally go through the proxy. The lazy vals make sure the instance is assigned
+ * constructor will actually go through the proxy. The lazy vals make sure the instance is assigned
* in the proxy before the fields are initialized.
*
* Note: if we did not re-create the core BTypes on each compiler run, BType.classBTypeFromInternalNameMap
- * could not be a perRunCache anymore: the classes defeined here need to be in that map, they are
+ * could not be a perRunCache anymore: the classes defined here need to be in that map, they are
* added when the ClassBTypes are created. The per run cache removes them, so they would be missing
* in the second run.
*/
@@ -192,7 +192,7 @@ class CoreBTypes[BTFS <: BTypesFromSymbols[_ <: Global]](val bTypes: BTFS) {
}
/**
- * This trait make some core BTypes availalbe that don't depend on a Global instance. Some core
+ * This trait make some core BTypes available that don't depend on a Global instance. Some core
* BTypes are required to be accessible in the BTypes trait, which does not have access to Global.
*
* BTypes cannot refer to CoreBTypesProxy because some of its members depend on global, for example
diff --git a/src/compiler/scala/tools/nsc/backend/jvm/GenASM.scala b/src/compiler/scala/tools/nsc/backend/jvm/GenASM.scala
index e56a20c2e7..abe3bc512c 100644
--- a/src/compiler/scala/tools/nsc/backend/jvm/GenASM.scala
+++ b/src/compiler/scala/tools/nsc/backend/jvm/GenASM.scala
@@ -677,7 +677,7 @@ abstract class GenASM extends SubComponent with BytecodeWriters { self =>
def isDeprecated(sym: Symbol): Boolean = { sym.annotations exists (_ matches definitions.DeprecatedAttr) }
- def addInnerClasses(csym: Symbol, jclass: asm.ClassVisitor) {
+ def addInnerClasses(csym: Symbol, jclass: asm.ClassVisitor, isMirror: Boolean = false) {
/* The outer name for this inner class. Note that it returns null
* when the inner class should not get an index in the constant pool.
* That means non-member classes (anonymous). See Section 4.7.5 in the JVMS.
@@ -698,11 +698,19 @@ abstract class GenASM extends SubComponent with BytecodeWriters { self =>
else
innerSym.rawname + innerSym.moduleSuffix
- // This collects all inner classes of csym, including local and anonymous: lambdalift makes
- // them members of their enclosing class.
- innerClassBuffer ++= exitingPhase(currentRun.lambdaliftPhase)(memberClassesOf(csym))
+ innerClassBuffer ++= {
+ val members = exitingPickler(memberClassesOf(csym))
+ // lambdalift makes all classes (also local, anonymous) members of their enclosing class
+ val allNested = exitingPhase(currentRun.lambdaliftPhase)(memberClassesOf(csym))
- // Add members of the companion object (if top-level). why, see comment in BTypes.scala.
+ // for the mirror class, we take the members of the companion module class (Java compat,
+ // see doc in BTypes.scala). for module classes, we filter out those members.
+ if (isMirror) members
+ else if (isTopLevelModule(csym)) allNested diff members
+ else allNested
+ }
+
+ // If this is a top-level class, add members of the companion object.
val linkedClass = exitingPickler(csym.linkedClassOfClass) // linkedCoC does not work properly in late phases
if (isTopLevelModule(linkedClass)) {
// phase travel to exitingPickler: this makes sure that memberClassesOf only sees member classes,
@@ -1206,22 +1214,6 @@ abstract class GenASM extends SubComponent with BytecodeWriters { self =>
def serialVUID: Option[Long] = genBCode.serialVUID(clasz.symbol)
- private def getSuperInterfaces(c: IClass): Array[String] = {
-
- // Additional interface parents based on annotations and other cues
- def newParentForAttr(ann: AnnotationInfo): Symbol = ann.symbol match {
- case RemoteAttr => RemoteInterfaceClass
- case _ => NoSymbol
- }
-
- val ps = c.symbol.info.parents
- val superInterfaces0: List[Symbol] = if(ps.isEmpty) Nil else c.symbol.mixinClasses
- val superInterfaces = existingSymbols(superInterfaces0 ++ c.symbol.annotations.map(newParentForAttr)).distinct
-
- if(superInterfaces.isEmpty) EMPTY_STRING_ARRAY
- else mkArray(erasure.minimizeInterfaces(superInterfaces.map(_.info)).map(t => javaName(t.typeSymbol)))
- }
-
var clasz: IClass = _ // this var must be assigned only by genClass()
var jclass: asm.ClassWriter = _ // the classfile being emitted
var thisName: String = _ // the internal name of jclass
@@ -1242,7 +1234,7 @@ abstract class GenASM extends SubComponent with BytecodeWriters { self =>
val ps = c.symbol.info.parents
val superClass: String = if(ps.isEmpty) JAVA_LANG_OBJECT.getInternalName else javaName(ps.head.typeSymbol)
- val ifaces = getSuperInterfaces(c)
+ val ifaces: Array[String] = implementedInterfaces(c.symbol).map(javaName)(collection.breakOut)
val thisSignature = getGenericSignature(c.symbol, c.symbol.owner)
val flags = mkFlags(
@@ -2812,7 +2804,7 @@ abstract class GenASM extends SubComponent with BytecodeWriters { self =>
addForwarders(isRemote(modsym), mirrorClass, mirrorName, modsym)
- addInnerClasses(modsym, mirrorClass)
+ addInnerClasses(modsym, mirrorClass, isMirror = true)
mirrorClass.visitEnd()
writeIfNotTooBig("" + modsym.name, mirrorName, mirrorClass, modsym)
}
@@ -2947,7 +2939,7 @@ abstract class GenASM extends SubComponent with BytecodeWriters { self =>
} // end of class JBeanInfoBuilder
/** A namespace for utilities to normalize the code of an IMethod, over and beyond what IMethod.normalize() strives for.
- * In particualr, IMethod.normalize() doesn't collapseJumpChains().
+ * In particular, IMethod.normalize() doesn't collapseJumpChains().
*
* TODO Eventually, these utilities should be moved to IMethod and reused from normalize() (there's nothing JVM-specific about them).
*/
@@ -3162,7 +3154,7 @@ abstract class GenASM extends SubComponent with BytecodeWriters { self =>
}
}
- // remove the unusued exception handler references
+ // remove the unused exception handler references
if (settings.debug)
for (exh <- unusedExceptionHandlers) debuglog(s"eliding exception handler $exh because it does not cover any reachable blocks")
m.exh = m.exh filterNot unusedExceptionHandlers
diff --git a/src/compiler/scala/tools/nsc/backend/jvm/GenBCode.scala b/src/compiler/scala/tools/nsc/backend/jvm/GenBCode.scala
index a45f586666..d5e95c47cf 100644
--- a/src/compiler/scala/tools/nsc/backend/jvm/GenBCode.scala
+++ b/src/compiler/scala/tools/nsc/backend/jvm/GenBCode.scala
@@ -286,7 +286,7 @@ abstract class GenBCode extends BCodeSyncAndTry {
val initStart = Statistics.startTimer(BackendStats.bcodeInitTimer)
arrivalPos = 0 // just in case
scalaPrimitives.init()
- bTypes.intializeCoreBTypes()
+ bTypes.initializeCoreBTypes()
Statistics.stopTimer(BackendStats.bcodeInitTimer, initStart)
// initBytecodeWriter invokes fullName, thus we have to run it before the typer-dependent thread is activated.
diff --git a/src/compiler/scala/tools/nsc/backend/jvm/opt/ByteCodeRepository.scala b/src/compiler/scala/tools/nsc/backend/jvm/opt/ByteCodeRepository.scala
new file mode 100644
index 0000000000..7b424d2107
--- /dev/null
+++ b/src/compiler/scala/tools/nsc/backend/jvm/opt/ByteCodeRepository.scala
@@ -0,0 +1,112 @@
+/* NSC -- new Scala compiler
+ * Copyright 2005-2014 LAMP/EPFL
+ * @author Martin Odersky
+ */
+
+package scala.tools.nsc
+package backend.jvm
+package opt
+
+import scala.tools.asm
+import asm.tree._
+import scala.collection.convert.decorateAsScala._
+import scala.tools.nsc.io.AbstractFile
+import scala.tools.nsc.util.ClassFileLookup
+import OptimizerReporting._
+import ByteCodeRepository._
+import BTypes.InternalName
+
+/**
+ * The ByteCodeRepository provides utilities to read the bytecode of classfiles from the compilation
+ * classpath. Parsed classes are cached in the `classes` map.
+ *
+ * @param classPath The compiler classpath where classfiles are searched and read from.
+ * @param classes Cache for parsed ClassNodes. Also stores the source of the bytecode:
+ * [[Classfile]] if read from `classPath`, [[CompilationUnit]] if the bytecode
+ * corresponds to a class being compiled.
+ */
+class ByteCodeRepository(val classPath: ClassFileLookup[AbstractFile], val classes: collection.concurrent.Map[InternalName, (ClassNode, Source)]) {
+ /**
+ * The class node and source for an internal name. If the class node is not yet available, it is
+ * parsed from the classfile on the compile classpath.
+ */
+ def classNodeAndSource(internalName: InternalName): (ClassNode, Source) = {
+ classes.getOrElseUpdate(internalName, (parseClass(internalName), Classfile))
+ }
+
+ /**
+ * The class node for an internal name. If the class node is not yet available, it is parsed from
+ * the classfile on the compile classpath.
+ */
+ def classNode(internalName: InternalName) = classNodeAndSource(internalName)._1
+
+ /**
+ * The field node for a field matching `name` and `descriptor`, accessed in class `classInternalName`.
+ * The declaration of the field may be in one of the superclasses.
+ *
+ * @return The [[FieldNode]] of the requested field and the [[InternalName]] of its declaring class.
+ */
+ def fieldNode(classInternalName: InternalName, name: String, descriptor: String): Option[(FieldNode, InternalName)] = {
+ val c = classNode(classInternalName)
+ c.fields.asScala.find(f => f.name == name && f.desc == descriptor).map((_, classInternalName)) orElse {
+ Option(c.superName).flatMap(n => fieldNode(n, name, descriptor))
+ }
+ }
+
+ /**
+ * The method node for a method matching `name` and `descriptor`, accessed in class `classInternalName`.
+ * The declaration of the method may be in one of the parents.
+ *
+ * @return The [[MethodNode]] of the requested method and the [[InternalName]] of its declaring class.
+ */
+ def methodNode(classInternalName: InternalName, name: String, descriptor: String): Option[(MethodNode, InternalName)] = {
+ val c = classNode(classInternalName)
+ c.methods.asScala.find(m => m.name == name && m.desc == descriptor).map((_, classInternalName)) orElse {
+ val parents = Option(c.superName) ++ c.interfaces.asScala
+ // `view` to stop at the first result
+ parents.view.flatMap(methodNode(_, name, descriptor)).headOption
+ }
+ }
+
+ private def parseClass(internalName: InternalName): ClassNode = {
+ val fullName = internalName.replace('/', '.')
+ classPath.findClassFile(fullName) map { classFile =>
+ val classNode = new asm.tree.ClassNode()
+ val classReader = new asm.ClassReader(classFile.toByteArray)
+ // We don't need frames when inlining, but we want to keep the local variable table, so we
+ // don't use SKIP_DEBUG.
+ classReader.accept(classNode, asm.ClassReader.SKIP_FRAMES)
+ // SKIP_FRAMES leaves line number nodes. Remove them because they are not correct after
+ // inlining.
+ // TODO: we need to remove them also for classes that are not parsed from classfiles, why not simplify and do it once when inlining?
+ // OR: instead of skipping line numbers for inlined code, use write a SourceDebugExtension
+ // attribute that contains JSR-45 data that encodes debugging info.
+ // http://docs.oracle.com/javase/specs/jvms/se7/html/jvms-4.html#jvms-4.7.11
+ // https://jcp.org/aboutJava/communityprocess/final/jsr045/index.html
+ removeLineNumberNodes(classNode)
+ classNode
+ } getOrElse {
+ inlineFailure(s"Class file for class $fullName not found.")
+ }
+ }
+
+ private def removeLineNumberNodes(classNode: ClassNode): Unit = {
+ for (method <- classNode.methods.asScala) {
+ val iter = method.instructions.iterator()
+ while (iter.hasNext) iter.next() match {
+ case _: LineNumberNode => iter.remove()
+ case _ =>
+ }
+ }
+ }
+}
+
+object ByteCodeRepository {
+ /**
+ * The source of a ClassNode in the ByteCodeRepository. Can be either [[CompilationUnit]] if the
+ * class is being compiled or [[Classfile]] if the class was parsed from the compilation classpath.
+ */
+ sealed trait Source
+ object CompilationUnit extends Source
+ object Classfile extends Source
+}
diff --git a/src/compiler/scala/tools/nsc/backend/jvm/opt/LocalOpt.scala b/src/compiler/scala/tools/nsc/backend/jvm/opt/LocalOpt.scala
index 273112b93c..87ad715e4d 100644
--- a/src/compiler/scala/tools/nsc/backend/jvm/opt/LocalOpt.scala
+++ b/src/compiler/scala/tools/nsc/backend/jvm/opt/LocalOpt.scala
@@ -19,16 +19,16 @@ import scala.tools.nsc.settings.ScalaSettings
* Optimizations within a single method.
*
* unreachable code
- * - removes instrucions of basic blocks to which no branch instruction points
+ * - removes instructions of basic blocks to which no branch instruction points
* + enables eliminating some exception handlers and local variable descriptors
* > eliminating them is required for correctness, as explained in `removeUnreachableCode`
*
* empty exception handlers
* - removes exception handlers whose try block is empty
* + eliminating a handler where the try block is empty and reachable will turn the catch block
- * unreachble. in this case "unreachable code" is invoked recursively until reaching a fixpiont.
+ * unreachable. in this case "unreachable code" is invoked recursively until reaching a fixpoint.
* > for try blocks that are unreachable, "unreachable code" removes also the instructions of the
- * catch block, and the recrusive invocation is not necessary.
+ * catch block, and the recursive invocation is not necessary.
*
* simplify jumps
* - various simplifications, see doc domments of individual optimizations
@@ -52,10 +52,10 @@ class LocalOpt(settings: ScalaSettings) {
* cleanups to the bytecode.
*
* @param clazz The class whose methods are optimized
- * @return `true` if unreachable code was elminated in some method, `false` otherwise.
+ * @return `true` if unreachable code was eliminated in some method, `false` otherwise.
*/
def methodOptimizations(clazz: ClassNode): Boolean = {
- settings.Yopt.value.nonEmpty && clazz.methods.asScala.foldLeft(false) {
+ !settings.YoptNone && clazz.methods.asScala.foldLeft(false) {
case (changed, method) => methodOptimizations(method, clazz.name) || changed
}
}
@@ -66,7 +66,7 @@ class LocalOpt(settings: ScalaSettings) {
* We rely on dead code elimination provided by the ASM framework, as described in the ASM User
* Guide (http://asm.ow2.org/index.html), Section 8.2.1. It runs a data flow analysis, which only
* computes Frame information for reachable instructions. Instructions for which no Frame data is
- * available after the analyis are unreachable.
+ * available after the analysis are unreachable.
*
* Also simplifies branching instructions, removes unused local variable descriptors, empty
* exception handlers, unnecessary label declarations and empty line number nodes.
@@ -240,7 +240,7 @@ class LocalOpt(settings: ScalaSettings) {
}
/**
- * The number of local varialbe slots used for parameters and for the `this` reference.
+ * The number of local variable slots used for parameters and for the `this` reference.
*/
private def parametersSize(method: MethodNode): Int = {
// Double / long fields occupy two slots, so we sum up the sizes. Since getSize returns 0 for
@@ -322,7 +322,7 @@ class LocalOpt(settings: ScalaSettings) {
* In order to run an Analyzer, the maxLocals / maxStack fields need to be available. The ASM
* framework only computes these values during bytecode generation.
*
- * Sicne there's currently no better way, we run a bytecode generator on the method and extract
+ * Since there's currently no better way, we run a bytecode generator on the method and extract
* the computed values. This required changes to the ASM codebase:
* - the [[MethodWriter]] class was made public
* - accessors for maxLocals / maxStack were added to the MethodWriter class
@@ -345,7 +345,7 @@ class LocalOpt(settings: ScalaSettings) {
* Removes LineNumberNodes that don't describe any executable instructions.
*
* This method expects (and asserts) that the `start` label of each LineNumberNode is the
- * lexically preceeding label declaration.
+ * lexically preceding label declaration.
*/
def removeEmptyLineNumbers(method: MethodNode): Boolean = {
def isEmpty(node: AbstractInsnNode): Boolean = node.getNext match {
@@ -510,7 +510,7 @@ class LocalOpt(settings: ScalaSettings) {
* CondJump l; [nops, no labels]; GOTO m; [nops]; l: [...]
* => NegatedCondJump m; [nops, no labels]; [nops]; l: [...]
*
- * Note that no label definitions are allowed in the first [nops] section. Otherwsie, there could
+ * Note that no label definitions are allowed in the first [nops] section. Otherwise, there could
* be some other jump to the GOTO, and eliminating it would change behavior.
*
* For technical reasons, we cannot remove the GOTO here (*).Instead this method returns an Option
@@ -542,7 +542,7 @@ class LocalOpt(settings: ScalaSettings) {
* => xRETURN/ATHROW; [any ops]; l: xRETURN/ATHROW
*
* inlining is only done if the GOTO instruction is not part of a try block, otherwise the
- * rewrite might change the behavior. For xRETURN, the reason is that return insructions may throw
+ * rewrite might change the behavior. For xRETURN, the reason is that return instructions may throw
* an IllegalMonitorStateException, as described here:
* http://docs.oracle.com/javase/specs/jvms/se8/html/jvms-6.html#jvms-6.5.return
*/
diff --git a/src/compiler/scala/tools/nsc/backend/jvm/opt/OptimizerReporting.scala b/src/compiler/scala/tools/nsc/backend/jvm/opt/OptimizerReporting.scala
new file mode 100644
index 0000000000..7002e43d98
--- /dev/null
+++ b/src/compiler/scala/tools/nsc/backend/jvm/opt/OptimizerReporting.scala
@@ -0,0 +1,24 @@
+/* NSC -- new Scala compiler
+ * Copyright 2005-2014 LAMP/EPFL
+ * @author Martin Odersky
+ */
+
+package scala.tools.nsc
+package backend.jvm
+
+import scala.tools.asm
+import asm.tree._
+
+/**
+ * Reporting utilities used in the optimizer.
+ */
+object OptimizerReporting {
+ def methodSignature(className: String, methodName: String, methodDescriptor: String): String = {
+ className + "::" + methodName + methodDescriptor
+ }
+
+ def methodSignature(className: String, method: MethodNode): String = methodSignature(className, method.name, method.desc)
+
+ def inlineFailure(reason: String): Nothing = MissingRequirementError.signal(reason)
+ def assertionError(message: String): Nothing = throw new AssertionError(message)
+}
diff --git a/src/compiler/scala/tools/nsc/backend/opt/ConstantOptimization.scala b/src/compiler/scala/tools/nsc/backend/opt/ConstantOptimization.scala
index c6e699373b..0e6ee76eb2 100644
--- a/src/compiler/scala/tools/nsc/backend/opt/ConstantOptimization.scala
+++ b/src/compiler/scala/tools/nsc/backend/opt/ConstantOptimization.scala
@@ -18,7 +18,7 @@ import scala.annotation.tailrec
*
* With some more work it could be extended to
* - cache stable values (final fields, modules) in locals
- * - replace the copy propagation in ClosureElilmination
+ * - replace the copy propagation in ClosureElimination
* - fold constants
* - eliminate unnecessary stores and loads
* - propagate knowledge gathered from conditionals for further optimization
@@ -437,7 +437,7 @@ abstract class ConstantOptimization extends SubComponent {
// TODO if we do all that we need to be careful in the
// case that success and failure are the same target block
// because we're using a Map and don't want one possible state to clobber the other
- // alternative mayb we should just replace the conditional with a jump if both targets are the same
+ // alternative maybe we should just replace the conditional with a jump if both targets are the same
def mightEqual = val1 mightEqual val2
def mightNotEqual = val1 mightNotEqual val2
diff --git a/src/compiler/scala/tools/nsc/backend/opt/DeadCodeElimination.scala b/src/compiler/scala/tools/nsc/backend/opt/DeadCodeElimination.scala
index 4b419b210c..3704acb055 100644
--- a/src/compiler/scala/tools/nsc/backend/opt/DeadCodeElimination.scala
+++ b/src/compiler/scala/tools/nsc/backend/opt/DeadCodeElimination.scala
@@ -223,7 +223,7 @@ abstract class DeadCodeElimination extends SubComponent {
debuglog("Marking instr: \tBB_" + bb + ": " + idx + " " + bb(idx))
val instr = bb(idx)
- // adds the instrutions that define the stack values about to be consumed to the work list to
+ // adds the instructions that define the stack values about to be consumed to the work list to
// be marked useful
def addDefs() = for ((bb1, idx1) <- rdef.findDefs(bb, idx, instr.consumed) if !useful(bb1)(idx1)) {
debuglog(s"\t${bb1(idx1)} is consumed by $instr")
diff --git a/src/compiler/scala/tools/nsc/backend/opt/Inliners.scala b/src/compiler/scala/tools/nsc/backend/opt/Inliners.scala
index aa18b26d93..8f6fc65706 100644
--- a/src/compiler/scala/tools/nsc/backend/opt/Inliners.scala
+++ b/src/compiler/scala/tools/nsc/backend/opt/Inliners.scala
@@ -290,7 +290,7 @@ abstract class Inliners extends SubComponent {
/**
* A transformation local to the body of the IMethod received as argument.
- * An linining decision consists in replacing a callsite with the body of the callee.
+ * An inlining decision consists in replacing a callsite with the body of the callee.
* Please notice that, because `analyzeMethod()` itself may modify a method body,
* the particular callee bodies that end up being inlined depend on the particular order in which methods are visited
* (no topological sorting over the call-graph is attempted).
diff --git a/src/compiler/scala/tools/nsc/classpath/FlatClassPath.scala b/src/compiler/scala/tools/nsc/classpath/FlatClassPath.scala
index 26b5429e23..cb201617d2 100644
--- a/src/compiler/scala/tools/nsc/classpath/FlatClassPath.scala
+++ b/src/compiler/scala/tools/nsc/classpath/FlatClassPath.scala
@@ -23,8 +23,8 @@ trait FlatClassPath extends ClassFileLookup[AbstractFile] {
/** Allows to get entries for packages and classes merged with sources possibly in one pass. */
private[nsc] def list(inPackage: String): FlatClassPathEntries
- // A default implementation which should be overriden, if we can create more efficient
- // solution for given type of FlatClassPath
+ // A default implementation which should be overridden, if we can create the more efficient
+ // solution for a given type of FlatClassPath
override def findClass(className: String): Option[ClassRepresentation[AbstractFile]] = {
val (pkg, simpleClassName) = PackageNameUtils.separatePkgAndClassNames(className)
diff --git a/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala b/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala
index 18e639b81c..a5b722612d 100644
--- a/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala
+++ b/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala
@@ -168,7 +168,7 @@ trait ScalaSettings extends AbsScalaSettings
val termConflict = ChoiceSetting ("-Yresolve-term-conflict", "strategy", "Resolve term conflicts", List("package", "object", "error"), "error")
val inline = BooleanSetting ("-Yinline", "Perform inlining when possible.")
val inlineHandlers = BooleanSetting ("-Yinline-handlers", "Perform exception handler inlining when possible.")
- val YinlinerWarnings= BooleanSetting ("-Yinline-warnings", "Emit inlining warnings. (Normally surpressed due to high volume)")
+ val YinlinerWarnings= BooleanSetting ("-Yinline-warnings", "Emit inlining warnings. (Normally suppressed due to high volume)")
val Xlinearizer = ChoiceSetting ("-Ylinearizer", "which", "Linearizer to use", List("normal", "dfs", "rpo", "dump"), "rpo")
val log = PhasesSetting ("-Ylog", "Log operations during")
val Ylogcp = BooleanSetting ("-Ylog-classpath", "Output information about what classpath is being applied.")
@@ -199,7 +199,7 @@ trait ScalaSettings extends AbsScalaSettings
val Yreplsync = BooleanSetting ("-Yrepl-sync", "Do not use asynchronous code for repl startup")
val Yreplclassbased = BooleanSetting ("-Yrepl-class-based", "Use classes to wrap REPL snippets instead of objects")
val Yreploutdir = StringSetting ("-Yrepl-outdir", "path", "Write repl-generated classfiles to given output directory (use \"\" to generate a temporary dir)" , "")
- val YmethodInfer = BooleanSetting ("-Yinfer-argument-types", "Infer types for arguments of overriden methods.")
+ val YmethodInfer = BooleanSetting ("-Yinfer-argument-types", "Infer types for arguments of overridden methods.")
val etaExpandKeepsStar = BooleanSetting ("-Yeta-expand-keeps-star", "Eta-expand varargs methods to T* rather than Seq[T]. This is a temporary option to ease transition.").withDeprecationMessage(removalIn212)
val inferByName = BooleanSetting ("-Yinfer-by-name", "Allow inference of by-name types. This is a temporary option to ease transition. See SI-7899.").withDeprecationMessage(removalIn212)
val YclasspathImpl = ChoiceSetting ("-YclasspathImpl", "implementation", "Choose classpath scanning method.", List(ClassPathRepresentationType.Recursive, ClassPathRepresentationType.Flat), ClassPathRepresentationType.Recursive)
@@ -215,7 +215,7 @@ trait ScalaSettings extends AbsScalaSettings
object YoptChoices extends MultiChoiceEnumeration {
val unreachableCode = Choice("unreachable-code", "Eliminate unreachable code, exception handlers protecting no instructions, debug information of eliminated variables.")
- val simplifyJumps = Choice("simplify-jumps", "Simplify branching instructions, eliminate unnecessery ones.")
+ val simplifyJumps = Choice("simplify-jumps", "Simplify branching instructions, eliminate unnecessary ones.")
val recurseUnreachableJumps = Choice("recurse-unreachable-jumps", "Recursively apply unreachable-code and simplify-jumps (if enabled) until reaching a fixpoint.")
val emptyLineNumbers = Choice("empty-line-numbers", "Eliminate unnecessary line number information.")
val emptyLabels = Choice("empty-labels", "Eliminate and collapse redundant labels in the bytecode.")
@@ -242,6 +242,7 @@ trait ScalaSettings extends AbsScalaSettings
descr = "Enable optimizations",
domain = YoptChoices)
+ def YoptNone = Yopt.isSetByUser && Yopt.value.isEmpty
def YoptUnreachableCode = !Yopt.isSetByUser || Yopt.contains(YoptChoices.unreachableCode)
def YoptSimplifyJumps = Yopt.contains(YoptChoices.simplifyJumps)
def YoptRecurseUnreachableJumps = Yopt.contains(YoptChoices.recurseUnreachableJumps)
diff --git a/src/compiler/scala/tools/nsc/settings/Warnings.scala b/src/compiler/scala/tools/nsc/settings/Warnings.scala
index c400e8c29c..41ce0837cb 100644
--- a/src/compiler/scala/tools/nsc/settings/Warnings.scala
+++ b/src/compiler/scala/tools/nsc/settings/Warnings.scala
@@ -28,10 +28,11 @@ trait Warnings {
val warnUnusedImport = BooleanSetting("-Ywarn-unused-import", "Warn when imports are unused.")
// Experimental lint warnings that are turned off, but which could be turned on programmatically.
- // These warnings are said to blind those who dare enable them.
- // They are not activated by -Xlint and can't be enabled on the command line.
- val warnValueOverrides = { // currently turned off as experimental. creaded using constructor (new BS), so not available on the command line.
- val flag = new BooleanSetting("value-overrides", "Generated value class method overrides an implementation")
+ // They are not activated by -Xlint and can't be enabled on the command line because they are not
+ // created using the standard factory methods.
+
+ val warnValueOverrides = {
+ val flag = new BooleanSetting("value-overrides", "Generated value class method overrides an implementation.")
flag.value = false
flag
}
@@ -53,10 +54,11 @@ trait Warnings {
val TypeParameterShadow = LintWarning("type-parameter-shadow", "A local type parameter shadows a type already in scope.")
val PolyImplicitOverload = LintWarning("poly-implicit-overload", "Parameterized overloaded implicit methods are not visible as view bounds.")
val OptionImplicit = LintWarning("option-implicit", "Option.apply used implicit view.")
- val DelayedInitSelect = LintWarning("delayedinit-select", "Selecting member of DelayedInit")
+ val DelayedInitSelect = LintWarning("delayedinit-select", "Selecting member of DelayedInit.")
val ByNameRightAssociative = LintWarning("by-name-right-associative", "By-name parameter of right associative operator.")
val PackageObjectClasses = LintWarning("package-object-classes", "Class or object defined in package object.")
val UnsoundMatch = LintWarning("unsound-match", "Pattern match may not be typesafe.")
+ val StarsAlign = LintWarning("stars-align", "Pattern sequence wildcard must align with sequence component.")
def allLintWarnings = values.toSeq.asInstanceOf[Seq[LintWarning]]
}
@@ -77,6 +79,7 @@ trait Warnings {
def warnByNameRightAssociative = lint contains ByNameRightAssociative
def warnPackageObjectClasses = lint contains PackageObjectClasses
def warnUnsoundMatch = lint contains UnsoundMatch
+ def warnStarsAlign = lint contains StarsAlign
// Lint warnings that are currently -Y, but deprecated in that usage
@deprecated("Use warnAdaptedArgs", since="2.11.2")
diff --git a/src/compiler/scala/tools/nsc/symtab/SymbolLoaders.scala b/src/compiler/scala/tools/nsc/symtab/SymbolLoaders.scala
index 9af3efbece..8fd2ea45e4 100644
--- a/src/compiler/scala/tools/nsc/symtab/SymbolLoaders.scala
+++ b/src/compiler/scala/tools/nsc/symtab/SymbolLoaders.scala
@@ -170,7 +170,7 @@ abstract class SymbolLoaders {
}
/** Create a new loader from a binary classfile.
- * This is intented as a hook allowing to support loading symbols from
+ * This is intended as a hook allowing to support loading symbols from
* files other than .class files.
*/
protected def newClassLoader(bin: AbstractFile): SymbolLoader =
diff --git a/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala b/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala
index 1abbdb50b0..4d08be3c24 100644
--- a/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala
+++ b/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala
@@ -587,7 +587,7 @@ abstract class ClassfileParser {
info = MethodType(newParams, clazz.tpe)
}
- // Note: the info may be overrwritten later with a generic signature
+ // Note: the info may be overwritten later with a generic signature
// parsed from SignatureATTR
sym setInfo info
propagatePackageBoundary(jflags, sym)
@@ -768,7 +768,7 @@ abstract class ClassfileParser {
classTParams = tparams
val parents = new ListBuffer[Type]()
while (index < end) {
- parents += sig2type(tparams, skiptvs = false) // here the variance doesnt'matter
+ parents += sig2type(tparams, skiptvs = false) // here the variance doesn't matter
}
ClassInfoType(parents.toList, instanceScope, sym)
}
diff --git a/src/compiler/scala/tools/nsc/transform/Constructors.scala b/src/compiler/scala/tools/nsc/transform/Constructors.scala
index f471440293..362cbde04f 100644
--- a/src/compiler/scala/tools/nsc/transform/Constructors.scala
+++ b/src/compiler/scala/tools/nsc/transform/Constructors.scala
@@ -535,7 +535,7 @@ abstract class Constructors extends Statics with Transform with ast.TreeDSL {
* whether `sym` denotes a param-accessor (ie a field) that fulfills all of:
* (a) has stationary value, ie the same value provided via the corresponding ctor-arg; and
* (b) isn't subject to specialization. We might be processing statements for:
- * (b.1) the constructur in the generic (super-)class; or
+ * (b.1) the constructor in the generic (super-)class; or
* (b.2) the constructor in the specialized (sub-)class.
* (c) isn't part of a DelayedInit subclass.
*/
diff --git a/src/compiler/scala/tools/nsc/transform/Delambdafy.scala b/src/compiler/scala/tools/nsc/transform/Delambdafy.scala
index f7b1021ea2..1f832ba81e 100644
--- a/src/compiler/scala/tools/nsc/transform/Delambdafy.scala
+++ b/src/compiler/scala/tools/nsc/transform/Delambdafy.scala
@@ -9,7 +9,7 @@ import scala.reflect.internal.Symbols
import scala.collection.mutable.LinkedHashMap
/**
- * This transformer is responisble for turning lambdas into anonymous classes.
+ * This transformer is responsible for turning lambdas into anonymous classes.
* The main assumption it makes is that a lambda {args => body} has been turned into
* {args => liftedBody()} where lifted body is a top level method that implements the body of the lambda.
* Currently Uncurry is responsible for that transformation.
@@ -17,7 +17,7 @@ import scala.collection.mutable.LinkedHashMap
* From a lambda, Delambdafy will create
* 1) a static forwarder at the top level of the class that contained the lambda
* 2) a new top level class that
- a) has fields and a constructor taking the captured environment (including possbily the "this"
+ a) has fields and a constructor taking the captured environment (including possibly the "this"
* reference)
* b) an apply method that calls the static forwarder
* c) if needed a bridge method for the apply method
@@ -99,7 +99,7 @@ abstract class Delambdafy extends Transform with TypingTransformers with ast.Tre
super.transform(newExpr)
// when we encounter a template (basically the thing that holds body of a class/trait)
- // we need to updated it to include newly created accesor methods after transforming it
+ // we need to updated it to include newly created accessor methods after transforming it
case Template(_, _, _) =>
try {
// during this call accessorMethods will be populated from the Function case
@@ -113,7 +113,9 @@ abstract class Delambdafy extends Transform with TypingTransformers with ast.Tre
// after working on the entire compilation until we'll have a set of
// new class definitions to add to the top level
override def transformStats(stats: List[Tree], exprOwner: Symbol): List[Tree] = {
- super.transformStats(stats, exprOwner) ++ lambdaClassDefs(exprOwner)
+ // Need to remove from the lambdaClassDefs map: there may be multiple PackageDef for the same
+ // package when defining a package object. We only add the lambda class to one. See SI-9097.
+ super.transformStats(stats, exprOwner) ++ lambdaClassDefs.remove(exprOwner).getOrElse(Nil)
}
private def optionSymbol(sym: Symbol): Option[Symbol] = if (sym.exists) Some(sym) else None
@@ -249,7 +251,7 @@ abstract class Delambdafy extends Transform with TypingTransformers with ast.Tre
else "$" + funOwner.name + "$"
)
val oldClassPart = oldClass.name.decode
- // make sure the class name doesn't contain $anon, otherwsie isAnonymousClass/Function may be true
+ // make sure the class name doesn't contain $anon, otherwise isAnonymousClass/Function may be true
val name = unit.freshTypeName(s"$oldClassPart$suffix".replace("$anon", "$nestedInAnon"))
val lambdaClass = pkg newClassSymbol(name, originalFunction.pos, FINAL | SYNTHETIC) addAnnotation SerialVersionUIDAnnotation
@@ -434,7 +436,7 @@ abstract class Delambdafy extends Transform with TypingTransformers with ast.Tre
}
/**
- * Get the symbol of the target lifted lambad body method from a function. I.e. if
+ * Get the symbol of the target lifted lambda body method from a function. I.e. if
* the function is {args => anonfun(args)} then this method returns anonfun's symbol
*/
private def targetMethod(fun: Function): Symbol = fun match {
diff --git a/src/compiler/scala/tools/nsc/transform/Erasure.scala b/src/compiler/scala/tools/nsc/transform/Erasure.scala
index b6af19250e..5c72bb3258 100644
--- a/src/compiler/scala/tools/nsc/transform/Erasure.scala
+++ b/src/compiler/scala/tools/nsc/transform/Erasure.scala
@@ -185,22 +185,22 @@ abstract class Erasure extends AddInterfaces
private def isErasedValueType(tpe: Type) = tpe.isInstanceOf[ErasedValueType]
- /* Drop redundant interfaces (ones which are implemented by some other parent) from the immediate parents.
+ /* Drop redundant types (ones which are implemented by some other parent) from the immediate parents.
* This is important on Android because there is otherwise an interface explosion.
*/
- def minimizeInterfaces(lstIfaces: List[Type]): List[Type] = {
- var rest = lstIfaces
- var leaves = List.empty[Type]
- while(!rest.isEmpty) {
+ def minimizeParents(parents: List[Type]): List[Type] = {
+ var rest = parents
+ var leaves = collection.mutable.ListBuffer.empty[Type]
+ while(rest.nonEmpty) {
val candidate = rest.head
val nonLeaf = leaves exists { t => t.typeSymbol isSubClass candidate.typeSymbol }
if(!nonLeaf) {
- leaves = candidate :: (leaves filterNot { t => candidate.typeSymbol isSubClass t.typeSymbol })
+ leaves = leaves filterNot { t => candidate.typeSymbol isSubClass t.typeSymbol }
+ leaves += candidate
}
rest = rest.tail
}
-
- leaves.reverse
+ leaves.toList
}
@@ -220,7 +220,7 @@ abstract class Erasure extends AddInterfaces
case _ => tps
}
- val minParents = minimizeInterfaces(parents)
+ val minParents = minimizeParents(parents)
val validParents =
if (isTraitSignature)
// java is unthrilled about seeing interfaces inherit from classes
@@ -430,7 +430,7 @@ abstract class Erasure extends AddInterfaces
* a name clash. The present method guards against these name clashes.
*
* @param member The original member
- * @param other The overidden symbol for which the bridge was generated
+ * @param other The overridden symbol for which the bridge was generated
* @param bridge The bridge
*/
def checkBridgeOverrides(member: Symbol, other: Symbol, bridge: Symbol): Seq[(Position, String)] = {
@@ -1153,7 +1153,7 @@ abstract class Erasure extends AddInterfaces
}
}
- /** The main transform function: Pretransfom the tree, and then
+ /** The main transform function: Pretransform the tree, and then
* re-type it at phase erasure.next.
*/
override def transform(tree: Tree): Tree = {
diff --git a/src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala b/src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala
index c291961447..6225b486c2 100644
--- a/src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala
+++ b/src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala
@@ -441,7 +441,7 @@ abstract class ExplicitOuter extends InfoTransform
else atPos(tree.pos)(outerPath(outerValue, currentClass.outerClass, sym)) // (5)
case Select(qual, name) =>
- // make not private symbol acessed from inner classes, as well as
+ // make not private symbol accessed from inner classes, as well as
// symbols accessed from @inline methods
//
// See SI-6552 for an example of why `sym.owner.enclMethod hasAnnotation ScalaInlineClass`
diff --git a/src/compiler/scala/tools/nsc/transform/Flatten.scala b/src/compiler/scala/tools/nsc/transform/Flatten.scala
index 4662ef6224..fbb0307773 100644
--- a/src/compiler/scala/tools/nsc/transform/Flatten.scala
+++ b/src/compiler/scala/tools/nsc/transform/Flatten.scala
@@ -77,7 +77,7 @@ abstract class Flatten extends InfoTransform {
if (sym.isTerm && !sym.isStaticModule) {
decls1 enter sym
if (sym.isModule) {
- // In theory, we could assert(sym.isMethod), because nested, non-static moduls are
+ // In theory, we could assert(sym.isMethod), because nested, non-static modules are
// transformed to methods (lateMETHOD flag added in RefChecks). But this requires
// forcing sym.info (see comment on isModuleNotMethod), which forces stub symbols
// too eagerly (SI-8907).
@@ -166,7 +166,7 @@ abstract class Flatten extends InfoTransform {
override def transformStats(stats: List[Tree], exprOwner: Symbol): List[Tree] = {
val stats1 = super.transformStats(stats, exprOwner)
if (currentOwner.isPackageClass) {
- val lifted = liftedDefs(currentOwner).toList
+ val lifted = liftedDefs.remove(currentOwner).toList.flatten
stats1 ::: lifted
}
else stats1
diff --git a/src/compiler/scala/tools/nsc/transform/LambdaLift.scala b/src/compiler/scala/tools/nsc/transform/LambdaLift.scala
index d69c9d9a65..a703542587 100644
--- a/src/compiler/scala/tools/nsc/transform/LambdaLift.scala
+++ b/src/compiler/scala/tools/nsc/transform/LambdaLift.scala
@@ -402,7 +402,7 @@ abstract class LambdaLift extends InfoTransform {
}
/* SI-6231: Something like this will be necessary to eliminate the implementation
- * restiction from paramGetter above:
+ * restriction from paramGetter above:
* We need to pass getters to the interface of an implementation class.
private def fixTraitGetters(lifted: List[Tree]): List[Tree] =
for (stat <- lifted) yield stat match {
@@ -539,12 +539,11 @@ abstract class LambdaLift extends InfoTransform {
override def transformStats(stats: List[Tree], exprOwner: Symbol): List[Tree] = {
def addLifted(stat: Tree): Tree = stat match {
case ClassDef(_, _, _, _) =>
- val lifted = liftedDefs get stat.symbol match {
+ val lifted = liftedDefs remove stat.symbol match {
case Some(xs) => xs reverseMap addLifted
case _ => log("unexpectedly no lifted defs for " + stat.symbol) ; Nil
}
- try deriveClassDef(stat)(impl => deriveTemplate(impl)(_ ::: lifted))
- finally liftedDefs -= stat.symbol
+ deriveClassDef(stat)(impl => deriveTemplate(impl)(_ ::: lifted))
case DefDef(_, _, _, _, _, Block(Nil, expr)) if !stat.symbol.isConstructor =>
deriveDefDef(stat)(_ => expr)
diff --git a/src/compiler/scala/tools/nsc/transform/OverridingPairs.scala b/src/compiler/scala/tools/nsc/transform/OverridingPairs.scala
index c1c025ad48..e4082eb376 100644
--- a/src/compiler/scala/tools/nsc/transform/OverridingPairs.scala
+++ b/src/compiler/scala/tools/nsc/transform/OverridingPairs.scala
@@ -35,7 +35,7 @@ abstract class OverridingPairs extends SymbolPairs {
*/
override protected def matches(lo: Symbol, high: Symbol) = lo.isType || (
(lo.owner != high.owner) // don't try to form pairs from overloaded members
- && !high.isPrivate // private or private[this] members never are overriden
+ && !high.isPrivate // private or private[this] members never are overridden
&& !exclude(lo) // this admits private, as one can't have a private member that matches a less-private member.
&& relatively.matches(lo, high)
) // TODO we don't call exclude(high), should we?
diff --git a/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala b/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala
index 9c81e31ad9..1691b01e3e 100644
--- a/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala
+++ b/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala
@@ -894,7 +894,6 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
}
val specMember = subst(outerEnv)(specializedOverload(owner, sym, spec))
- owner.info.decls.enter(specMember)
typeEnv(specMember) = typeEnv(sym) ++ outerEnv ++ spec
wasSpecializedForTypeVars(specMember) ++= spec collect { case (s, tp) if s.tpe == tp => s }
@@ -1291,7 +1290,7 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
* // even in the specialized variant, the local X class
* // doesn't extend Parent$mcI$sp, since its symbol has
* // been created after specialization and was not seen
- * // by specialzation's info transformer.
+ * // by specialization's info transformer.
* ...
* }
* }
diff --git a/src/compiler/scala/tools/nsc/transform/patmat/Logic.scala b/src/compiler/scala/tools/nsc/transform/patmat/Logic.scala
index e6ddf8b758..0b53dc37de 100644
--- a/src/compiler/scala/tools/nsc/transform/patmat/Logic.scala
+++ b/src/compiler/scala/tools/nsc/transform/patmat/Logic.scala
@@ -16,8 +16,8 @@ trait Logic extends Debugging {
import PatternMatchingStats._
private def max(xs: Seq[Int]) = if (xs isEmpty) 0 else xs max
- private def alignedColumns(cols: Seq[AnyRef]): Seq[String] = {
- def toString(x: AnyRef) = if (x eq null) "" else x.toString
+ private def alignedColumns(cols: Seq[Any]): Seq[String] = {
+ def toString(x: Any) = if (x == null) "" else x.toString
if (cols.isEmpty || cols.tails.isEmpty) cols map toString
else {
val colLens = cols map (c => toString(c).length)
@@ -32,7 +32,7 @@ trait Logic extends Debugging {
}
}
- def alignAcrossRows(xss: List[List[AnyRef]], sep: String, lineSep: String = "\n"): String = {
+ def alignAcrossRows(xss: List[List[Any]], sep: String, lineSep: String = "\n"): String = {
val maxLen = max(xss map (_.length))
val padded = xss map (xs => xs ++ List.fill(maxLen - xs.length)(null))
padded.transpose.map(alignedColumns).transpose map (_.mkString(sep)) mkString(lineSep)
@@ -46,7 +46,7 @@ trait Logic extends Debugging {
type Tree
class Prop
- case class Eq(p: Var, q: Const) extends Prop
+ final case class Eq(p: Var, q: Const) extends Prop
type Const
@@ -105,43 +105,157 @@ trait Logic extends Debugging {
// would be nice to statically check whether a prop is equational or pure,
// but that requires typing relations like And(x: Tx, y: Ty) : (if(Tx == PureProp && Ty == PureProp) PureProp else Prop)
- case class And(a: Prop, b: Prop) extends Prop
- case class Or(a: Prop, b: Prop) extends Prop
- case class Not(a: Prop) extends Prop
+ final case class And(ops: Set[Prop]) extends Prop
+ object And {
+ def apply(ops: Prop*) = new And(ops.toSet)
+ }
+
+ final case class Or(ops: Set[Prop]) extends Prop
+ object Or {
+ def apply(ops: Prop*) = new Or(ops.toSet)
+ }
+
+ final case class Not(a: Prop) extends Prop
case object True extends Prop
case object False extends Prop
// symbols are propositions
- abstract case class Sym(variable: Var, const: Const) extends Prop {
+ final class Sym private[PropositionalLogic] (val variable: Var, val const: Const) extends Prop {
+
+ override def equals(other: scala.Any): Boolean = other match {
+ case that: Sym => this.variable == that.variable &&
+ this.const == that.const
+ case _ => false
+ }
+
+ override def hashCode(): Int = {
+ variable.hashCode * 41 + const.hashCode
+ }
+
private val id: Int = Sym.nextSymId
- override def toString = variable +"="+ const +"#"+ id
+ override def toString = s"$variable=$const#$id"
}
- class UniqueSym(variable: Var, const: Const) extends Sym(variable, const)
+
object Sym {
private val uniques: HashSet[Sym] = new HashSet("uniques", 512)
def apply(variable: Var, const: Const): Sym = {
- val newSym = new UniqueSym(variable, const)
+ val newSym = new Sym(variable, const)
(uniques findEntryOrUpdate newSym)
}
- private def nextSymId = {_symId += 1; _symId}; private var _symId = 0
+ def nextSymId = {_symId += 1; _symId}; private var _symId = 0
implicit val SymOrdering: Ordering[Sym] = Ordering.by(_.id)
}
- def /\(props: Iterable[Prop]) = if (props.isEmpty) True else props.reduceLeft(And(_, _))
- def \/(props: Iterable[Prop]) = if (props.isEmpty) False else props.reduceLeft(Or(_, _))
+ def /\(props: Iterable[Prop]) = if (props.isEmpty) True else And(props.toSeq: _*)
+ def \/(props: Iterable[Prop]) = if (props.isEmpty) False else Or(props.toSeq: _*)
+
+ /**
+ * Simplifies propositional formula according to the following rules:
+ * - eliminate double negation (avoids unnecessary Tseitin variables)
+ * - flatten trees of same connectives (avoids unnecessary Tseitin variables)
+ * - removes constants and connectives that are in fact constant because of their operands
+ * - eliminates duplicate operands
+ * - convert formula into NNF: all sub-expressions have a positive polarity
+ * which makes them amenable for the subsequent Plaisted transformation
+ * and increases chances to figure out that the formula is already in CNF
+ *
+ * Complexity: DFS over formula tree
+ *
+ * See http://www.decision-procedures.org/slides/propositional_logic-2x3.pdf
+ */
+ def simplify(f: Prop): Prop = {
+
+ // limit size to avoid blow up
+ def hasImpureAtom(ops: Seq[Prop]): Boolean = ops.size < 10 &&
+ ops.combinations(2).exists {
+ case Seq(a, Not(b)) if a == b => true
+ case Seq(Not(a), b) if a == b => true
+ case _ => false
+ }
+
+ // push negation inside formula
+ def negationNormalFormNot(p: Prop): Prop = p match {
+ case And(ops) => Or(ops.map(negationNormalFormNot)) // De'Morgan
+ case Or(ops) => And(ops.map(negationNormalFormNot)) // De'Morgan
+ case Not(p) => negationNormalForm(p)
+ case True => False
+ case False => True
+ case s: Sym => Not(s)
+ }
+
+ def negationNormalForm(p: Prop): Prop = p match {
+ case And(ops) => And(ops.map(negationNormalForm))
+ case Or(ops) => Or(ops.map(negationNormalForm))
+ case Not(negated) => negationNormalFormNot(negated)
+ case True
+ | False
+ | (_: Sym) => p
+ }
+
+ def simplifyProp(p: Prop): Prop = p match {
+ case And(fv) =>
+ // recurse for nested And (pulls all Ands up)
+ val ops = fv.map(simplifyProp) - True // ignore `True`
+
+ // build up Set in order to remove duplicates
+ val opsFlattened = ops.flatMap {
+ case And(fv) => fv
+ case f => Set(f)
+ }.toSeq
+
+ if (hasImpureAtom(opsFlattened) || opsFlattened.contains(False)) {
+ False
+ } else {
+ opsFlattened match {
+ case Seq() => True
+ case Seq(f) => f
+ case ops => And(ops: _*)
+ }
+ }
+ case Or(fv) =>
+ // recurse for nested Or (pulls all Ors up)
+ val ops = fv.map(simplifyProp) - False // ignore `False`
+
+ val opsFlattened = ops.flatMap {
+ case Or(fv) => fv
+ case f => Set(f)
+ }.toSeq
+
+ if (hasImpureAtom(opsFlattened) || opsFlattened.contains(True)) {
+ True
+ } else {
+ opsFlattened match {
+ case Seq() => False
+ case Seq(f) => f
+ case ops => Or(ops: _*)
+ }
+ }
+ case Not(Not(a)) =>
+ simplify(a)
+ case Not(p) =>
+ Not(simplify(p))
+ case p =>
+ p
+ }
+
+ val nnf = negationNormalForm(f)
+ simplifyProp(nnf)
+ }
trait PropTraverser {
def apply(x: Prop): Unit = x match {
- case And(a, b) => apply(a); apply(b)
- case Or(a, b) => apply(a); apply(b)
+ case And(ops) => ops foreach apply
+ case Or(ops) => ops foreach apply
case Not(a) => apply(a)
case Eq(a, b) => applyVar(a); applyConst(b)
+ case s: Sym => applySymbol(s)
case _ =>
}
def applyVar(x: Var): Unit = {}
def applyConst(x: Const): Unit = {}
+ def applySymbol(x: Sym): Unit = {}
}
def gatherVariables(p: Prop): Set[Var] = {
@@ -152,36 +266,27 @@ trait Logic extends Debugging {
vars.toSet
}
+ def gatherSymbols(p: Prop): Set[Sym] = {
+ val syms = new mutable.HashSet[Sym]()
+ (new PropTraverser {
+ override def applySymbol(s: Sym) = syms += s
+ })(p)
+ syms.toSet
+ }
+
trait PropMap {
def apply(x: Prop): Prop = x match { // TODO: mapConserve
- case And(a, b) => And(apply(a), apply(b))
- case Or(a, b) => Or(apply(a), apply(b))
+ case And(ops) => And(ops map apply)
+ case Or(ops) => Or(ops map apply)
case Not(a) => Not(apply(a))
case p => p
}
}
- // to govern how much time we spend analyzing matches for unreachability/exhaustivity
- object AnalysisBudget {
- private val budgetProp = scala.sys.Prop[String]("scalac.patmat.analysisBudget")
- private val budgetOff = "off"
- val max: Int = {
- val DefaultBudget = 256
- budgetProp.option match {
- case Some(`budgetOff`) =>
- Integer.MAX_VALUE
- case Some(x) =>
- x.toInt
- case None =>
- DefaultBudget
- }
- }
-
- abstract class Exception(val advice: String) extends RuntimeException("CNF budget exceeded")
-
- object exceeded extends Exception(
- s"(The analysis required more space than allowed. Please try with scalac -D${budgetProp.key}=${AnalysisBudget.max*2} or -D${budgetProp.key}=${budgetOff}.)")
-
+ // TODO: remove since deprecated
+ val budgetProp = scala.sys.Prop[String]("scalac.patmat.analysisBudget")
+ if (budgetProp.isSet) {
+ reportWarning(s"Please remove -D${budgetProp.key}, it is ignored.")
}
// convert finite domain propositional logic with subtyping to pure boolean propositional logic
@@ -202,7 +307,7 @@ trait Logic extends Debugging {
// TODO: for V1 representing x1 and V2 standing for x1.head, encode that
// V1 = Nil implies -(V2 = Ci) for all Ci in V2's domain (i.e., it is unassignable)
// may throw an AnalysisBudget.Exception
- def removeVarEq(props: List[Prop], modelNull: Boolean = false): (Formula, List[Formula]) = {
+ def removeVarEq(props: List[Prop], modelNull: Boolean = false): (Prop, List[Prop]) = {
val start = if (Statistics.canEnable) Statistics.startTimer(patmatAnaVarEq) else null
val vars = new mutable.HashSet[Var]
@@ -226,10 +331,10 @@ trait Logic extends Debugging {
props foreach gatherEqualities.apply
if (modelNull) vars foreach (_.registerNull())
- val pure = props map (p => eqFreePropToSolvable(rewriteEqualsToProp(p)))
+ val pure = props map (p => rewriteEqualsToProp(p))
- val eqAxioms = formulaBuilder
- @inline def addAxiom(p: Prop) = addFormula(eqAxioms, eqFreePropToSolvable(p))
+ val eqAxioms = mutable.ArrayBuffer[Prop]()
+ @inline def addAxiom(p: Prop) = eqAxioms += p
debug.patmat("removeVarEq vars: "+ vars)
vars.foreach { v =>
@@ -255,49 +360,32 @@ trait Logic extends Debugging {
}
}
- debug.patmat("eqAxioms:\n"+ cnfString(toFormula(eqAxioms)))
- debug.patmat("pure:"+ pure.map(p => cnfString(p)).mkString("\n"))
+ debug.patmat(s"eqAxioms:\n${eqAxioms.mkString("\n")}")
+ debug.patmat(s"pure:${pure.mkString("\n")}")
if (Statistics.canEnable) Statistics.stopTimer(patmatAnaVarEq, start)
- (toFormula(eqAxioms), pure)
+ (And(eqAxioms: _*), pure)
}
+ type Solvable
- // an interface that should be suitable for feeding a SAT solver when the time comes
- type Formula
- type FormulaBuilder
-
- // creates an empty formula builder to which more formulae can be added
- def formulaBuilder: FormulaBuilder
-
- // val f = formulaBuilder; addFormula(f, f1); ... addFormula(f, fN)
- // toFormula(f) == andFormula(f1, andFormula(..., fN))
- def addFormula(buff: FormulaBuilder, f: Formula): Unit
- def toFormula(buff: FormulaBuilder): Formula
-
- // the conjunction of formulae `a` and `b`
- def andFormula(a: Formula, b: Formula): Formula
-
- // equivalent formula to `a`, but simplified in a lightweight way (drop duplicate clauses)
- def simplifyFormula(a: Formula): Formula
-
- // may throw an AnalysisBudget.Exception
- def propToSolvable(p: Prop): Formula = {
- val (eqAxioms, pure :: Nil) = removeVarEq(List(p), modelNull = false)
- andFormula(eqAxioms, pure)
+ def propToSolvable(p: Prop): Solvable = {
+ val (eqAxiom, pure :: Nil) = removeVarEq(List(p), modelNull = false)
+ eqFreePropToSolvable(And(eqAxiom, pure))
}
- // may throw an AnalysisBudget.Exception
- def eqFreePropToSolvable(p: Prop): Formula
- def cnfString(f: Formula): String
+ def eqFreePropToSolvable(f: Prop): Solvable
type Model = Map[Sym, Boolean]
val EmptyModel: Model
val NoModel: Model
- def findModelFor(f: Formula): Model
- def findAllModelsFor(f: Formula): List[Model]
+ final case class Solution(model: Model, unassigned: List[Sym])
+
+ def findModelFor(solvable: Solvable): Model
+
+ def findAllModelsFor(solvable: Solvable): List[Solution]
}
}
@@ -547,7 +635,7 @@ trait ScalaLogic extends Interface with Logic with TreeAndTypeAnalysis {
if (!t.symbol.isStable) {
// Create a fresh type for each unstable value, since we can never correlate it to another value.
- // For example `case X => case X =>` should not complaing about the second case being unreachable,
+ // For example `case X => case X =>` should not complain about the second case being unreachable,
// if X is mutable.
freshExistentialSubtype(t.tpe)
}
diff --git a/src/compiler/scala/tools/nsc/transform/patmat/MatchAnalysis.scala b/src/compiler/scala/tools/nsc/transform/patmat/MatchAnalysis.scala
index 21e90b1d78..34ebbc7463 100644
--- a/src/compiler/scala/tools/nsc/transform/patmat/MatchAnalysis.scala
+++ b/src/compiler/scala/tools/nsc/transform/patmat/MatchAnalysis.scala
@@ -6,6 +6,8 @@
package scala.tools.nsc.transform.patmat
+import scala.annotation.tailrec
+import scala.collection.immutable.{IndexedSeq, Iterable}
import scala.language.postfixOps
import scala.collection.mutable
import scala.reflect.internal.util.Statistics
@@ -266,7 +268,7 @@ trait MatchApproximation extends TreeAndTypeAnalysis with ScalaLogic with MatchT
// the type of the binder passed to the first invocation
// determines the type of the tree that'll be returned for that binder as of then
final def binderToUniqueTree(b: Symbol) =
- unique(accumSubst(normalize(CODE.REF(b))), b.tpe)
+ unique(accumSubst(normalize(gen.mkAttributedStableRef(b))), b.tpe)
// note that the sequencing of operations is important: must visit in same order as match execution
// binderToUniqueTree uses the type of the first symbol that was encountered as the type for all future binders
@@ -363,7 +365,7 @@ trait MatchApproximation extends TreeAndTypeAnalysis with ScalaLogic with MatchT
def handleUnknown(tm: TreeMaker) = handler(tm)
}
- // used for CSE -- rewrite all unknowns to False (the most conserative option)
+ // used for CSE -- rewrite all unknowns to False (the most conservative option)
object conservative extends TreeMakerToProp {
def handleUnknown(tm: TreeMaker) = False
}
@@ -397,7 +399,6 @@ trait MatchAnalysis extends MatchApproximation {
trait MatchAnalyzer extends MatchApproximator {
def uncheckedWarning(pos: Position, msg: String) = currentRun.reporting.uncheckedWarning(pos, msg)
- def warn(pos: Position, ex: AnalysisBudget.Exception, kind: String) = uncheckedWarning(pos, s"Cannot check match for $kind.\n${ex.advice}")
def reportWarning(message: String) = global.reporter.warning(typer.context.tree.pos, message)
// TODO: model dependencies between variables: if V1 corresponds to (x: List[_]) and V2 is (x.hd), V2 cannot be assigned when V1 = null or V1 = Nil
@@ -428,49 +429,44 @@ trait MatchAnalysis extends MatchApproximation {
val propsCasesOk = approximate(True) map caseWithoutBodyToProp
val propsCasesFail = approximate(False) map (t => Not(caseWithoutBodyToProp(t)))
- try {
- val (eqAxiomsFail, symbolicCasesFail) = removeVarEq(propsCasesFail, modelNull = true)
- val (eqAxiomsOk, symbolicCasesOk) = removeVarEq(propsCasesOk, modelNull = true)
- val eqAxioms = simplifyFormula(andFormula(eqAxiomsOk, eqAxiomsFail)) // I'm pretty sure eqAxiomsOk == eqAxiomsFail, but not 100% sure.
-
- val prefix = formulaBuilder
- addFormula(prefix, eqAxioms)
-
- var prefixRest = symbolicCasesFail
- var current = symbolicCasesOk
- var reachable = true
- var caseIndex = 0
-
- debug.patmat("reachability, vars:\n"+ ((propsCasesFail flatMap gatherVariables).distinct map (_.describe) mkString ("\n")))
- debug.patmat("equality axioms:\n"+ cnfString(eqAxiomsOk))
-
- // invariant (prefixRest.length == current.length) && (prefix.reverse ++ prefixRest == symbolicCasesFail)
- // termination: prefixRest.length decreases by 1
- while (prefixRest.nonEmpty && reachable) {
- val prefHead = prefixRest.head
- caseIndex += 1
- prefixRest = prefixRest.tail
- if (prefixRest.isEmpty) reachable = true
- else {
- addFormula(prefix, prefHead)
- current = current.tail
- val model = findModelFor(andFormula(current.head, toFormula(prefix)))
+ val (eqAxiomsFail, symbolicCasesFail) = removeVarEq(propsCasesFail, modelNull = true)
+ val (eqAxiomsOk, symbolicCasesOk) = removeVarEq(propsCasesOk, modelNull = true)
+ val eqAxioms = simplify(And(eqAxiomsOk, eqAxiomsFail)) // I'm pretty sure eqAxiomsOk == eqAxiomsFail, but not 100% sure.
- // debug.patmat("trying to reach:\n"+ cnfString(current.head) +"\nunder prefix:\n"+ cnfString(prefix))
- // if (NoModel ne model) debug.patmat("reached: "+ modelString(model))
+ val prefix = mutable.ArrayBuffer[Prop]()
+ prefix += eqAxioms
- reachable = NoModel ne model
- }
- }
+ var prefixRest = symbolicCasesFail
+ var current = symbolicCasesOk
+ var reachable = true
+ var caseIndex = 0
+
+ debug.patmat("reachability, vars:\n" + ((propsCasesFail flatMap gatherVariables).distinct map (_.describe) mkString ("\n")))
+ debug.patmat(s"equality axioms:\n$eqAxiomsOk")
+
+ // invariant (prefixRest.length == current.length) && (prefix.reverse ++ prefixRest == symbolicCasesFail)
+ // termination: prefixRest.length decreases by 1
+ while (prefixRest.nonEmpty && reachable) {
+ val prefHead = prefixRest.head
+ caseIndex += 1
+ prefixRest = prefixRest.tail
+ if (prefixRest.isEmpty) reachable = true
+ else {
+ prefix += prefHead
+ current = current.tail
+ val and = And((current.head +: prefix): _*)
+ val model = findModelFor(eqFreePropToSolvable(and))
- if (Statistics.canEnable) Statistics.stopTimer(patmatAnaReach, start)
+ // debug.patmat("trying to reach:\n"+ cnfString(current.head) +"\nunder prefix:\n"+ cnfString(prefix))
+ // if (NoModel ne model) debug.patmat("reached: "+ modelString(model))
- if (reachable) None else Some(caseIndex)
- } catch {
- case ex: AnalysisBudget.Exception =>
- warn(prevBinder.pos, ex, "unreachability")
- None // CNF budget exceeded
+ reachable = NoModel ne model
+ }
}
+
+ if (Statistics.canEnable) Statistics.stopTimer(patmatAnaReach, start)
+
+ if (reachable) None else Some(caseIndex)
}
// exhaustivity
@@ -518,24 +514,25 @@ trait MatchAnalysis extends MatchApproximation {
// debug.patmat("\nvars:\n"+ (vars map (_.describe) mkString ("\n")))
// debug.patmat("\nmatchFails as CNF:\n"+ cnfString(propToSolvable(matchFails)))
- try {
- // find the models (under which the match fails)
- val matchFailModels = findAllModelsFor(propToSolvable(matchFails))
-
- val scrutVar = Var(prevBinderTree)
- val counterExamples = matchFailModels.flatMap(modelToCounterExample(scrutVar))
- // sorting before pruning is important here in order to
- // keep neg/t7020.scala stable
- // since e.g. List(_, _) would cover List(1, _)
- val pruned = CounterExample.prune(counterExamples.sortBy(_.toString)).map(_.toString)
-
- if (Statistics.canEnable) Statistics.stopTimer(patmatAnaExhaust, start)
- pruned
- } catch {
- case ex : AnalysisBudget.Exception =>
- warn(prevBinder.pos, ex, "exhaustivity")
- Nil // CNF budget exceeded
+ // find the models (under which the match fails)
+ val matchFailModels = findAllModelsFor(propToSolvable(matchFails))
+
+ val scrutVar = Var(prevBinderTree)
+ val counterExamples = {
+ matchFailModels.flatMap {
+ model =>
+ val varAssignments = expandModel(model)
+ varAssignments.flatMap(modelToCounterExample(scrutVar) _)
+ }
}
+
+ // sorting before pruning is important here in order to
+ // keep neg/t7020.scala stable
+ // since e.g. List(_, _) would cover List(1, _)
+ val pruned = CounterExample.prune(counterExamples.sortBy(_.toString)).map(_.toString)
+
+ if (Statistics.canEnable) Statistics.stopTimer(patmatAnaExhaust, start)
+ pruned
}
}
@@ -600,6 +597,8 @@ trait MatchAnalysis extends MatchApproximation {
case object WildcardExample extends CounterExample { override def toString = "_" }
case object NoExample extends CounterExample { override def toString = "??" }
+ // returns a mapping from variable to
+ // equal and notEqual symbols
def modelToVarAssignment(model: Model): Map[Var, (Seq[Const], Seq[Const])] =
model.toSeq.groupBy{f => f match {case (sym, value) => sym.variable} }.mapValues{ xs =>
val (trues, falses) = xs.partition(_._2)
@@ -613,20 +612,110 @@ trait MatchAnalysis extends MatchApproximation {
v +"(="+ v.path +": "+ v.staticTpCheckable +") "+ assignment
}.mkString("\n")
- // return constructor call when the model is a true counter example
- // (the variables don't take into account type information derived from other variables,
- // so, naively, you might try to construct a counter example like _ :: Nil(_ :: _, _ :: _),
- // since we didn't realize the tail of the outer cons was a Nil)
- def modelToCounterExample(scrutVar: Var)(model: Model): Option[CounterExample] = {
+ /**
+ * The models we get from the DPLL solver need to be mapped back to counter examples.
+ * However there's no precalculated mapping model -> counter example. Even worse,
+ * not every valid model corresponds to a valid counter example.
+ * The reason is that restricting the valid models further would for example require
+ * a quadratic number of additional clauses. So to keep the optimistic case fast
+ * (i.e., all cases are covered in a pattern match), the infeasible counter examples
+ * are filtered later.
+ *
+ * The DPLL procedure keeps the literals that do not contribute to the solution
+ * unassigned, e.g., for `(a \/ b)`
+ * only {a = true} or {b = true} is required and the other variable can have any value.
+ *
+ * This function does a smart expansion of the model and avoids models that
+ * have conflicting mappings.
+ *
+ * For example for in case of the given set of symbols (taken from `t7020.scala`):
+ * "V2=2#16"
+ * "V2=6#19"
+ * "V2=5#18"
+ * "V2=4#17"
+ * "V2=7#20"
+ *
+ * One possibility would be to group the symbols by domain but
+ * this would only work for equality tests and would not be compatible
+ * with type tests.
+ * Another observation leads to a much simpler algorithm:
+ * Only one of these symbols can be set to true,
+ * since `V2` can at most be equal to one of {2,6,5,4,7}.
+ */
+ def expandModel(solution: Solution): List[Map[Var, (Seq[Const], Seq[Const])]] = {
+
+ val model = solution.model
+
// x1 = ...
// x1.hd = ...
// x1.tl = ...
// x1.hd.hd = ...
// ...
val varAssignment = modelToVarAssignment(model)
+ debug.patmat("var assignment for model " + model + ":\n" + varAssignmentString(varAssignment))
+
+ // group symbols that assign values to the same variables (i.e., symbols are mutually exclusive)
+ // (thus the groups are sets of disjoint assignments to variables)
+ val groupedByVar: Map[Var, List[Sym]] = solution.unassigned.groupBy(_.variable)
+
+ val expanded = for {
+ (variable, syms) <- groupedByVar.toList
+ } yield {
- debug.patmat("var assignment for model "+ model +":\n"+ varAssignmentString(varAssignment))
+ val (equal, notEqual) = varAssignment.getOrElse(variable, Nil -> Nil)
+ def addVarAssignment(equalTo: List[Const], notEqualTo: List[Const]) = {
+ Map(variable ->(equal ++ equalTo, notEqual ++ notEqualTo))
+ }
+
+ // this assignment is needed in case that
+ // there exists already an assign
+ val allNotEqual = addVarAssignment(Nil, syms.map(_.const))
+
+ // this assignment is conflicting on purpose:
+ // a list counter example could contain wildcards: e.g. `List(_,_)`
+ val allEqual = addVarAssignment(syms.map(_.const), Nil)
+
+ if(equal.isEmpty) {
+ val oneHot = for {
+ s <- syms
+ } yield {
+ addVarAssignment(List(s.const), syms.filterNot(_ == s).map(_.const))
+ }
+ allEqual :: allNotEqual :: oneHot
+ } else {
+ allEqual :: allNotEqual :: Nil
+ }
+ }
+
+ if (expanded.isEmpty) {
+ List(varAssignment)
+ } else {
+ // we need the cartesian product here,
+ // since we want to report all missing cases
+ // (i.e., combinations)
+ val cartesianProd = expanded.reduceLeft((xs, ys) =>
+ for {map1 <- xs
+ map2 <- ys} yield {
+ map1 ++ map2
+ })
+
+ // add expanded variables
+ // note that we can just use `++`
+ // since the Maps have disjoint keySets
+ for {
+ m <- cartesianProd
+ } yield {
+ varAssignment ++ m
+ }
+ }
+ }
+
+ // return constructor call when the model is a true counter example
+ // (the variables don't take into account type information derived from other variables,
+ // so, naively, you might try to construct a counter example like _ :: Nil(_ :: _, _ :: _),
+ // since we didn't realize the tail of the outer cons was a Nil)
+ def modelToCounterExample(scrutVar: Var)(varAssignment: Map[Var, (Seq[Const], Seq[Const])]): Option[CounterExample] = {
// chop a path into a list of symbols
def chop(path: Tree): List[Symbol] = path match {
case Ident(_) => List(path.symbol)
@@ -755,7 +844,7 @@ trait MatchAnalysis extends MatchApproximation {
// then we can safely ignore these counter examples since we will eventually encounter
// both counter examples separately
case _ if inSameDomain => None
-
+
// not a valid counter-example, possibly since we have a definite type but there was a field mismatch
// TODO: improve reasoning -- in the mean time, a false negative is better than an annoying false positive
case _ => Some(NoExample)
@@ -774,12 +863,12 @@ trait MatchAnalysis extends MatchApproximation {
}
def analyzeCases(prevBinder: Symbol, cases: List[List[TreeMaker]], pt: Type, suppression: Suppression): Unit = {
- if (!suppression.unreachable) {
+ if (!suppression.suppressUnreachable) {
unreachableCase(prevBinder, cases, pt) foreach { caseIndex =>
reportUnreachable(cases(caseIndex).last.pos)
}
}
- if (!suppression.exhaustive) {
+ if (!suppression.suppressExhaustive) {
val counterExamples = exhaustive(prevBinder, cases, pt)
if (counterExamples.nonEmpty)
reportMissingCases(prevBinder.pos, counterExamples)
diff --git a/src/compiler/scala/tools/nsc/transform/patmat/MatchOptimization.scala b/src/compiler/scala/tools/nsc/transform/patmat/MatchOptimization.scala
index e9c81f4728..b3aef8a20e 100644
--- a/src/compiler/scala/tools/nsc/transform/patmat/MatchOptimization.scala
+++ b/src/compiler/scala/tools/nsc/transform/patmat/MatchOptimization.scala
@@ -46,16 +46,16 @@ trait MatchOptimization extends MatchTreeMaking with MatchAnalysis {
val cond = test.prop
def simplify(c: Prop): Set[Prop] = c match {
- case And(a, b) => simplify(a) ++ simplify(b)
- case Or(_, _) => Set(False) // TODO: make more precise
- case Not(Eq(Var(_), NullConst)) => Set(True) // not worth remembering
+ case And(ops) => ops.toSet flatMap simplify
+ case Or(ops) => Set(False) // TODO: make more precise
+ case Not(Eq(Var(_), NullConst)) => Set(True) // not worth remembering
case _ => Set(c)
}
val conds = simplify(cond)
if (conds(False)) false // stop when we encounter a definite "no" or a "not sure"
else {
- val nonTrivial = conds filterNot (_ == True)
+ val nonTrivial = conds - True
if (nonTrivial nonEmpty) {
tested ++= nonTrivial
diff --git a/src/compiler/scala/tools/nsc/transform/patmat/MatchTranslation.scala b/src/compiler/scala/tools/nsc/transform/patmat/MatchTranslation.scala
index 22661d6ccf..6302e34ac9 100644
--- a/src/compiler/scala/tools/nsc/transform/patmat/MatchTranslation.scala
+++ b/src/compiler/scala/tools/nsc/transform/patmat/MatchTranslation.scala
@@ -208,7 +208,7 @@ trait MatchTranslation {
case _ => (cases, None)
}
- checkMatchVariablePatterns(nonSyntheticCases)
+ if (!settings.XnoPatmatAnalysis) checkMatchVariablePatterns(nonSyntheticCases)
// we don't transform after uncurry
// (that would require more sophistication when generating trees,
@@ -248,7 +248,10 @@ trait MatchTranslation {
if (caseDefs forall treeInfo.isCatchCase) caseDefs
else {
val swatches = { // switch-catches
- val bindersAndCases = caseDefs map { caseDef =>
+ // SI-7459 must duplicate here as we haven't commited to switch emission, and just figuring out
+ // if we can ends up mutating `caseDefs` down in the use of `substituteSymbols` in
+ // `TypedSubstitution#Substitution`. That is called indirectly by `emitTypeSwitch`.
+ val bindersAndCases = caseDefs.map(_.duplicate) map { caseDef =>
// generate a fresh symbol for each case, hoping we'll end up emitting a type-switch (we don't have a global scrut there)
// if we fail to emit a fine-grained switch, have to do translateCase again with a single scrutSym (TODO: uniformize substitution on treemakers so we can avoid this)
val caseScrutSym = freshSym(pos, pureType(ThrowableTpe))
@@ -518,7 +521,7 @@ trait MatchTranslation {
// reference the (i-1)th case accessor if it exists, otherwise the (i-1)th tuple component
override protected def tupleSel(binder: Symbol)(i: Int): Tree = {
val accessors = binder.caseFieldAccessors
- if (accessors isDefinedAt (i-1)) REF(binder) DOT accessors(i-1)
+ if (accessors isDefinedAt (i-1)) gen.mkAttributedStableRef(binder) DOT accessors(i-1)
else codegen.tupleSel(binder)(i) // this won't type check for case classes, as they do not inherit ProductN
}
}
@@ -580,7 +583,7 @@ trait MatchTranslation {
// duplicated with the extractor Unapplied
case Apply(x, List(i @ Ident(nme.SELECTOR_DUMMY))) =>
treeCopy.Apply(t, x, binderRef(i.pos) :: Nil)
- // SI-7868 Account for numeric widening, e.g. <unappplySelector>.toInt
+ // SI-7868 Account for numeric widening, e.g. <unapplySelector>.toInt
case Apply(x, List(i @ (sel @ Select(Ident(nme.SELECTOR_DUMMY), name)))) =>
treeCopy.Apply(t, x, treeCopy.Select(sel, binderRef(i.pos), name) :: Nil)
case _ =>
diff --git a/src/compiler/scala/tools/nsc/transform/patmat/MatchTreeMaking.scala b/src/compiler/scala/tools/nsc/transform/patmat/MatchTreeMaking.scala
index 3fd9ce76f8..b703b5bc6d 100644
--- a/src/compiler/scala/tools/nsc/transform/patmat/MatchTreeMaking.scala
+++ b/src/compiler/scala/tools/nsc/transform/patmat/MatchTreeMaking.scala
@@ -21,9 +21,10 @@ trait MatchTreeMaking extends MatchCodeGen with Debugging {
import global._
import definitions._
- final case class Suppression(exhaustive: Boolean, unreachable: Boolean)
+ final case class Suppression(suppressExhaustive: Boolean, suppressUnreachable: Boolean)
object Suppression {
val NoSuppression = Suppression(false, false)
+ val FullSuppression = Suppression(true, true)
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -166,8 +167,17 @@ trait MatchTreeMaking extends MatchCodeGen with Debugging {
val usedBinders = new mutable.HashSet[Symbol]()
// all potentially stored subpat binders
val potentiallyStoredBinders = stored.unzip._1.toSet
+ def ref(sym: Symbol) =
+ if (potentiallyStoredBinders(sym)) usedBinders += sym
// compute intersection of all symbols in the tree `in` and all potentially stored subpat binders
- in.foreach(t => if (potentiallyStoredBinders(t.symbol)) usedBinders += t.symbol)
+ in.foreach {
+ case tt: TypeTree =>
+ tt.tpe foreach { // SI-7459 e.g. case Prod(t) => new t.u.Foo
+ case SingleType(_, sym) => ref(sym)
+ case _ =>
+ }
+ case t => ref(t.symbol)
+ }
if (usedBinders.isEmpty) in
else {
@@ -517,7 +527,7 @@ trait MatchTreeMaking extends MatchCodeGen with Debugging {
def removeSubstOnly(makers: List[TreeMaker]) = makers filterNot (_.isInstanceOf[SubstOnlyTreeMaker])
// a foldLeft to accumulate the localSubstitution left-to-right
- // it drops SubstOnly tree makers, since their only goal in life is to propagate substitutions to the next tree maker, which is fullfilled by propagateSubstitution
+ // it drops SubstOnly tree makers, since their only goal in life is to propagate substitutions to the next tree maker, which is fulfilled by propagateSubstitution
def propagateSubstitution(treeMakers: List[TreeMaker], initial: Substitution): List[TreeMaker] = {
var accumSubst: Substitution = initial
treeMakers foreach { maker =>
@@ -542,7 +552,7 @@ trait MatchTreeMaking extends MatchCodeGen with Debugging {
debug.patmat("combining cases: "+ (casesNoSubstOnly.map(_.mkString(" >> ")).mkString("{", "\n", "}")))
val (suppression, requireSwitch): (Suppression, Boolean) =
- if (settings.XnoPatmatAnalysis) (Suppression.NoSuppression, false)
+ if (settings.XnoPatmatAnalysis) (Suppression.FullSuppression, false)
else scrut match {
case Typed(tree, tpt) =>
val suppressExhaustive = tpt.tpe hasAnnotation UncheckedClass
@@ -574,7 +584,7 @@ trait MatchTreeMaking extends MatchCodeGen with Debugging {
(Suppression.NoSuppression, false)
}
- emitSwitch(scrut, scrutSym, casesNoSubstOnly, pt, matchFailGenOverride, suppression.exhaustive).getOrElse{
+ emitSwitch(scrut, scrutSym, casesNoSubstOnly, pt, matchFailGenOverride, unchecked = suppression.suppressExhaustive).getOrElse{
if (requireSwitch) reporter.warning(scrut.pos, "could not emit switch for @switch annotated match")
if (casesNoSubstOnly nonEmpty) {
diff --git a/src/compiler/scala/tools/nsc/transform/patmat/PatternMatching.scala b/src/compiler/scala/tools/nsc/transform/patmat/PatternMatching.scala
index ef50e083a1..b2f2516b5b 100644
--- a/src/compiler/scala/tools/nsc/transform/patmat/PatternMatching.scala
+++ b/src/compiler/scala/tools/nsc/transform/patmat/PatternMatching.scala
@@ -12,7 +12,7 @@ import scala.language.postfixOps
import scala.tools.nsc.transform.TypingTransformers
import scala.tools.nsc.transform.Transform
import scala.reflect.internal.util.Statistics
-import scala.reflect.internal.Types
+import scala.reflect.internal.{Mode, Types}
import scala.reflect.internal.util.Position
/** Translate pattern matching.
@@ -198,33 +198,62 @@ trait Interface extends ast.TreeDSL {
}
class Substitution(val from: List[Symbol], val to: List[Tree]) {
- import global.{Transformer, Ident, NoType}
+ import global.{Transformer, Ident, NoType, TypeTree, SingleType}
// We must explicitly type the trees that we replace inside some other tree, since the latter may already have been typed,
// and will thus not be retyped. This means we might end up with untyped subtrees inside bigger, typed trees.
def apply(tree: Tree): Tree = {
// according to -Ystatistics 10% of translateMatch's time is spent in this method...
// since about half of the typedSubst's end up being no-ops, the check below shaves off 5% of the time spent in typedSubst
- if (!tree.exists { case i@Ident(_) => from contains i.symbol case _ => false}) tree
- else (new Transformer {
+ val toIdents = to.forall(_.isInstanceOf[Ident])
+ val containsSym = tree.exists {
+ case i@Ident(_) => from contains i.symbol
+ case tt: TypeTree => tt.tpe.exists {
+ case SingleType(_, sym) =>
+ (from contains sym) && {
+ if (!toIdents) global.devWarning(s"Unexpected substitution of non-Ident into TypeTree `$tt`, subst= $this")
+ true
+ }
+ case _ => false
+ }
+ case _ => false
+ }
+ val toSyms = to.map(_.symbol)
+ object substIdentsForTrees extends Transformer {
private def typedIfOrigTyped(to: Tree, origTp: Type): Tree =
if (origTp == null || origTp == NoType) to
// important: only type when actually substing and when original tree was typed
// (don't need to use origTp as the expected type, though, and can't always do this anyway due to unknown type params stemming from polymorphic extractors)
else typer.typed(to)
+ def typedStable(t: Tree) = typer.typed(t.shallowDuplicate, Mode.MonoQualifierModes | Mode.TYPEPATmode)
+ lazy val toTypes: List[Type] = to map (tree => typedStable(tree).tpe)
+
override def transform(tree: Tree): Tree = {
def subst(from: List[Symbol], to: List[Tree]): Tree =
if (from.isEmpty) tree
- else if (tree.symbol == from.head) typedIfOrigTyped(to.head.shallowDuplicate.setPos(tree.pos), tree.tpe)
+ else if (tree.symbol == from.head) typedIfOrigTyped(typedStable(to.head).setPos(tree.pos), tree.tpe)
else subst(from.tail, to.tail)
- tree match {
+ val tree1 = tree match {
case Ident(_) => subst(from, to)
case _ => super.transform(tree)
}
+ tree1 match {
+ case _: DefTree =>
+ tree1.symbol.modifyInfo(_.substituteTypes(from, toTypes))
+ case _ =>
+ }
+ tree1.modifyType(_.substituteTypes(from, toTypes))
}
- }).transform(tree)
+ }
+ if (containsSym) {
+ if (to.forall(_.isInstanceOf[Ident]))
+ tree.duplicate.substituteSymbols(from, to.map(_.symbol)) // SI-7459 catches `case t => new t.Foo`
+ else
+ substIdentsForTrees.transform(tree)
+ }
+ else tree
}
diff --git a/src/compiler/scala/tools/nsc/transform/patmat/ScalacPatternExpanders.scala b/src/compiler/scala/tools/nsc/transform/patmat/ScalacPatternExpanders.scala
index 8924394b72..2753baa51d 100644
--- a/src/compiler/scala/tools/nsc/transform/patmat/ScalacPatternExpanders.scala
+++ b/src/compiler/scala/tools/nsc/transform/patmat/ScalacPatternExpanders.scala
@@ -110,8 +110,10 @@ trait ScalacPatternExpanders {
err("Star pattern must correspond with varargs or unapplySeq")
else if (elementArity < 0)
arityError("not enough")
- else if (elementArity > 0 && !extractor.hasSeq)
+ else if (elementArity > 0 && !isSeq)
arityError("too many")
+ else if (settings.warnStarsAlign && isSeq && productArity > 0 && (elementArity > 0 || !isStar))
+ warn("A repeated case parameter or extracted sequence should be matched only by a sequence wildcard (_*).")
aligned
}
diff --git a/src/compiler/scala/tools/nsc/transform/patmat/Solving.scala b/src/compiler/scala/tools/nsc/transform/patmat/Solving.scala
index 4330781013..27217f0dc2 100644
--- a/src/compiler/scala/tools/nsc/transform/patmat/Solving.scala
+++ b/src/compiler/scala/tools/nsc/transform/patmat/Solving.scala
@@ -6,252 +6,380 @@
package scala.tools.nsc.transform.patmat
-import scala.collection.mutable
+import scala.collection.mutable.ArrayBuffer
import scala.reflect.internal.util.Statistics
import scala.language.postfixOps
+import scala.collection.mutable
import scala.reflect.internal.util.Collections._
-// naive CNF translation and simple DPLL solver
+// a literal is a (possibly negated) variable
+class Lit(val v: Int) extends AnyVal {
+ def unary_- : Lit = Lit(-v)
+
+ def variable: Int = Math.abs(v)
+
+ def positive = v >= 0
+
+ override def toString(): String = s"Lit#$v"
+}
+
+object Lit {
+ def apply(v: Int): Lit = new Lit(v)
+
+ implicit val LitOrdering: Ordering[Lit] = Ordering.by(_.v)
+}
+
+/** Solve pattern matcher exhaustivity problem via DPLL.
+ */
trait Solving extends Logic {
+
import PatternMatchingStats._
- trait CNF extends PropositionalLogic {
- import scala.collection.mutable.ArrayBuffer
- type FormulaBuilder = ArrayBuffer[Clause]
- def formulaBuilder = ArrayBuffer[Clause]()
- def formulaBuilderSized(init: Int) = new ArrayBuffer[Clause](init)
- def addFormula(buff: FormulaBuilder, f: Formula): Unit = buff ++= f
- def toFormula(buff: FormulaBuilder): Formula = buff
- // CNF: a formula is a conjunction of clauses
- type Formula = FormulaBuilder
- def formula(c: Clause*): Formula = ArrayBuffer(c: _*)
+ trait CNF extends PropositionalLogic {
type Clause = Set[Lit]
+
// a clause is a disjunction of distinct literals
def clause(l: Lit*): Clause = l.toSet
- type Lit
- def Lit(sym: Sym, pos: Boolean = true): Lit
-
- def andFormula(a: Formula, b: Formula): Formula = a ++ b
- def simplifyFormula(a: Formula): Formula = a.distinct
-
- private def merge(a: Clause, b: Clause) = a ++ b
-
- // throws an AnalysisBudget.Exception when the prop results in a CNF that's too big
- // TODO: be smarter/more efficient about this (http://lara.epfl.ch/w/sav09:tseitin_s_encoding)
- def eqFreePropToSolvable(p: Prop): Formula = {
- def negationNormalFormNot(p: Prop, budget: Int): Prop =
- if (budget <= 0) throw AnalysisBudget.exceeded
- else p match {
- case And(a, b) => Or(negationNormalFormNot(a, budget - 1), negationNormalFormNot(b, budget - 1))
- case Or(a, b) => And(negationNormalFormNot(a, budget - 1), negationNormalFormNot(b, budget - 1))
- case Not(p) => negationNormalForm(p, budget - 1)
- case True => False
- case False => True
- case s: Sym => Not(s)
+ /** Conjunctive normal form (of a Boolean formula).
+ * A formula in this form is amenable to a SAT solver
+ * (i.e., solver that decides satisfiability of a formula).
+ */
+ type Cnf = Array[Clause]
+
+ class SymbolMapping(symbols: Set[Sym]) {
+ val variableForSymbol: Map[Sym, Int] = {
+ symbols.zipWithIndex.map {
+ case (sym, i) => sym -> (i + 1)
+ }.toMap
+ }
+
+ val symForVar: Map[Int, Sym] = variableForSymbol.map(_.swap)
+
+ val relevantVars: Set[Int] = symForVar.keySet.map(math.abs)
+
+ def lit(sym: Sym): Lit = Lit(variableForSymbol(sym))
+
+ def size = symbols.size
+ }
+
+ case class Solvable(cnf: Cnf, symbolMapping: SymbolMapping)
+
+ trait CnfBuilder {
+ private[this] val buff = ArrayBuffer[Clause]()
+
+ var literalCount: Int
+
+ /**
+ * @return new Tseitin variable
+ */
+ def newLiteral(): Lit = {
+ literalCount += 1
+ Lit(literalCount)
+ }
+
+ lazy val constTrue: Lit = {
+ val constTrue = newLiteral()
+ addClauseProcessed(clause(constTrue))
+ constTrue
+ }
+
+ def constFalse: Lit = -constTrue
+
+ def isConst(l: Lit): Boolean = l == constTrue || l == constFalse
+
+ def addClauseProcessed(clause: Clause) {
+ if (clause.nonEmpty) {
+ buff += clause
}
+ }
+
+ def buildCnf: Array[Clause] = buff.toArray
+
+ }
- def negationNormalForm(p: Prop, budget: Int = AnalysisBudget.max): Prop =
- if (budget <= 0) throw AnalysisBudget.exceeded
- else p match {
- case And(a, b) => And(negationNormalForm(a, budget - 1), negationNormalForm(b, budget - 1))
- case Or(a, b) => Or(negationNormalForm(a, budget - 1), negationNormalForm(b, budget - 1))
- case Not(negated) => negationNormalFormNot(negated, budget - 1)
- case True
- | False
- | (_ : Sym) => p
+ /** Plaisted transformation: used for conversion of a
+ * propositional formula into conjunctive normal form (CNF)
+ * (input format for SAT solver).
+ * A simple conversion into CNF via Shannon expansion would
+ * also be possible but it's worst-case complexity is exponential
+ * (in the number of variables) and thus even simple problems
+ * could become untractable.
+ * The Plaisted transformation results in an _equisatisfiable_
+ * CNF-formula (it generates auxiliary variables)
+ * but runs with linear complexity.
+ * The common known Tseitin transformation uses bi-implication,
+ * whereas the Plaisted transformation uses implication only, thus
+ * the resulting CNF formula has (on average) only half of the clauses
+ * of a Tseitin transformation.
+ * The Plaisted transformation uses the polarities of sub-expressions
+ * to figure out which part of the bi-implication can be omitted.
+ * However, if all sub-expressions have positive polarity
+ * (e.g., after transformation into negation normal form)
+ * then the conversion is rather simple and the pseudo-normalization
+ * via NNF increases chances only one side of the bi-implication
+ * is needed.
+ */
+ class TransformToCnf(symbolMapping: SymbolMapping) extends CnfBuilder {
+
+ // new literals start after formula symbols
+ var literalCount: Int = symbolMapping.size
+
+ def convertSym(sym: Sym): Lit = symbolMapping.lit(sym)
+
+ def apply(p: Prop): Solvable = {
+
+ def convert(p: Prop): Lit = {
+ p match {
+ case And(fv) =>
+ and(fv.map(convert))
+ case Or(fv) =>
+ or(fv.map(convert))
+ case Not(a) =>
+ not(convert(a))
+ case sym: Sym =>
+ convertSym(sym)
+ case True =>
+ constTrue
+ case False =>
+ constFalse
+ case _: Eq =>
+ throw new MatchError(p)
+ }
}
- val TrueF = formula()
- val FalseF = formula(clause())
- def lit(s: Sym) = formula(clause(Lit(s)))
- def negLit(s: Sym) = formula(clause(Lit(s, pos = false)))
-
- def conjunctiveNormalForm(p: Prop, budget: Int = AnalysisBudget.max): Formula = {
- def distribute(a: Formula, b: Formula, budget: Int): Formula =
- if (budget <= 0) throw AnalysisBudget.exceeded
- else
- (a, b) match {
- // true \/ _ = true
- // _ \/ true = true
- case (trueA, trueB) if trueA.size == 0 || trueB.size == 0 => TrueF
- // lit \/ lit
- case (a, b) if a.size == 1 && b.size == 1 => formula(merge(a(0), b(0)))
- // (c1 /\ ... /\ cn) \/ d = ((c1 \/ d) /\ ... /\ (cn \/ d))
- // d \/ (c1 /\ ... /\ cn) = ((d \/ c1) /\ ... /\ (d \/ cn))
- case (cs, ds) =>
- val (big, small) = if (cs.size > ds.size) (cs, ds) else (ds, cs)
- big flatMap (c => distribute(formula(c), small, budget - (big.size*small.size)))
- }
+ def and(bv: Set[Lit]): Lit = {
+ if (bv.isEmpty) {
+ // this case can actually happen because `removeVarEq` could add no constraints
+ constTrue
+ } else if (bv.size == 1) {
+ bv.head
+ } else if (bv.contains(constFalse)) {
+ constFalse
+ } else {
+ // op1 /\ op2 /\ ... /\ opx <==>
+ // (o -> op1) /\ (o -> op2) ... (o -> opx) /\ (!op1 \/ !op2 \/... \/ !opx \/ o)
+ // (!o \/ op1) /\ (!o \/ op2) ... (!o \/ opx) /\ (!op1 \/ !op2 \/... \/ !opx \/ o)
+ val new_bv = bv - constTrue // ignore `True`
+ val o = newLiteral() // auxiliary Tseitin variable
+ new_bv.map(op => addClauseProcessed(clause(op, -o)))
+ o
+ }
+ }
- if (budget <= 0) throw AnalysisBudget.exceeded
-
- p match {
- case True => TrueF
- case False => FalseF
- case s: Sym => lit(s)
- case Not(s: Sym) => negLit(s)
- case And(a, b) =>
- val cnfA = conjunctiveNormalForm(a, budget - 1)
- val cnfB = conjunctiveNormalForm(b, budget - cnfA.size)
- cnfA ++ cnfB
- case Or(a, b) =>
- val cnfA = conjunctiveNormalForm(a)
- val cnfB = conjunctiveNormalForm(b)
- distribute(cnfA, cnfB, budget - (cnfA.size + cnfB.size))
+ def or(bv: Set[Lit]): Lit = {
+ if (bv.isEmpty) {
+ constFalse
+ } else if (bv.size == 1) {
+ bv.head
+ } else if (bv.contains(constTrue)) {
+ constTrue
+ } else {
+ // op1 \/ op2 \/ ... \/ opx <==>
+ // (op1 -> o) /\ (op2 -> o) ... (opx -> o) /\ (op1 \/ op2 \/... \/ opx \/ !o)
+ // (!op1 \/ o) /\ (!op2 \/ o) ... (!opx \/ o) /\ (op1 \/ op2 \/... \/ opx \/ !o)
+ val new_bv = bv - constFalse // ignore `False`
+ val o = newLiteral() // auxiliary Tseitin variable
+ addClauseProcessed(new_bv + (-o))
+ o
+ }
}
+
+ // no need for auxiliary variable
+ def not(a: Lit): Lit = -a
+
+ // add intermediate variable since we want the formula to be SAT!
+ addClauseProcessed(clause(convert(p)))
+
+ Solvable(buildCnf, symbolMapping)
}
+ }
- val start = if (Statistics.canEnable) Statistics.startTimer(patmatCNF) else null
- val res = conjunctiveNormalForm(negationNormalForm(p))
+ class AlreadyInCNF(symbolMapping: SymbolMapping) {
- if (Statistics.canEnable) Statistics.stopTimer(patmatCNF, start)
+ object ToLiteral {
+ def unapply(f: Prop): Option[Lit] = f match {
+ case Not(ToLiteral(lit)) => Some(-lit)
+ case sym: Sym => Some(symbolMapping.lit(sym))
+ case _ => None
+ }
+ }
- if (Statistics.canEnable) patmatCNFSizes(res.size).value += 1
+ object ToDisjunction {
+ def unapply(f: Prop): Option[Array[Clause]] = f match {
+ case Or(fv) =>
+ val cl = fv.foldLeft(Option(clause())) {
+ case (Some(clause), ToLiteral(lit)) =>
+ Some(clause + lit)
+ case (_, _) =>
+ None
+ }
+ cl.map(Array(_))
+ case True => Some(Array()) // empty, no clauses needed
+ case False => Some(Array(clause())) // empty clause can't be satisfied
+ case ToLiteral(lit) => Some(Array(clause(lit)))
+ case _ => None
+ }
+ }
-// debug.patmat("cnf for\n"+ p +"\nis:\n"+cnfString(res))
- res
+ /**
+ * Checks if propositional formula is already in CNF
+ */
+ object ToCnf {
+ def unapply(f: Prop): Option[Solvable] = f match {
+ case ToDisjunction(clauses) => Some(Solvable(clauses, symbolMapping) )
+ case And(fv) =>
+ val clauses = fv.foldLeft(Option(mutable.ArrayBuffer[Clause]())) {
+ case (Some(cnf), ToDisjunction(clauses)) =>
+ Some(cnf ++= clauses)
+ case (_, _) =>
+ None
+ }
+ clauses.map(c => Solvable(c.toArray, symbolMapping))
+ case _ => None
+ }
+ }
+ }
+
+ def eqFreePropToSolvable(p: Prop): Solvable = {
+
+ // collect all variables since after simplification / CNF conversion
+ // they could have been removed from the formula
+ val symbolMapping = new SymbolMapping(gatherSymbols(p))
+
+ val simplified = simplify(p)
+ val cnfExtractor = new AlreadyInCNF(symbolMapping)
+ simplified match {
+ case cnfExtractor.ToCnf(solvable) =>
+ // this is needed because t6942 would generate too many clauses with Tseitin
+ // already in CNF, just add clauses
+ solvable
+ case p =>
+ new TransformToCnf(symbolMapping).apply(p)
+ }
}
}
// simple solver using DPLL
trait Solver extends CNF {
- // a literal is a (possibly negated) variable
- def Lit(sym: Sym, pos: Boolean = true) = new Lit(sym, pos)
- class Lit(val sym: Sym, val pos: Boolean) {
- override def toString = if (!pos) "-"+ sym.toString else sym.toString
- override def equals(o: Any) = o match {
- case o: Lit => (o.sym eq sym) && (o.pos == pos)
- case _ => false
- }
- override def hashCode = sym.hashCode + pos.hashCode
+ import scala.collection.mutable.ArrayBuffer
- def unary_- = Lit(sym, !pos)
+ def cnfString(f: Array[Clause]): String = {
+ val lits: Array[List[String]] = f map (_.map(_.toString).toList)
+ val xss: List[List[String]] = lits toList
+ val aligned: String = alignAcrossRows(xss, "\\/", " /\\\n")
+ aligned
}
- def cnfString(f: Formula) = alignAcrossRows(f map (_.toList) toList, "\\/", " /\\\n")
-
// adapted from http://lara.epfl.ch/w/sav10:simple_sat_solver (original by Hossein Hojjat)
+
+ // empty set of clauses is trivially satisfied
val EmptyModel = Map.empty[Sym, Boolean]
+
+ // no model: originates from the encounter of an empty clause, i.e.,
+ // happens if all variables have been assigned in a way that makes the corresponding literals false
+ // thus there is no possibility to satisfy that clause, so the whole formula is UNSAT
val NoModel: Model = null
+ // this model contains the auxiliary variables as well
+ type TseitinModel = Set[Lit]
+ val EmptyTseitinModel = Set.empty[Lit]
+ val NoTseitinModel: TseitinModel = null
+
// returns all solutions, if any (TODO: better infinite recursion backstop -- detect fixpoint??)
- def findAllModelsFor(f: Formula): List[Model] = {
+ def findAllModelsFor(solvable: Solvable): List[Solution] = {
+ debug.patmat("find all models for\n"+ cnfString(solvable.cnf))
- debug.patmat("find all models for\n"+ cnfString(f))
+ // we must take all vars from non simplified formula
+ // otherwise if we get `T` as formula, we don't expand the variables
+ // that are not in the formula...
+ val relevantVars: Set[Int] = solvable.symbolMapping.relevantVars
- val vars: Set[Sym] = f.flatMap(_ collect {case l: Lit => l.sym}).toSet
// debug.patmat("vars "+ vars)
// the negation of a model -(S1=True/False /\ ... /\ SN=True/False) = clause(S1=False/True, ...., SN=False/True)
- def negateModel(m: Model) = clause(m.toSeq.map{ case (sym, pos) => Lit(sym, !pos) } : _*)
-
- /**
- * The DPLL procedure only returns a minimal mapping from literal to value
- * such that the CNF formula is satisfied.
- * E.g. for:
- * `(a \/ b)`
- * The DPLL procedure will find either {a = true} or {b = true}
- * as solution.
- *
- * The expansion step will amend both solutions with the unassigned variable
- * i.e., {a = true} will be expanded to {a = true, b = true} and {a = true, b = false}.
- */
- def expandUnassigned(unassigned: List[Sym], model: Model): List[Model] = {
- // the number of solutions is doubled for every unassigned variable
- val expandedModels = 1 << unassigned.size
- var current = mutable.ArrayBuffer[Model]()
- var next = mutable.ArrayBuffer[Model]()
- current.sizeHint(expandedModels)
- next.sizeHint(expandedModels)
-
- current += model
-
- // we use double buffering:
- // read from `current` and create a two models for each model in `next`
- for {
- s <- unassigned
- } {
- for {
- model <- current
- } {
- def force(l: Lit) = model + (l.sym -> l.pos)
-
- next += force(Lit(s, pos = true))
- next += force(Lit(s, pos = false))
- }
-
- val tmp = current
- current = next
- next = tmp
-
- next.clear()
- }
-
- current.toList
+ // (i.e. the blocking clause - used for ALL-SAT)
+ def negateModel(m: TseitinModel) = {
+ // filter out auxiliary Tseitin variables
+ val relevantLits = m.filter(l => relevantVars.contains(l.variable))
+ relevantLits.map(lit => -lit)
}
- def findAllModels(f: Formula,
- models: List[Model],
- recursionDepthAllowed: Int = global.settings.YpatmatExhaustdepth.value): List[Model]=
+ final case class TseitinSolution(model: TseitinModel, unassigned: List[Int]) {
+ def projectToSolution(symForVar: Map[Int, Sym]) = Solution(projectToModel(model, symForVar), unassigned map symForVar)
+ }
+ def findAllModels(clauses: Array[Clause],
+ models: List[TseitinSolution],
+ recursionDepthAllowed: Int = global.settings.YpatmatExhaustdepth.value): List[TseitinSolution]=
if (recursionDepthAllowed == 0) {
val maxDPLLdepth = global.settings.YpatmatExhaustdepth.value
reportWarning("(Exhaustivity analysis reached max recursion depth, not all missing cases are reported. " +
s"Please try with scalac -Ypatmat-exhaust-depth ${maxDPLLdepth * 2} or -Ypatmat-exhaust-depth off.)")
models
} else {
- val model = findModelFor(f)
+ debug.patmat("find all models for\n" + cnfString(clauses))
+ val model = findTseitinModelFor(clauses)
// if we found a solution, conjunct the formula with the model's negation and recurse
- if (model ne NoModel) {
- val unassigned = (vars -- model.keySet).toList
+ if (model ne NoTseitinModel) {
+ // note that we should not expand the auxiliary variables (from Tseitin transformation)
+ // since they are existentially quantified in the final solution
+ val unassigned: List[Int] = (relevantVars -- model.map(lit => lit.variable)).toList
debug.patmat("unassigned "+ unassigned +" in "+ model)
- val forced = expandUnassigned(unassigned, model)
- debug.patmat("forced "+ forced)
+ val solution = TseitinSolution(model, unassigned)
val negated = negateModel(model)
- findAllModels(f :+ negated, forced ++ models, recursionDepthAllowed - 1)
+ findAllModels(clauses :+ negated, solution :: models, recursionDepthAllowed - 1)
}
else models
}
- findAllModels(f, Nil)
+ val tseitinSolutions = findAllModels(solvable.cnf, Nil)
+ tseitinSolutions.map(_.projectToSolution(solvable.symbolMapping.symForVar))
}
- private def withLit(res: Model, l: Lit): Model = if (res eq NoModel) NoModel else res + (l.sym -> l.pos)
- private def dropUnit(f: Formula, unitLit: Lit): Formula = {
+ private def withLit(res: TseitinModel, l: Lit): TseitinModel = {
+ if (res eq NoTseitinModel) NoTseitinModel else res + l
+ }
+
+ /** Drop trivially true clauses, simplify others by dropping negation of `unitLit`.
+ *
+ * Disjunctions that contain the literal we're making true in the returned model are trivially true.
+ * Clauses can be simplified by dropping the negation of the literal we're making true
+ * (since False \/ X == X)
+ */
+ private def dropUnit(clauses: Array[Clause], unitLit: Lit): Array[Clause] = {
val negated = -unitLit
- // drop entire clauses that are trivially true
- // (i.e., disjunctions that contain the literal we're making true in the returned model),
- // and simplify clauses by dropping the negation of the literal we're making true
- // (since False \/ X == X)
- val dropped = formulaBuilderSized(f.size)
- for {
- clause <- f
- if !(clause contains unitLit)
- } dropped += (clause - negated)
- dropped
+ val simplified = new ArrayBuffer[Clause](clauses.size)
+ clauses foreach {
+ case trivial if trivial contains unitLit => // drop
+ case clause => simplified += clause - negated
+ }
+ simplified.toArray
+ }
+
+ def findModelFor(solvable: Solvable): Model = {
+ projectToModel(findTseitinModelFor(solvable.cnf), solvable.symbolMapping.symForVar)
}
- def findModelFor(f: Formula): Model = {
- @inline def orElse(a: Model, b: => Model) = if (a ne NoModel) a else b
+ def findTseitinModelFor(clauses: Array[Clause]): TseitinModel = {
+ @inline def orElse(a: TseitinModel, b: => TseitinModel) = if (a ne NoTseitinModel) a else b
- debug.patmat("DPLL\n"+ cnfString(f))
+ debug.patmat(s"DPLL\n${cnfString(clauses)}")
val start = if (Statistics.canEnable) Statistics.startTimer(patmatAnaDPLL) else null
- val satisfiableWithModel: Model =
- if (f isEmpty) EmptyModel
- else if(f exists (_.isEmpty)) NoModel
- else f.find(_.size == 1) match {
+ val satisfiableWithModel: TseitinModel =
+ if (clauses isEmpty) EmptyTseitinModel
+ else if (clauses exists (_.isEmpty)) NoTseitinModel
+ else clauses.find(_.size == 1) match {
case Some(unitClause) =>
val unitLit = unitClause.head
- // debug.patmat("unit: "+ unitLit)
- withLit(findModelFor(dropUnit(f, unitLit)), unitLit)
+ withLit(findTseitinModelFor(dropUnit(clauses, unitLit)), unitLit)
case _ =>
// partition symbols according to whether they appear in positive and/or negative literals
- val pos = new mutable.HashSet[Sym]()
- val neg = new mutable.HashSet[Sym]()
- mforeach(f)(lit => if (lit.pos) pos += lit.sym else neg += lit.sym)
+ val pos = new mutable.HashSet[Int]()
+ val neg = new mutable.HashSet[Int]()
+ mforeach(clauses)(lit => if (lit.positive) pos += lit.variable else neg += lit.variable)
// appearing in both positive and negative
val impures = pos intersect neg
@@ -259,23 +387,38 @@ trait Solving extends Logic {
val pures = (pos ++ neg) -- impures
if (pures nonEmpty) {
- val pureSym = pures.head
+ val pureVar = pures.head
// turn it back into a literal
// (since equality on literals is in terms of equality
// of the underlying symbol and its positivity, simply construct a new Lit)
- val pureLit = Lit(pureSym, pos(pureSym))
+ val pureLit = Lit(if (neg(pureVar)) -pureVar else pureVar)
// debug.patmat("pure: "+ pureLit +" pures: "+ pures +" impures: "+ impures)
- val simplified = f.filterNot(_.contains(pureLit))
- withLit(findModelFor(simplified), pureLit)
+ val simplified = clauses.filterNot(_.contains(pureLit))
+ withLit(findTseitinModelFor(simplified), pureLit)
} else {
- val split = f.head.head
+ val split = clauses.head.head
// debug.patmat("split: "+ split)
- orElse(findModelFor(f :+ clause(split)), findModelFor(f :+ clause(-split)))
+ orElse(findTseitinModelFor(clauses :+ clause(split)), findTseitinModelFor(clauses :+ clause(-split)))
}
}
if (Statistics.canEnable) Statistics.stopTimer(patmatAnaDPLL, start)
satisfiableWithModel
}
+
+ private def projectToModel(model: TseitinModel, symForVar: Map[Int, Sym]): Model =
+ if (model == NoTseitinModel) NoModel
+ else if (model == EmptyTseitinModel) EmptyModel
+ else {
+ val mappedModels = model.toList collect {
+ case lit if symForVar isDefinedAt lit.variable => (symForVar(lit.variable), lit.positive)
+ }
+ if (mappedModels.isEmpty) {
+ // could get an empty model if mappedModels is a constant like `True`
+ EmptyModel
+ } else {
+ mappedModels.toMap
+ }
+ }
}
}
diff --git a/src/compiler/scala/tools/nsc/typechecker/ContextErrors.scala b/src/compiler/scala/tools/nsc/typechecker/ContextErrors.scala
index 6868f06606..c80aaea160 100644
--- a/src/compiler/scala/tools/nsc/typechecker/ContextErrors.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/ContextErrors.scala
@@ -81,7 +81,7 @@ trait ContextErrors {
// 2) provide the type of the implicit parameter for which we got diverging expansion
// (pt at the point of divergence gives less information to the user)
// Note: it is safe to delay error message generation in this case
- // becasue we don't modify implicits' infos.
+ // because we don't modify implicits' infos.
case class DivergentImplicitTypeError(underlyingTree: Tree, pt0: Type, sym: Symbol)
extends TreeTypeError {
def errMsg: String = errMsgForPt(pt0)
diff --git a/src/compiler/scala/tools/nsc/typechecker/Contexts.scala b/src/compiler/scala/tools/nsc/typechecker/Contexts.scala
index a7d0d32c6f..ca25e59c4b 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Contexts.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Contexts.scala
@@ -145,7 +145,7 @@ trait Contexts { self: Analyzer =>
* - A variety of bits that track the current error reporting policy (more on this later);
* whether or not implicits/macros are enabled, whether we are in a self or super call or
* in a constructor suffix. These are represented as bits in the mask `contextMode`.
- * - Some odds and ends: undetermined type pararameters of the current line of type inference;
+ * - Some odds and ends: undetermined type parameters of the current line of type inference;
* contextual augmentation for error messages, tracking of the nesting depth.
*
* And behaviour:
@@ -154,19 +154,19 @@ trait Contexts { self: Analyzer =>
* to buffer these for use in 'silent' type checking, when some recovery might be possible.
* - `Context` is something of a Zipper for the tree were are typechecking: it `enclosingContextChain`
* is the path back to the root. This is exactly what we need to resolve names (`lookupSymbol`)
- * and to collect in-scope implicit defintions (`implicitss`)
+ * and to collect in-scope implicit definitions (`implicitss`)
* Supporting these are `imports`, which represents all `Import` trees in in the enclosing context chain.
- * - In a similar vein, we can assess accessiblity (`isAccessible`.)
+ * - In a similar vein, we can assess accessibility (`isAccessible`.)
*
* More on error buffering:
* When are type errors recoverable? In quite a few places, it turns out. Some examples:
* trying to type an application with/without the expected type, or with/without implicit views
* enabled. This is usually mediated by `Typer.silent`, `Inferencer#tryTwice`.
*
- * Intially, starting from the `typer` phase, the contexts either buffer or report errors;
+ * Initially, starting from the `typer` phase, the contexts either buffer or report errors;
* afterwards errors are thrown. This is configured in `rootContext`. Additionally, more
* fine grained control is needed based on the kind of error; ambiguity errors are often
- * suppressed during exploraratory typing, such as determining whether `a == b` in an argument
+ * suppressed during exploratory typing, such as determining whether `a == b` in an argument
* position is an assignment or a named argument, when `Infererencer#isApplicableSafe` type checks
* applications with and without an expected type, or whtn `Typer#tryTypedApply` tries to fit arguments to
* a function type with/without implicit views.
diff --git a/src/compiler/scala/tools/nsc/typechecker/Implicits.scala b/src/compiler/scala/tools/nsc/typechecker/Implicits.scala
index 74c28122a1..71558273a6 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Implicits.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Implicits.scala
@@ -3,7 +3,7 @@
* @author Martin Odersky
*/
-//todo: rewrite or disllow new T where T is a mixin (currently: <init> not a member of T)
+//todo: rewrite or disallow new T where T is a mixin (currently: <init> not a member of T)
//todo: use inherited type info also for vars and values
//todo: disallow C#D in superclass
//todo: treat :::= correctly
@@ -159,7 +159,7 @@ trait Implicits {
* @param tree The tree representing the implicit
* @param subst A substituter that represents the undetermined type parameters
* that were instantiated by the winning implicit.
- * @param undetparams undeterminted type parameters
+ * @param undetparams undetermined type parameters
*/
class SearchResult(val tree: Tree, val subst: TreeTypeSubstituter, val undetparams: List[Symbol]) {
override def toString = "SearchResult(%s, %s)".format(tree,
diff --git a/src/compiler/scala/tools/nsc/typechecker/Infer.scala b/src/compiler/scala/tools/nsc/typechecker/Infer.scala
index 8979b26719..cf97474d9a 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Infer.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Infer.scala
@@ -1017,7 +1017,7 @@ trait Infer extends Checkable {
/** Substitute free type variables `undetparams` of type constructor
* `tree` in pattern, given prototype `pt`.
*
- * @param tree the constuctor that needs to be instantiated
+ * @param tree the constructor that needs to be instantiated
* @param undetparams the undetermined type parameters
* @param pt0 the expected result type of the instance
*/
diff --git a/src/compiler/scala/tools/nsc/typechecker/Namers.scala b/src/compiler/scala/tools/nsc/typechecker/Namers.scala
index 0bb94be636..711cfba24d 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Namers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Namers.scala
@@ -171,7 +171,7 @@ trait Namers extends MethodSynthesis {
val newFlags = (sym.flags & LOCKED) | flags
sym.rawInfo match {
case tr: TypeRef =>
- // !!! needed for: pos/t5954d; the uniques type cache will happilly serve up the same TypeRef
+ // !!! needed for: pos/t5954d; the uniques type cache will happily serve up the same TypeRef
// over this mutated symbol, and we witness a stale cache for `parents`.
tr.invalidateCaches()
case _ =>
diff --git a/src/compiler/scala/tools/nsc/typechecker/NamesDefaults.scala b/src/compiler/scala/tools/nsc/typechecker/NamesDefaults.scala
index 4f943fcd28..39cd610b1c 100644
--- a/src/compiler/scala/tools/nsc/typechecker/NamesDefaults.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/NamesDefaults.scala
@@ -384,7 +384,7 @@ trait NamesDefaults { self: Analyzer =>
* of arguments.
*
* @param args The list of arguments
- * @param params The list of parameter sybols of the invoked method
+ * @param params The list of parameter symbols of the invoked method
* @param argName A function that extracts the name of an argument expression, if it is a named argument.
*/
def missingParams[T](args: List[T], params: List[Symbol], argName: T => Option[Name]): (List[Symbol], Boolean) = {
diff --git a/src/compiler/scala/tools/nsc/typechecker/PatternTypers.scala b/src/compiler/scala/tools/nsc/typechecker/PatternTypers.scala
index bb8c3c3c6d..fa4a764f1b 100644
--- a/src/compiler/scala/tools/nsc/typechecker/PatternTypers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/PatternTypers.scala
@@ -336,7 +336,7 @@ trait PatternTypers {
val app = atPos(uncheckedPattern.pos)(Apply(classTagExtractor, args))
// must call doTypedUnapply directly, as otherwise we get undesirable rewrites
// and re-typechecks of the target of the unapply call in PATTERNmode,
- // this breaks down when the classTagExtractor (which defineds the unapply member) is not a simple reference to an object,
+ // this breaks down when the classTagExtractor (which defines the unapply member) is not a simple reference to an object,
// but an arbitrary tree as is the case here
val res = doTypedUnapply(app, classTagExtractor, classTagExtractor, args, PATTERNmode, pt)
diff --git a/src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala b/src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala
index 1daff02c23..d2046a158c 100644
--- a/src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala
@@ -171,7 +171,7 @@ trait SyntheticMethods extends ast.TreeDSL {
def thatCast(eqmeth: Symbol): Tree =
gen.mkCast(Ident(eqmeth.firstParam), clazz.tpe)
- /* The equality method core for case classes and inline clases.
+ /* The equality method core for case classes and inline classes.
* 1+ args:
* (that.isInstanceOf[this.C]) && {
* val x$1 = that.asInstanceOf[this.C]
diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
index 22cf8c6808..3a85d16f55 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
@@ -829,6 +829,16 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper
}
orElse { _ =>
val resetTree = resetAttrs(original)
+ resetTree match {
+ case treeInfo.Applied(fun, targs, args) =>
+ if (fun.symbol != null && fun.symbol.isError)
+ // SI-9041 Without this, we leak error symbols past the typer!
+ // because the fallback typechecking notices the error-symbol,
+ // refuses to re-attempt typechecking, and presumes that someone
+ // else was responsible for issuing the related type error!
+ fun.setSymbol(NoSymbol)
+ case _ =>
+ }
debuglog(s"fallback on implicits: ${tree}/$resetTree")
val tree1 = typed(resetTree, mode)
// Q: `typed` already calls `pluginsTyped` and `adapt`. the only difference here is that
@@ -950,7 +960,7 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper
// Ignore type errors raised in later phases that are due to mismatching types with existential skolems
// We have lift crashing in 2.9 with an adapt failure in the pattern matcher.
- // Here's my hypothsis why this happens. The pattern matcher defines a variable of type
+ // Here's my hypothesis why this happens. The pattern matcher defines a variable of type
//
// val x: T = expr
//
@@ -1181,7 +1191,7 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper
}
def instantiatePossiblyExpectingUnit(tree: Tree, mode: Mode, pt: Type): Tree = {
- if (mode.typingExprNotFun && pt.typeSymbol == UnitClass)
+ if (mode.typingExprNotFun && pt.typeSymbol == UnitClass && !tree.tpe.isInstanceOf[MethodType])
instantiateExpectingUnit(tree, mode)
else
instantiate(tree, mode, pt)
@@ -1540,7 +1550,11 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper
val cbody1 = treeCopy.Block(cbody, preSuperStats, superCall1)
val clazz = context.owner
assert(clazz != NoSymbol, templ)
- val dummy = context.outer.owner.newLocalDummy(templ.pos)
+ // SI-9086 The position of this symbol is material: implicit search will avoid triggering
+ // cyclic errors in an implicit search in argument to the super constructor call on
+ // account of the "ignore symbols without complete info that succeed the implicit search"
+ // in this source file. See `ImplicitSearch#isValid` and `ImplicitInfo#isCyclicOrErroneous`.
+ val dummy = context.outer.owner.newLocalDummy(context.owner.pos)
val cscope = context.outer.makeNewScope(ctor, dummy)
if (dummy.isTopLevel) currentRun.symSource(dummy) = currentUnit.source.file
val cbody2 = { // called both during completion AND typing.
@@ -3285,6 +3299,22 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper
}
handleOverloaded
+ case _ if isPolymorphicSignature(fun.symbol) =>
+ // Mimic's Java's treatment of polymorphic signatures as described in
+ // https://docs.oracle.com/javase/specs/jls/se8/html/jls-15.html#jls-15.12.3
+ //
+ // One can think of these methods as being infinitely overloaded. We create
+ // a ficticious new cloned method symbol for each call site that takes on a signature
+ // governed by a) the argument types and b) the expected type
+ val args1 = typedArgs(args, forArgMode(fun, mode))
+ val pts = args1.map(_.tpe.deconst)
+ val clone = fun.symbol.cloneSymbol
+ val cloneParams = pts map (pt => clone.newValueParameter(currentUnit.freshTermName()).setInfo(pt))
+ val resultType = if (isFullyDefined(pt)) pt else ObjectTpe
+ clone.modifyInfo(mt => copyMethodType(mt, cloneParams, resultType))
+ val fun1 = fun.setSymbol(clone).setType(clone.info)
+ doTypedApply(tree, fun1, args1, mode, resultType).setType(resultType)
+
case mt @ MethodType(params, _) =>
val paramTypes = mt.paramTypes
// repeat vararg as often as needed, remove by-name
@@ -3780,8 +3810,12 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper
case TypeRef(pre, sym, args) =>
if (sym.isAliasType && containsLocal(tp) && (tp.dealias ne tp)) apply(tp.dealias)
else {
- if (pre.isVolatile)
- InferTypeWithVolatileTypeSelectionError(tree, pre)
+ if (pre.isVolatile) pre match {
+ case SingleType(_, sym) if sym.isSynthetic && isPastTyper =>
+ debuglog(s"ignoring volatility of prefix in pattern matcher generated inferred type: $tp") // See pos/t7459c.scala
+ case _ =>
+ InferTypeWithVolatileTypeSelectionError(tree, pre)
+ }
mapOver(tp)
}
case _ =>
diff --git a/src/compiler/scala/tools/nsc/util/DocStrings.scala b/src/compiler/scala/tools/nsc/util/DocStrings.scala
index ba44126df2..352816803f 100755
--- a/src/compiler/scala/tools/nsc/util/DocStrings.scala
+++ b/src/compiler/scala/tools/nsc/util/DocStrings.scala
@@ -8,7 +8,7 @@ package util
import scala.reflect.internal.Chars._
-/** Utilitity methods for doc comment strings
+/** Utility methods for doc comment strings
*/
object DocStrings {
diff --git a/src/eclipse/README.md b/src/eclipse/README.md
index 5311651db5..03c7403b04 100644
--- a/src/eclipse/README.md
+++ b/src/eclipse/README.md
@@ -1,28 +1,9 @@
Eclipse project files
=====================
-The following points describe how to get Scala to run in Eclipse:
+The following points describe how to get Scala to run in Eclipse. Please also take a look at the [excellent tutorial on scala-ide.org](http://scala-ide.org/docs/tutorials/scalac-trunk/index.html).
-0. To get Scala to work inside of Eclipse Kepler it is necessary to build the Scala IDE by your own
-because for the moment there is no update site provided for the newest development version
-of Scala. To do so enter the following commands one after the other:
-
- git clone https://github.com/scala-ide/scala-ide.git
- cd scala-ide
- ./build-all.sh clean install -Pscala-2.11.x -Peclipse-kepler -DskipTests
-
- After that you have an update site in `scala-ide/org.scala-ide.sdt.update-site/target/site`, which needs to be
-installed in Eclipse.
-
-0. The second thing that needs to be done is building Scala in order to get all necessary
-dependencies. To do that simply enter
-
- ant
-
- and wait until it is completed. To verify that everything has been built successfully, execute the REPL that can be found
-at `scala/build/pack/bin/scala`.
-
-0. Import all projects inside of Eclipse by choosing `File/Import Existing Projects`
+0. Import all projects into a [very recent version of Scala IDE for Eclipse](http://scala-ide.org/download/nightly.html) by choosing `File/Import Existing Projects`
and navigate to `scala/src/eclipse`. Check all projects and click ok.
0. You need to define a `path variable` inside Eclipse. Define `SCALA_BASEDIR` in
diff --git a/src/intellij-14/scala.ipr.SAMPLE b/src/intellij-14/scala.ipr.SAMPLE
index 7c2022f3a9..1e3d07466d 100644
--- a/src/intellij-14/scala.ipr.SAMPLE
+++ b/src/intellij-14/scala.ipr.SAMPLE
@@ -233,14 +233,14 @@
<library name="starr" type="Scala">
<properties>
<compiler-classpath>
- <root url="file://$PROJECT_DIR$/../../build/deps/starr/scala-compiler-2.11.2.jar" />
- <root url="file://$PROJECT_DIR$/../../build/deps/starr/scala-library-2.11.2.jar" />
- <root url="file://$PROJECT_DIR$/../../build/deps/starr/scala-reflect-2.11.2.jar" />
+ <root url="file://$PROJECT_DIR$/../../build/deps/starr/scala-compiler-#scala-version#.jar" />
+ <root url="file://$PROJECT_DIR$/../../build/deps/starr/scala-library-#scala-version#.jar" />
+ <root url="file://$PROJECT_DIR$/../../build/deps/starr/scala-reflect-#scala-version#.jar" />
</compiler-classpath>
</properties>
<CLASSES>
- <root url="jar://$PROJECT_DIR$/../../build/deps/starr/scala-library-2.11.2.jar!/" />
- <root url="jar://$PROJECT_DIR$/../../build/deps/starr/scala-reflect-2.11.2.jar!/" />
+ <root url="jar://$PROJECT_DIR$/../../build/deps/starr/scala-library-#scala-version#.jar!/" />
+ <root url="jar://$PROJECT_DIR$/../../build/deps/starr/scala-reflect-#scala-version#.jar!/" />
</CLASSES>
<JAVADOC />
<SOURCES />
@@ -248,9 +248,9 @@
<library name="starr-no-deps" type="Scala">
<properties>
<compiler-classpath>
- <root url="file://$PROJECT_DIR$/../../build/deps/starr/scala-compiler-2.11.2.jar" />
- <root url="file://$PROJECT_DIR$/../../build/deps/starr/scala-library-2.11.2.jar" />
- <root url="file://$PROJECT_DIR$/../../build/deps/starr/scala-reflect-2.11.2.jar" />
+ <root url="file://$PROJECT_DIR$/../../build/deps/starr/scala-compiler-#scala-version#.jar" />
+ <root url="file://$PROJECT_DIR$/../../build/deps/starr/scala-library-#scala-version#.jar" />
+ <root url="file://$PROJECT_DIR$/../../build/deps/starr/scala-reflect-#scala-version#.jar" />
</compiler-classpath>
</properties>
<CLASSES />
diff --git a/src/intellij-14/setup.sh b/src/intellij-14/setup.sh
index ec303778ed..cf08898f24 100755
--- a/src/intellij-14/setup.sh
+++ b/src/intellij-14/setup.sh
@@ -12,3 +12,6 @@ for f in "$SCRIPT_DIR"/*.SAMPLE; do
g=${f%.SAMPLE}
cp $f $g
done
+
+SCALA_VERSION="`cat $SCRIPT_DIR/../../versions.properties | grep 'starr.version' | awk '{split($0,a,"="); print a[2]}'`"
+sed "s/#scala-version#/$SCALA_VERSION/g" $SCRIPT_DIR/scala.ipr.SAMPLE > $SCRIPT_DIR/scala.ipr \ No newline at end of file
diff --git a/src/intellij/scala-lang.ipr.SAMPLE b/src/intellij/scala-lang.ipr.SAMPLE
index c0614c946c..0cd3fdae6a 100644
--- a/src/intellij/scala-lang.ipr.SAMPLE
+++ b/src/intellij/scala-lang.ipr.SAMPLE
@@ -218,6 +218,7 @@
<module fileurl="file://$PROJECT_DIR$/scalap.iml" filepath="$PROJECT_DIR$/scalap.iml" />
<module fileurl="file://$PROJECT_DIR$/test.iml" filepath="$PROJECT_DIR$/test.iml" />
<module fileurl="file://$PROJECT_DIR$/test-junit.iml" filepath="$PROJECT_DIR$/test-junit.iml" />
+ <module fileurl="file://$PROJECT_DIR$/test-osgi.iml" filepath="$PROJECT_DIR$/test-osgi.iml" />
</modules>
</component>
<component name="ProjectResources">
diff --git a/src/intellij/test-osgi.iml.SAMPLE b/src/intellij/test-osgi.iml.SAMPLE
new file mode 100644
index 0000000000..a589aaa0a9
--- /dev/null
+++ b/src/intellij/test-osgi.iml.SAMPLE
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<module type="JAVA_MODULE" version="4">
+ <component name="NewModuleRootManager" inherit-compiler-output="true">
+ <exclude-output />
+ <content url="file://$MODULE_DIR$/../../test/osgi">
+ <sourceFolder url="file://$MODULE_DIR$/../../test/osgi/src" isTestSource="false" />
+ </content>
+ <orderEntry type="inheritedJdk" />
+ <orderEntry type="sourceFolder" forTests="false" />
+ <orderEntry type="module" module-name="actors" />
+ <orderEntry type="module" module-name="asm" />
+ <orderEntry type="module" module-name="compiler" />
+ <orderEntry type="module" module-name="library" />
+ <orderEntry type="module" module-name="reflect" />
+ <orderEntry type="module" module-name="repl" />
+ <orderEntry type="module" module-name="partest-extras" />
+ <orderEntry type="module" module-name="forkjoin" />
+ <orderEntry type="library" name="junit" level="project" />
+ <orderEntry type="library" name="scaladoc-deps" level="project" />
+ <orderEntry type="library" name="scala-sdk" level="project" />
+ <orderEntry type="library" scope="PROVIDED" name="pax.exam-deps" level="project" />
+ </component>
+</module> \ No newline at end of file
diff --git a/src/intellij/test/files/neg/virtpatmat_exhaust_big.check b/src/intellij/test/files/neg/virtpatmat_exhaust_big.check
new file mode 100644
index 0000000000..fddc85a362
--- /dev/null
+++ b/src/intellij/test/files/neg/virtpatmat_exhaust_big.check
@@ -0,0 +1,7 @@
+virtpatmat_exhaust_big.scala:27: warning: match may not be exhaustive.
+It would fail on the following input: Z11()
+ def foo(z: Z) = z match {
+ ^
+error: No warnings can be incurred under -Xfatal-warnings.
+one warning found
+one error found
diff --git a/src/intellij/test/files/neg/virtpatmat_exhaust_big.flags b/src/intellij/test/files/neg/virtpatmat_exhaust_big.flags
new file mode 100644
index 0000000000..b5a8748652
--- /dev/null
+++ b/src/intellij/test/files/neg/virtpatmat_exhaust_big.flags
@@ -0,0 +1 @@
+-Xfatal-warnings -unchecked
diff --git a/src/intellij/test/files/neg/virtpatmat_exhaust_big.scala b/src/intellij/test/files/neg/virtpatmat_exhaust_big.scala
new file mode 100644
index 0000000000..dd639eb56e
--- /dev/null
+++ b/src/intellij/test/files/neg/virtpatmat_exhaust_big.scala
@@ -0,0 +1,32 @@
+sealed abstract class Z
+object Z {
+ object Z0 extends Z
+ case class Z1() extends Z
+ object Z2 extends Z
+ case class Z3() extends Z
+ object Z4 extends Z
+ case class Z5() extends Z
+ object Z6 extends Z
+ case class Z7() extends Z
+ object Z8 extends Z
+ case class Z9() extends Z
+ object Z10 extends Z
+ case class Z11() extends Z
+ object Z12 extends Z
+ case class Z13() extends Z
+ object Z14 extends Z
+ case class Z15() extends Z
+ object Z16 extends Z
+ case class Z17() extends Z
+ object Z18 extends Z
+ case class Z19() extends Z
+}
+
+object Test {
+ import Z._
+ def foo(z: Z) = z match {
+ case Z0 | Z1() | Z2 | Z3() | Z4 | Z5() | Z6 | Z7() | Z8 | Z9() |
+ Z10 | Z12 | Z13() | Z14 | Z15() | Z16 | Z17() | Z18 | Z19()
+ =>
+ }
+}
diff --git a/src/intellij/test/files/pos/virtpatmat_exhaust_big.scala b/src/intellij/test/files/pos/virtpatmat_exhaust_big.scala
new file mode 100644
index 0000000000..41aef3226e
--- /dev/null
+++ b/src/intellij/test/files/pos/virtpatmat_exhaust_big.scala
@@ -0,0 +1,34 @@
+sealed abstract class Z
+object Z {
+ object Z0 extends Z
+ case class Z1() extends Z
+ object Z2 extends Z
+ case class Z3() extends Z
+ object Z4 extends Z
+ case class Z5() extends Z
+ object Z6 extends Z
+ case class Z7() extends Z
+ object Z8 extends Z
+ case class Z9() extends Z
+ object Z10 extends Z
+ case class Z11() extends Z
+ object Z12 extends Z
+ case class Z13() extends Z
+ object Z14 extends Z
+ case class Z15() extends Z
+ object Z16 extends Z
+ case class Z17() extends Z
+ object Z18 extends Z
+ case class Z19() extends Z
+}
+
+// drop any case and it will report an error
+object Test {
+ import Z._
+ def foo(z: Z) = z match {
+ case Z0 | Z1() | Z2 | Z3() | Z4 | Z5() | Z6 | Z7() | Z8 | Z9() |
+ Z10 | Z11() | Z12 | Z13() | Z14 | Z15() | Z16 | Z17() | Z18 | Z19()
+ =>
+ }
+}
+-
diff --git a/src/interactive/scala/tools/nsc/interactive/Global.scala b/src/interactive/scala/tools/nsc/interactive/Global.scala
index 5d00141e6a..9b34a39e02 100644
--- a/src/interactive/scala/tools/nsc/interactive/Global.scala
+++ b/src/interactive/scala/tools/nsc/interactive/Global.scala
@@ -78,7 +78,11 @@ trait InteractiveAnalyzer extends Analyzer {
val owningInfo = sym.owner.info
val existingDerivedSym = owningInfo.decl(sym.name.toTermName).filter(sym => sym.isSynthetic && sym.isMethod)
existingDerivedSym.alternatives foreach (owningInfo.decls.unlink)
- enterImplicitWrapper(tree.asInstanceOf[ClassDef])
+ val defTree = tree match {
+ case dd: DocDef => dd.definition // See SI-9011, Scala IDE's presentation compiler incorporates ScalaDocGlobal with InterativeGlobal, so we have to unwrap DocDefs.
+ case _ => tree
+ }
+ enterImplicitWrapper(defTree.asInstanceOf[ClassDef])
}
super.enterExistingSym(sym, tree)
}
@@ -522,7 +526,7 @@ class Global(settings: Settings, _reporter: Reporter, projectName: String = "")
/** The current presentation compiler runner */
@volatile private[interactive] var compileRunner: Thread = newRunnerThread()
- /** Check that the currenyly executing thread is the presentation compiler thread.
+ /** Check that the currently executing thread is the presentation compiler thread.
*
* Compiler initialization may happen on a different thread (signalled by globalPhase being NoPhase)
*/
@@ -1188,7 +1192,7 @@ class Global(settings: Settings, _reporter: Reporter, projectName: String = "")
}
}
- /** Parses and enters given source file, stroring parse tree in response */
+ /** Parses and enters given source file, storing parse tree in response */
private def getParsedEnteredNow(source: SourceFile, response: Response[Tree]) {
respond(response) {
onUnitOf(source) { unit =>
diff --git a/src/interactive/scala/tools/nsc/interactive/Pickler.scala b/src/interactive/scala/tools/nsc/interactive/Pickler.scala
index 83f3fab925..ddc0c8a068 100644
--- a/src/interactive/scala/tools/nsc/interactive/Pickler.scala
+++ b/src/interactive/scala/tools/nsc/interactive/Pickler.scala
@@ -6,7 +6,7 @@ import scala.language.implicitConversions
import scala.reflect.ClassTag
/** An abstract class for writing and reading Scala objects to and
- * from a legible representation. The presesentation follows the following grammar:
+ * from a legible representation. The representation follows the following grammar:
* {{{
* Pickled = `true` | `false` | `null` | NumericLit | StringLit |
* Labelled | Pickled `,` Pickled
@@ -85,7 +85,7 @@ abstract class Pickler[T] {
object Pickler {
/** A base class representing unpickler result. It has two subclasses:
- * `UnpickleSucess` for successful unpicklings and `UnpickleFailure` for failures,
+ * `UnpickleSuccess` for successful unpicklings and `UnpickleFailure` for failures,
* where a value of the given type `T` could not be unpickled from input.
* @tparam T the type of unpickled values in case of success.
*/
@@ -154,7 +154,7 @@ object Pickler {
*/
def pkl[T: Pickler] = implicitly[Pickler[T]]
- /** A class represenenting `~`-pairs */
+ /** A class representing `~`-pairs */
case class ~[+S, +T](fst: S, snd: T)
/** A wrapper class to be able to use `~` s an infix method */
diff --git a/src/library/scala/Enumeration.scala b/src/library/scala/Enumeration.scala
index e11d1b35d7..c4aa511cd7 100644
--- a/src/library/scala/Enumeration.scala
+++ b/src/library/scala/Enumeration.scala
@@ -121,7 +121,8 @@ abstract class Enumeration (initial: Int) extends Serializable {
* @throws NoSuchElementException if no `Value` with a matching
* name is in this `Enumeration`
*/
- final def withName(s: String): Value = values.find(_.toString == s).get
+ final def withName(s: String): Value = values.find(_.toString == s).getOrElse(
+ throw new NoSuchElementException(s"No value found for '$s'"))
/** Creates a fresh value, part of this enumeration. */
protected final def Value: Value = Value(nextId)
diff --git a/src/library/scala/Option.scala b/src/library/scala/Option.scala
index 41224f4c6c..f134f5ce3d 100644
--- a/src/library/scala/Option.scala
+++ b/src/library/scala/Option.scala
@@ -125,8 +125,8 @@ sealed abstract class Option[+A] extends Product with Serializable {
* Although the use of null is discouraged, code written to use
* $option must often interface with code that expects and returns nulls.
* @example {{{
- * val initalText: Option[String] = getInitialText
- * val textField = new JComponent(initalText.orNull,20)
+ * val initialText: Option[String] = getInitialText
+ * val textField = new JComponent(initialText.orNull,20)
* }}}
*/
@inline final def orNull[A1 >: A](implicit ev: Null <:< A1): A1 = this getOrElse ev(null)
diff --git a/src/library/scala/collection/GenSeqLike.scala b/src/library/scala/collection/GenSeqLike.scala
index 1c4f233e22..cf1de0c8e6 100644
--- a/src/library/scala/collection/GenSeqLike.scala
+++ b/src/library/scala/collection/GenSeqLike.scala
@@ -397,7 +397,7 @@ trait GenSeqLike[+A, +Repr] extends Any with GenIterableLike[A, Repr] with Equal
* @inheritdoc
*
* Another way to express this
- * is that `xs union ys` computes the order-presevring multi-set union of `xs` and `ys`.
+ * is that `xs union ys` computes the order-preserving multi-set union of `xs` and `ys`.
* `union` is hence a counter-part of `diff` and `intersect` which also work on multi-sets.
*
* $willNotTerminateInf
diff --git a/src/library/scala/collection/IterableLike.scala b/src/library/scala/collection/IterableLike.scala
index 91ab1f6ac2..7643b84a8b 100644
--- a/src/library/scala/collection/IterableLike.scala
+++ b/src/library/scala/collection/IterableLike.scala
@@ -179,6 +179,7 @@ self =>
/** Groups elements in fixed size blocks by passing a "sliding window"
* over them (as opposed to partitioning them, as is done in grouped.)
+ * "Sliding window" step is 1 by default.
* @see [[scala.collection.Iterator]], method `sliding`
*
* @param size the number of elements per group
@@ -194,7 +195,7 @@ self =>
*
* @param size the number of elements per group
* @param step the distance between the first elements of successive
- * groups (defaults to 1)
+ * groups
* @return An iterator producing ${coll}s of size `size`, except the
* last and the only element will be truncated if there are
* fewer elements than size.
diff --git a/src/library/scala/collection/Iterator.scala b/src/library/scala/collection/Iterator.scala
index 20712f918c..0783beac0f 100644
--- a/src/library/scala/collection/Iterator.scala
+++ b/src/library/scala/collection/Iterator.scala
@@ -479,7 +479,7 @@ trait Iterator[+A] extends TraversableOnce[A] {
}
}
- /** Produces a collection containing cummulative results of applying the
+ /** Produces a collection containing cumulative results of applying the
* operator going left to right.
*
* $willNotTerminateInf
@@ -502,8 +502,8 @@ trait Iterator[+A] extends TraversableOnce[A] {
} else Iterator.empty.next()
}
- /** Produces a collection containing cummulative results of applying the operator going right to left.
- * The head of the collection is the last cummulative result.
+ /** Produces a collection containing cumulative results of applying the operator going right to left.
+ * The head of the collection is the last cumulative result.
*
* $willNotTerminateInf
* $orderDependent
diff --git a/src/library/scala/collection/LinearSeqOptimized.scala b/src/library/scala/collection/LinearSeqOptimized.scala
index 64248aa755..9c336e8e31 100755
--- a/src/library/scala/collection/LinearSeqOptimized.scala
+++ b/src/library/scala/collection/LinearSeqOptimized.scala
@@ -44,7 +44,7 @@ trait LinearSeqOptimized[+A, +Repr <: LinearSeqOptimized[A, Repr]] extends Linea
*
* $willNotTerminateInf
*
- * Note: the execution of `length` may take time proportial to the length of the sequence.
+ * Note: the execution of `length` may take time proportional to the length of the sequence.
*/
def length: Int = {
var these = self
@@ -57,7 +57,7 @@ trait LinearSeqOptimized[+A, +Repr <: LinearSeqOptimized[A, Repr]] extends Linea
}
/** Selects an element by its index in the $coll.
- * Note: the execution of `apply` may take time proportial to the index value.
+ * Note: the execution of `apply` may take time proportional to the index value.
* @throws IndexOutOfBoundsException if `idx` does not satisfy `0 <= idx < length`.
*/
def apply(n: Int): A = {
diff --git a/src/library/scala/collection/SeqViewLike.scala b/src/library/scala/collection/SeqViewLike.scala
index ef6d2272cb..59e0e73e89 100644
--- a/src/library/scala/collection/SeqViewLike.scala
+++ b/src/library/scala/collection/SeqViewLike.scala
@@ -55,7 +55,7 @@ trait SeqViewLike[+A,
trait Sliced extends super.Sliced with Transformed[A] {
def length = iterator.size
def apply(idx: Int): A =
- if (idx + from < until) self.apply(idx + from)
+ if (idx >= 0 && idx + from < until) self.apply(idx + from)
else throw new IndexOutOfBoundsException(idx.toString)
override def foreach[U](f: A => U) = iterator foreach f
diff --git a/src/library/scala/collection/immutable/HashSet.scala b/src/library/scala/collection/immutable/HashSet.scala
index e4b7371ed4..f548eac88d 100644
--- a/src/library/scala/collection/immutable/HashSet.scala
+++ b/src/library/scala/collection/immutable/HashSet.scala
@@ -406,7 +406,7 @@ object HashSet extends ImmutableSetFactory[HashSet] {
// create a new HashSet1 with the hash we already know
new HashSet1(ks1.head, hash)
case _ =>
- // create a new HashSetCollison with the hash we already know and the new keys
+ // create a new HashSetCollision with the hash we already know and the new keys
new HashSetCollision1(hash, ks1)
}
}
@@ -426,7 +426,7 @@ object HashSet extends ImmutableSetFactory[HashSet] {
// create a new HashSet1 with the hash we already know
new HashSet1(ks1.head, hash)
case _ =>
- // create a new HashSetCollison with the hash we already know and the new keys
+ // create a new HashSetCollision with the hash we already know and the new keys
new HashSetCollision1(hash, ks1)
}
}
@@ -445,7 +445,7 @@ object HashSet extends ImmutableSetFactory[HashSet] {
// Should only have HSC1 if size > 1
this
case _ =>
- // create a new HashSetCollison with the hash we already know and the new keys
+ // create a new HashSetCollision with the hash we already know and the new keys
new HashSetCollision1(hash, ks1)
}
} else this
diff --git a/src/library/scala/collection/immutable/Stream.scala b/src/library/scala/collection/immutable/Stream.scala
index 09a69b8096..9ed5162061 100644
--- a/src/library/scala/collection/immutable/Stream.scala
+++ b/src/library/scala/collection/immutable/Stream.scala
@@ -944,7 +944,7 @@ self =>
*
* @param p the test predicate.
* @return A new `Stream` representing the results of applying `p` to the
- * oringal `Stream`.
+ * original `Stream`.
*
* @example {{{
* // Assume we have a Stream that takes the first 20 natural numbers
diff --git a/src/library/scala/collection/immutable/StringLike.scala b/src/library/scala/collection/immutable/StringLike.scala
index f0daaf25a5..1ead894faf 100644
--- a/src/library/scala/collection/immutable/StringLike.scala
+++ b/src/library/scala/collection/immutable/StringLike.scala
@@ -10,7 +10,7 @@ package scala
package collection
package immutable
-import mutable.Builder
+import mutable.{ ArrayBuilder, Builder }
import scala.util.matching.Regex
import scala.math.ScalaNumber
import scala.reflect.ClassTag
@@ -203,8 +203,33 @@ self =>
private def escape(ch: Char): String = "\\Q" + ch + "\\E"
- @throws(classOf[java.util.regex.PatternSyntaxException])
- def split(separator: Char): Array[String] = toString.split(escape(separator))
+ def split(separator: Char): Array[String] = {
+ val thisString = toString
+ var pos = thisString.indexOf(separator)
+
+ if (pos != -1) {
+ val res = new ArrayBuilder.ofRef[String]
+
+ var prev = 0
+ do {
+ res += thisString.substring(prev, pos)
+ prev = pos + 1
+ pos = thisString.indexOf(separator, prev)
+ } while (pos != -1)
+
+ if (prev != thisString.size)
+ res += thisString.substring(prev, thisString.size)
+
+ val initialResult = res.result()
+ pos = initialResult.length
+ while (pos > 0 && initialResult(pos - 1).isEmpty) pos = pos - 1
+ if (pos != initialResult.length) {
+ val trimmed = new Array[String](pos)
+ Array.copy(initialResult, 0, trimmed, 0, pos)
+ trimmed
+ } else initialResult
+ } else Array[String](thisString)
+ }
@throws(classOf[java.util.regex.PatternSyntaxException])
def split(separators: Array[Char]): Array[String] = {
diff --git a/src/library/scala/collection/immutable/Vector.scala b/src/library/scala/collection/immutable/Vector.scala
index c7da447f72..47a623a616 100644
--- a/src/library/scala/collection/immutable/Vector.scala
+++ b/src/library/scala/collection/immutable/Vector.scala
@@ -215,7 +215,7 @@ override def companion: GenericCompanion[Vector] = Vector
import Vector.{Log2ConcatFaster, TinyAppendFaster}
if (that.isEmpty) this.asInstanceOf[That]
else {
- val again = if (!that.isTraversableAgain) that.toVector else that
+ val again = if (!that.isTraversableAgain) that.toVector else that.seq
again.size match {
// Often it's better to append small numbers of elements (or prepend if RHS is a vector)
case n if n <= TinyAppendFaster || n < (this.size >> Log2ConcatFaster) =>
diff --git a/src/library/scala/collection/mutable/ArrayBuffer.scala b/src/library/scala/collection/mutable/ArrayBuffer.scala
index 8f77114746..011fd415ee 100644
--- a/src/library/scala/collection/mutable/ArrayBuffer.scala
+++ b/src/library/scala/collection/mutable/ArrayBuffer.scala
@@ -128,7 +128,7 @@ class ArrayBuffer[A](override protected val initialSize: Int)
override def ++=:(xs: TraversableOnce[A]): this.type = { insertAll(0, xs.toTraversable); this }
/** Inserts new elements at the index `n`. Opposed to method
- * `update`, this method will not replace an element with a
+ * `update`, this method will not replace an element with a new
* one. Instead, it will insert a new element at index `n`.
*
* @param n the index where a new element will be inserted.
@@ -137,12 +137,13 @@ class ArrayBuffer[A](override protected val initialSize: Int)
*/
def insertAll(n: Int, seq: Traversable[A]) {
if (n < 0 || n > size0) throw new IndexOutOfBoundsException(n.toString)
- val xs = seq.toList
- val len = xs.length
- ensureSize(size0 + len)
+ val len = seq.size
+ val newSize = size0 + len
+ ensureSize(newSize)
+
copy(n, n + len, size0 - n)
- xs.copyToArray(array.asInstanceOf[scala.Array[Any]], n)
- size0 += len
+ seq.copyToArray(array.asInstanceOf[Array[Any]], n)
+ size0 = newSize
}
/** Removes the element on a given index position. It takes time linear in
diff --git a/src/library/scala/collection/mutable/BitSet.scala b/src/library/scala/collection/mutable/BitSet.scala
index faa4155317..78150b5e88 100644
--- a/src/library/scala/collection/mutable/BitSet.scala
+++ b/src/library/scala/collection/mutable/BitSet.scala
@@ -160,6 +160,9 @@ class BitSet(protected final var elems: Array[Long]) extends AbstractSet[Int]
*
* @return an immutable set containing all the elements of this set.
*/
+ @deprecated("If this BitSet contains a value that is 128 or greater, the result of this method is an 'immutable' " +
+ "BitSet that shares state with this mutable BitSet. Thus, if the mutable BitSet is modified, it will violate the " +
+ "immutability of the result.", "2.11.6")
def toImmutable = immutable.BitSet.fromBitMaskNoCopy(elems)
override def clone(): BitSet = {
diff --git a/src/library/scala/collection/mutable/DoubleLinkedList.scala b/src/library/scala/collection/mutable/DoubleLinkedList.scala
index 671b79f8c2..fd95e74fbc 100644
--- a/src/library/scala/collection/mutable/DoubleLinkedList.scala
+++ b/src/library/scala/collection/mutable/DoubleLinkedList.scala
@@ -41,7 +41,7 @@ import generic._
* @define mayNotTerminateInf
* @define willNotTerminateInf
*/
-@deprecated("Low-level linked lists are deprecated due to idiosyncracies in interface and incomplete features.", "2.11.0")
+@deprecated("Low-level linked lists are deprecated due to idiosyncrasies in interface and incomplete features.", "2.11.0")
@SerialVersionUID(-8144992287952814767L)
class DoubleLinkedList[A]() extends AbstractSeq[A]
with LinearSeq[A]
diff --git a/src/library/scala/collection/mutable/DoubleLinkedListLike.scala b/src/library/scala/collection/mutable/DoubleLinkedListLike.scala
index a43fe34c99..aafe34f50a 100644
--- a/src/library/scala/collection/mutable/DoubleLinkedListLike.scala
+++ b/src/library/scala/collection/mutable/DoubleLinkedListLike.scala
@@ -56,10 +56,10 @@ import scala.annotation.migration
* @define Coll `DoubleLinkedList`
* @define coll double linked list
*/
-@deprecated("Low-level linked lists are deprecated due to idiosyncracies in interface and incomplete features.", "2.11.0")
+@deprecated("Low-level linked lists are deprecated due to idiosyncrasies in interface and incomplete features.", "2.11.0")
trait DoubleLinkedListLike[A, This <: Seq[A] with DoubleLinkedListLike[A, This]] extends SeqLike[A, This] with LinkedListLike[A, This] { self =>
- /** A reference to the node in the linked list preceeding the current node. */
+ /** A reference to the node in the linked list preceding the current node. */
var prev: This = _
// returns that list if this list is empty
diff --git a/src/library/scala/collection/mutable/IndexedSeqView.scala b/src/library/scala/collection/mutable/IndexedSeqView.scala
index 31a4749960..7acdeeff18 100644
--- a/src/library/scala/collection/mutable/IndexedSeqView.scala
+++ b/src/library/scala/collection/mutable/IndexedSeqView.scala
@@ -50,7 +50,7 @@ self =>
trait Sliced extends super.Sliced with Transformed[A] {
override def length = endpoints.width
def update(idx: Int, elem: A) =
- if (idx + from < until) self.update(idx + from, elem)
+ if (idx >= 0 && idx + from < until) self.update(idx + from, elem)
else throw new IndexOutOfBoundsException(idx.toString)
}
diff --git a/src/library/scala/collection/mutable/LinkedHashMap.scala b/src/library/scala/collection/mutable/LinkedHashMap.scala
index b64504be3d..275f490675 100644
--- a/src/library/scala/collection/mutable/LinkedHashMap.scala
+++ b/src/library/scala/collection/mutable/LinkedHashMap.scala
@@ -160,6 +160,7 @@ class LinkedHashMap[A, B] extends AbstractMap[A, B]
override def clear() {
clearTable()
firstEntry = null
+ lastEntry = null
}
private def writeObject(out: java.io.ObjectOutputStream) {
diff --git a/src/library/scala/collection/mutable/LinkedHashSet.scala b/src/library/scala/collection/mutable/LinkedHashSet.scala
index 1768c946ed..756a2f73c1 100644
--- a/src/library/scala/collection/mutable/LinkedHashSet.scala
+++ b/src/library/scala/collection/mutable/LinkedHashSet.scala
@@ -112,6 +112,7 @@ class LinkedHashSet[A] extends AbstractSet[A]
override def clear() {
clearTable()
firstEntry = null
+ lastEntry = null
}
private def writeObject(out: java.io.ObjectOutputStream) {
diff --git a/src/library/scala/collection/mutable/LinkedList.scala b/src/library/scala/collection/mutable/LinkedList.scala
index 092698ac0b..b3500367af 100644
--- a/src/library/scala/collection/mutable/LinkedList.scala
+++ b/src/library/scala/collection/mutable/LinkedList.scala
@@ -76,7 +76,7 @@ import generic._
* }}}
*/
@SerialVersionUID(-7308240733518833071L)
-@deprecated("Low-level linked lists are deprecated due to idiosyncracies in interface and incomplete features.", "2.11.0")
+@deprecated("Low-level linked lists are deprecated due to idiosyncrasies in interface and incomplete features.", "2.11.0")
class LinkedList[A]() extends AbstractSeq[A]
with LinearSeq[A]
with GenericTraversableTemplate[A, LinkedList]
diff --git a/src/library/scala/collection/mutable/LinkedListLike.scala b/src/library/scala/collection/mutable/LinkedListLike.scala
index 987b83d23b..a9d385bc5b 100644
--- a/src/library/scala/collection/mutable/LinkedListLike.scala
+++ b/src/library/scala/collection/mutable/LinkedListLike.scala
@@ -55,7 +55,7 @@ import scala.annotation.tailrec
*
* }}}
*/
-@deprecated("Low-level linked lists are deprecated due to idiosyncracies in interface and incomplete features.", "2.11.0")
+@deprecated("Low-level linked lists are deprecated due to idiosyncrasies in interface and incomplete features.", "2.11.0")
trait LinkedListLike[A, This <: Seq[A] with LinkedListLike[A, This]] extends SeqLike[A, This] { self =>
var elem: A = _
diff --git a/src/library/scala/collection/mutable/LongMap.scala b/src/library/scala/collection/mutable/LongMap.scala
index 5fafe23d9f..c124f35cd7 100644
--- a/src/library/scala/collection/mutable/LongMap.scala
+++ b/src/library/scala/collection/mutable/LongMap.scala
@@ -19,7 +19,7 @@ import generic.CanBuildFrom
* on a map that will no longer have elements removed but will be
* used heavily may save both time and storage space.
*
- * This map is not indended to contain more than 2^29 entries (approximately
+ * This map is not intended to contain more than 2^29 entries (approximately
* 500 million). The maximum capacity is 2^30, but performance will degrade
* rapidly as 2^30 is approached.
*
diff --git a/src/library/scala/collection/mutable/MapLike.scala b/src/library/scala/collection/mutable/MapLike.scala
index 471cd1cdde..af28df1b88 100644
--- a/src/library/scala/collection/mutable/MapLike.scala
+++ b/src/library/scala/collection/mutable/MapLike.scala
@@ -133,7 +133,7 @@ trait MapLike[A, B, +This <: MapLike[A, B, This] with Map[A, B]]
/** Creates a new map containing the key/value mappings provided by the specified traversable object
* and all the key/value mappings of this map.
*
- * Note that existing mappings from this map with the same key as those in `xs` will be overriden.
+ * Note that existing mappings from this map with the same key as those in `xs` will be overridden.
*
* @param xs the traversable object.
* @return a new map containing mappings of this map and those provided by `xs`.
diff --git a/src/library/scala/collection/mutable/MutableList.scala b/src/library/scala/collection/mutable/MutableList.scala
index b852a4747b..646023f469 100644
--- a/src/library/scala/collection/mutable/MutableList.scala
+++ b/src/library/scala/collection/mutable/MutableList.scala
@@ -13,7 +13,6 @@ package mutable
import generic._
import immutable.{List, Nil}
-// !!! todo: convert to LinkedListBuffer?
/**
* This class is used internally to represent mutable lists. It is the
* basis for the implementation of the class `Queue`.
@@ -113,9 +112,21 @@ extends AbstractSeq[A]
}
}
- /** Returns an iterator over all elements of this list.
+ /** Returns an iterator over up to `length` elements of this list.
*/
- override def iterator: Iterator[A] = first0.iterator
+ override def iterator: Iterator[A] = if (isEmpty) Iterator.empty else
+ new AbstractIterator[A] {
+ var elems = first0
+ var count = len
+ def hasNext = count > 0 && elems.nonEmpty
+ def next() = {
+ if (!hasNext) throw new NoSuchElementException
+ count = count - 1
+ val e = elems.elem
+ elems = if (count == 0) null else elems.next
+ e
+ }
+ }
override def last = {
if (isEmpty) throw new NoSuchElementException("MutableList.empty.last")
diff --git a/src/library/scala/collection/mutable/OpenHashMap.scala b/src/library/scala/collection/mutable/OpenHashMap.scala
index aade2ed6fb..24f5761cf5 100644
--- a/src/library/scala/collection/mutable/OpenHashMap.scala
+++ b/src/library/scala/collection/mutable/OpenHashMap.scala
@@ -31,7 +31,7 @@ object OpenHashMap {
/** A mutable hash map based on an open hashing scheme. The precise scheme is
* undefined, but it should make a reasonable effort to ensure that an insert
- * with consecutive hash codes is not unneccessarily penalised. In particular,
+ * with consecutive hash codes is not unnecessarily penalised. In particular,
* mappings of consecutive integer keys should work without significant
* performance loss.
*
diff --git a/src/library/scala/collection/package.scala b/src/library/scala/collection/package.scala
index 26b061b2a5..6a2b6de75a 100644
--- a/src/library/scala/collection/package.scala
+++ b/src/library/scala/collection/package.scala
@@ -18,7 +18,7 @@ package scala
*
* == Using Collections ==
*
- * It is convienient to treat all collections as either
+ * It is convenient to treat all collections as either
* a [[scala.collection.Traversable]] or [[scala.collection.Iterable]], as
* these traits define the vast majority of operations
* on a collection.
diff --git a/src/library/scala/collection/parallel/ParIterableLike.scala b/src/library/scala/collection/parallel/ParIterableLike.scala
index 2b54e05841..016255dca4 100644
--- a/src/library/scala/collection/parallel/ParIterableLike.scala
+++ b/src/library/scala/collection/parallel/ParIterableLike.scala
@@ -744,7 +744,7 @@ self: ParIterableLike[T, Repr, Sequential] =>
* The index flag is initially set to maximum integer value.
*
* @param pred the predicate used to test the elements
- * @return the longest prefix of this $coll of elements that satisy the predicate `pred`
+ * @return the longest prefix of this $coll of elements that satisfy the predicate `pred`
*/
def takeWhile(pred: T => Boolean): Repr = {
val cbf = combinerFactory
diff --git a/src/library/scala/collection/parallel/package.scala b/src/library/scala/collection/parallel/package.scala
index 91c54fa8f1..d77dcb0658 100644
--- a/src/library/scala/collection/parallel/package.scala
+++ b/src/library/scala/collection/parallel/package.scala
@@ -206,7 +206,7 @@ package parallel {
* Methods `beforeCombine` and `afterCombine` are called before and after
* combining the buckets, respectively, given that the argument to `combine`
* is not `this` (as required by the `combine` contract).
- * They can be overriden in subclasses to provide custom behaviour by modifying
+ * They can be overridden in subclasses to provide custom behaviour by modifying
* the receiver (which will be the return value).
*/
private[parallel] abstract class BucketCombiner[-Elem, +To, Buck, +CombinerType <: BucketCombiner[Elem, To, Buck, CombinerType]]
diff --git a/src/library/scala/concurrent/Future.scala b/src/library/scala/concurrent/Future.scala
index e93a3284dc..914646320c 100644
--- a/src/library/scala/concurrent/Future.scala
+++ b/src/library/scala/concurrent/Future.scala
@@ -485,7 +485,7 @@ object Future {
* The result becomes available once the asynchronous computation is completed.
*
* @tparam T the type of the result
- * @param body the asychronous computation
+ * @param body the asynchronous computation
* @param executor the execution context on which the future is run
* @return the `Future` holding the result of the computation
*/
diff --git a/src/library/scala/concurrent/SyncVar.scala b/src/library/scala/concurrent/SyncVar.scala
index 494c955833..9634f6d900 100644
--- a/src/library/scala/concurrent/SyncVar.scala
+++ b/src/library/scala/concurrent/SyncVar.scala
@@ -93,7 +93,7 @@ class SyncVar[A] {
// [Heather] the reason why: it doesn't take into consideration
// whether or not the SyncVar is already defined. So, set has been
// deprecated in order to eventually be able to make "setting" private
- @deprecated("Use `put` instead, as `set` is potentionally error-prone", "2.10.0")
+ @deprecated("Use `put` instead, as `set` is potentially error-prone", "2.10.0")
// NOTE: Used by SBT 0.13.0-M2 and below
def set(x: A): Unit = setVal(x)
@@ -113,7 +113,7 @@ class SyncVar[A] {
// [Heather] the reason why: it doesn't take into consideration
// whether or not the SyncVar is already defined. So, unset has been
// deprecated in order to eventually be able to make "unsetting" private
- @deprecated("Use `take` instead, as `unset` is potentionally error-prone", "2.10.0")
+ @deprecated("Use `take` instead, as `unset` is potentially error-prone", "2.10.0")
// NOTE: Used by SBT 0.13.0-M2 and below
def unset(): Unit = synchronized {
isDefined = false
diff --git a/src/library/scala/concurrent/package.scala b/src/library/scala/concurrent/package.scala
index 4843d28679..d159dda414 100644
--- a/src/library/scala/concurrent/package.scala
+++ b/src/library/scala/concurrent/package.scala
@@ -12,6 +12,75 @@ import scala.concurrent.duration.Duration
import scala.annotation.implicitNotFound
/** This package object contains primitives for concurrent and parallel programming.
+ *
+ * == Guide ==
+ *
+ * A more detailed guide to Futures and Promises, including discussion and examples
+ * can be found at
+ * [[http://docs.scala-lang.org/overviews/core/futures.html]].
+ *
+ * == Common Imports ==
+ *
+ * When working with Futures, you will often find that importing the whole concurrent
+ * package is convenient, furthermore you are likely to need an implicit ExecutionContext
+ * in scope for many operations involving Futures and Promises:
+ *
+ * {{{
+ * import scala.concurrent._
+ * import ExecutionContext.Implicits.global
+ * }}}
+ *
+ * == Specifying Durations ==
+ *
+ * Operations often require a duration to be specified. A duration DSL is available
+ * to make defining these easier:
+ *
+ * {{{
+ * import scala.concurrent.duration._
+ * val d: Duration = 10.seconds
+ * }}}
+ *
+ * == Using Futures For Non-blocking Computation ==
+ *
+ * Basic use of futures is easy with the factory method on Future, which executes a
+ * provided function asynchronously, handing you back a future result of that function
+ * without blocking the current thread. In order to create the Future you will need
+ * either an implicit or explicit ExecutionContext to be provided:
+ *
+ * {{{
+ * import scala.concurrent._
+ * import ExecutionContext.Implicits.global // implicit execution context
+ *
+ * val firstZebra: Future[Int] = Future {
+ * val source = scala.io.Source.fromFile("/etc/dictionaries-common/words")
+ * source.toSeq.indexOfSlice("zebra")
+ * }
+ * }}}
+ *
+ * == Avoid Blocking ==
+ *
+ * Although blocking is possible in order to await results (with a mandatory timeout duration):
+ *
+ * {{{
+ * import scala.concurrent.duration._
+ * Await.result(firstZebra, 10.seconds)
+ * }}}
+ *
+ * and although this is sometimes necessary to do, in particular for testing purposes, blocking
+ * in general is discouraged when working with Futures and concurrency in order to avoid
+ * potential deadlocks and improve performance. Instead, use callbacks or combinators to
+ * remain in the future domain:
+ *
+ * {{{
+ * val animalRange: Future[Int] = for {
+ * aardvark <- firstAardvark
+ * zebra <- firstZebra
+ * } yield zebra - aardvark
+ *
+ * animalRange.onSuccess {
+ * case x if x > 500000 => println("It's a long way from Aardvark to Zebra")
+ * }
+ * }}}
*/
package object concurrent {
type ExecutionException = java.util.concurrent.ExecutionException
@@ -70,6 +139,11 @@ package concurrent {
/**
* `Await` is what is used to ensure proper handling of blocking for `Awaitable` instances.
+ *
+ * While occasionally useful, e.g. for testing, it is recommended that you avoid Await
+ * when possible in favor of callbacks and combinators like onComplete and use in
+ * for comprehensions. Await will block the thread on which it runs, and could cause
+ * performance and deadlock issues.
*/
object Await {
/**
diff --git a/src/library/scala/io/Source.scala b/src/library/scala/io/Source.scala
index 74c3e06839..9f0b56b4fe 100644
--- a/src/library/scala/io/Source.scala
+++ b/src/library/scala/io/Source.scala
@@ -169,9 +169,20 @@ object Source {
createBufferedSource(is, reset = () => fromInputStream(is)(codec), close = () => is.close())(codec)
}
-/** The class `Source` implements an iterable representation of source data.
- * Calling method `reset` returns an identical, resetted source, where
- * possible.
+/** An iterable representation of source data.
+ * It may be reset with the optional `reset` method.
+ *
+ * Subclasses must supply [[scala.io.Source@iter the underlying iterator]].
+ *
+ * Error handling may be customized by overriding the [[scala.io.Source@report report]] method.
+ *
+ * The [[scala.io.Source@ch current input]] and [[scala.io.Source@pos position]],
+ * as well as the [[scala.io.Source@next next character]] methods delegate to
+ * [[scala.io.Source$Positioner the positioner]].
+ *
+ * The default positioner encodes line and column numbers in the position passed to `report`.
+ * This behavior can be changed by supplying a
+ * [[scala.io.Source@withPositioning(pos:Source.this.Positioner):Source.this.type custom positioner]].
*
* @author Burak Emir
* @version 1.0
diff --git a/src/library/scala/io/StdIn.scala b/src/library/scala/io/StdIn.scala
index 64836ecd6e..0f9656436b 100644
--- a/src/library/scala/io/StdIn.scala
+++ b/src/library/scala/io/StdIn.scala
@@ -4,7 +4,7 @@ package io
import java.text.MessageFormat
/** private[scala] because this is not functionality we should be providing
- * in the standard library, at least not in this idiosyncractic form.
+ * in the standard library, at least not in this idiosyncratic form.
* Factored into trait because it is better code structure regardless.
*/
private[scala] trait StdIn {
diff --git a/src/library/scala/language.scala b/src/library/scala/language.scala
index c638f531bb..2eb5514a18 100644
--- a/src/library/scala/language.scala
+++ b/src/library/scala/language.scala
@@ -1,3 +1,13 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2015, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+
+
package scala
/**
diff --git a/src/library/scala/languageFeature.scala b/src/library/scala/languageFeature.scala
index 1f411c412a..51118b43be 100644
--- a/src/library/scala/languageFeature.scala
+++ b/src/library/scala/languageFeature.scala
@@ -1,3 +1,13 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2015, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+
+
package scala
import scala.annotation.meta
diff --git a/src/library/scala/math/BigDecimal.scala b/src/library/scala/math/BigDecimal.scala
index 74a174ea74..cf95f945ba 100644
--- a/src/library/scala/math/BigDecimal.scala
+++ b/src/library/scala/math/BigDecimal.scala
@@ -364,7 +364,7 @@ object BigDecimal {
* to a decimal text representation, and build a `BigDecimal` based on that.
* `BigDecimal.binary` will expand the binary fraction to the requested or default
* precision. `BigDecimal.exact` will expand the binary fraction to the
- * full number of digits, thus producing the exact decimal value corrsponding to
+ * full number of digits, thus producing the exact decimal value corresponding to
* the binary fraction of that floating-point number. `BigDecimal` equality
* matches the decimal expansion of `Double`: `BigDecimal.decimal(0.1) == 0.1`.
* Note that since `0.1f != 0.1`, the same is not true for `Float`. Instead,
diff --git a/src/library/scala/math/Ordering.scala b/src/library/scala/math/Ordering.scala
index 0d7ea8bce2..827cccc77e 100644
--- a/src/library/scala/math/Ordering.scala
+++ b/src/library/scala/math/Ordering.scala
@@ -284,6 +284,9 @@ object Ordering extends LowPriorityOrderingImplicits {
override def gteq(x: Float, y: Float): Boolean = outer.gteq(y, x)
override def lt(x: Float, y: Float): Boolean = outer.lt(y, x)
override def gt(x: Float, y: Float): Boolean = outer.gt(y, x)
+ override def min(x: Float, y: Float): Float = outer.max(x, y)
+ override def max(x: Float, y: Float): Float = outer.min(x, y)
+
}
}
implicit object Float extends FloatOrdering
@@ -309,6 +312,8 @@ object Ordering extends LowPriorityOrderingImplicits {
override def gteq(x: Double, y: Double): Boolean = outer.gteq(y, x)
override def lt(x: Double, y: Double): Boolean = outer.lt(y, x)
override def gt(x: Double, y: Double): Boolean = outer.gt(y, x)
+ override def min(x: Double, y: Double): Double = outer.max(x, y)
+ override def max(x: Double, y: Double): Double = outer.min(x, y)
}
}
implicit object Double extends DoubleOrdering
diff --git a/src/library/scala/runtime/MethodCache.scala b/src/library/scala/runtime/MethodCache.scala
index 2d5f832e1f..a8fdfc1059 100644
--- a/src/library/scala/runtime/MethodCache.scala
+++ b/src/library/scala/runtime/MethodCache.scala
@@ -16,7 +16,7 @@ import java.lang.{ Class => JClass }
import scala.annotation.tailrec
/** An element of a polymorphic object cache.
- * This class is refered to by the `CleanUp` phase. Each `PolyMethodCache` chain
+ * This class is referred to by the `CleanUp` phase. Each `PolyMethodCache` chain
* must only relate to one method as `PolyMethodCache` does not identify
* the method name and argument types. In practice, one variable will be
* generated per call point, and will uniquely relate to the method called
diff --git a/src/library/scala/runtime/ScalaRunTime.scala b/src/library/scala/runtime/ScalaRunTime.scala
index f50059ce54..18fcbf8276 100644
--- a/src/library/scala/runtime/ScalaRunTime.scala
+++ b/src/library/scala/runtime/ScalaRunTime.scala
@@ -251,7 +251,7 @@ object ScalaRunTime {
*
* The primary motivation for this method is to provide a means for
* correctly obtaining a String representation of a value, while
- * avoiding the pitfalls of naïvely calling toString on said value.
+ * avoiding the pitfalls of naively calling toString on said value.
* In particular, it addresses the fact that (a) toString cannot be
* called on null and (b) depending on the apparent type of an
* array, toString may or may not print it in a human-readable form.
diff --git a/src/library/scala/sys/process/package.scala b/src/library/scala/sys/process/package.scala
index 1340a6c415..b1976ad4b6 100644
--- a/src/library/scala/sys/process/package.scala
+++ b/src/library/scala/sys/process/package.scala
@@ -119,7 +119,7 @@ package scala.sys {
* ==Handling Input and Output==
*
* In the underlying Java model, once a `Process` has been started, one can
- * get `java.io.InputStream` and `java.io.OutpuStream` representing its
+ * get `java.io.InputStream` and `java.io.OutputStream` representing its
* output and input respectively. That is, what one writes to an
* `OutputStream` is turned into input to the process, and the output of a
* process can be read from an `InputStream` -- of which there are two, one
diff --git a/src/manual/scala/man1/Command.scala b/src/manual/scala/man1/Command.scala
index 1cf55cb28d..8f811f950e 100644
--- a/src/manual/scala/man1/Command.scala
+++ b/src/manual/scala/man1/Command.scala
@@ -47,7 +47,7 @@ trait Command {
def copyright = Section("COPYRIGHT",
"This is open-source software, available to you under a BSD-like license. " &
- "See accomponying \"copyright\" or \"LICENSE\" file for copying conditions. " &
+ "See accompanying \"copyright\" or \"LICENSE\" file for copying conditions. " &
"There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A " &
"PARTICULAR PURPOSE.")
diff --git a/src/manual/scala/man1/scalac.scala b/src/manual/scala/man1/scalac.scala
index 31d25d4801..3954ed588e 100644
--- a/src/manual/scala/man1/scalac.scala
+++ b/src/manual/scala/man1/scalac.scala
@@ -360,7 +360,7 @@ object scalac extends Command {
"ANF pre-transform for " & MItalic("@cps") & " (CPS plugin)"),
Definition(
MItalic("selectivecps"),
- MItalic("@cps") & "-driven transform of selectiveanf assignements (CPS plugin)"),
+ MItalic("@cps") & "-driven transform of selectiveanf assignments (CPS plugin)"),
Definition(
MItalic("uncurry"),
"uncurry, translate function values to anonymous classes"),
diff --git a/src/partest-extras/scala/tools/partest/BytecodeTest.scala b/src/partest-extras/scala/tools/partest/BytecodeTest.scala
index 37ef4684ef..8459419fa5 100644
--- a/src/partest-extras/scala/tools/partest/BytecodeTest.scala
+++ b/src/partest-extras/scala/tools/partest/BytecodeTest.scala
@@ -136,7 +136,7 @@ abstract class BytecodeTest {
object BytecodeTest {
/** Parse `file` as a class file, transforms the ASM representation with `f`,
- * and overwrites the orginal file.
+ * and overwrites the original file.
*/
def modifyClassFile(file: JFile)(f: ClassNode => ClassNode) {
val rfile = new reflect.io.File(file)
diff --git a/src/partest-extras/scala/tools/partest/instrumented/Profiler.java b/src/partest-extras/scala/tools/partest/instrumented/Profiler.java
index d6b62e1d9e..848103f5cc 100644
--- a/src/partest-extras/scala/tools/partest/instrumented/Profiler.java
+++ b/src/partest-extras/scala/tools/partest/instrumented/Profiler.java
@@ -12,7 +12,7 @@ import java.util.Map;
* A simple profiler class that counts method invocations. It is being used in byte-code instrumentation by inserting
* call to {@link Profiler#methodCalled(String, String, String)} at the beginning of every instrumented class.
*
- * WARANING: This class is INTERNAL implementation detail and should never be used directly. It's made public only
+ * WARNING: This class is INTERNAL implementation detail and should never be used directly. It's made public only
* because it must be universally accessible for instrumentation needs. If you want to profile your test use
* {@link Instrumentation} instead.
*/
diff --git a/src/reflect/scala/reflect/api/Liftables.scala b/src/reflect/scala/reflect/api/Liftables.scala
index 673dbce6f5..c6352905d1 100644
--- a/src/reflect/scala/reflect/api/Liftables.scala
+++ b/src/reflect/scala/reflect/api/Liftables.scala
@@ -52,7 +52,7 @@ trait Liftables { self: Universe =>
object Unliftable extends StandardUnliftableInstances {
/** A helper method that simplifies creation of `Unliftable` instances.
* Takes a partial function which is defined on correct representations of `T`
- * and returns corresponing instances.
+ * and returns corresponding instances.
*
* For example to extract a reference to an object as object itself:
*
diff --git a/src/reflect/scala/reflect/api/Mirrors.scala b/src/reflect/scala/reflect/api/Mirrors.scala
index 773c6b6fb4..adaf829b32 100644
--- a/src/reflect/scala/reflect/api/Mirrors.scala
+++ b/src/reflect/scala/reflect/api/Mirrors.scala
@@ -338,7 +338,7 @@ trait Mirrors { self: Universe =>
* with getting a field or invoking a getter method of the field.
*
* If `symbol` represents a field of a base class with respect to the class of the receiver,
- * and this base field is overriden in the class of the receiver, then this method will retrieve
+ * and this base field is overridden in the class of the receiver, then this method will retrieve
* the value of the base field. To achieve overriding behavior, use reflectMethod on an accessor.
*/
def get: Any
@@ -352,7 +352,7 @@ trait Mirrors { self: Universe =>
* with setting a field or invoking a setter method of the field.
*
* If `symbol` represents a field of a base class with respect to the class of the receiver,
- * and this base field is overriden in the class of the receiver, then this method will set
+ * and this base field is overridden in the class of the receiver, then this method will set
* the value of the base field. To achieve overriding behavior, use reflectMethod on an accessor.
*/
def set(value: Any): Unit
diff --git a/src/reflect/scala/reflect/api/Names.scala b/src/reflect/scala/reflect/api/Names.scala
index 03f7b2d218..472da60338 100644
--- a/src/reflect/scala/reflect/api/Names.scala
+++ b/src/reflect/scala/reflect/api/Names.scala
@@ -72,10 +72,10 @@ trait Names {
* @group API
*/
abstract class NameApi {
- /** Checks wether the name is a term name */
+ /** Checks whether the name is a term name */
def isTermName: Boolean
- /** Checks wether the name is a type name */
+ /** Checks whether the name is a type name */
def isTypeName: Boolean
/** Returns a term name that wraps the same string as `this` */
diff --git a/src/reflect/scala/reflect/api/Symbols.scala b/src/reflect/scala/reflect/api/Symbols.scala
index 18d185067e..c01029d067 100644
--- a/src/reflect/scala/reflect/api/Symbols.scala
+++ b/src/reflect/scala/reflect/api/Symbols.scala
@@ -339,7 +339,7 @@ trait Symbols { self: Universe =>
@deprecated("Use `overrides` instead", "2.11.0")
def allOverriddenSymbols: List[Symbol]
- /** Returns all symbols overriden by this symbol.
+ /** Returns all symbols overridden by this symbol.
*
* @group Basics
*/
diff --git a/src/reflect/scala/reflect/api/Trees.scala b/src/reflect/scala/reflect/api/Trees.scala
index aeaa38c317..9ecd87c17e 100644
--- a/src/reflect/scala/reflect/api/Trees.scala
+++ b/src/reflect/scala/reflect/api/Trees.scala
@@ -158,7 +158,7 @@ trait Trees { self: Universe =>
/** Do all parts of this tree satisfy predicate `p`? */
def forAll(p: Tree => Boolean): Boolean
- /** Tests whether two trees are structurall equal.
+ /** Tests whether two trees are structurally equal.
* Note that `==` on trees is reference equality.
*/
def equalsStructure(that : Tree): Boolean
diff --git a/src/reflect/scala/reflect/internal/BaseTypeSeqs.scala b/src/reflect/scala/reflect/internal/BaseTypeSeqs.scala
index 0ca8611719..54f64153c1 100644
--- a/src/reflect/scala/reflect/internal/BaseTypeSeqs.scala
+++ b/src/reflect/scala/reflect/internal/BaseTypeSeqs.scala
@@ -144,7 +144,7 @@ trait BaseTypeSeqs {
"\n --- because ---\n"+msg)
}
- /** A merker object for a base type sequence that's no yet computed.
+ /** A marker object for a base type sequence that's no yet computed.
* used to catch inheritance cycles
*/
val undetBaseTypeSeq: BaseTypeSeq = newBaseTypeSeq(List(), Array())
@@ -152,7 +152,7 @@ trait BaseTypeSeqs {
/** Create a base type sequence consisting of a single type */
def baseTypeSingletonSeq(tp: Type): BaseTypeSeq = newBaseTypeSeq(List(), Array(tp))
- /** Create the base type sequence of a compound type wuth given tp.parents */
+ /** Create the base type sequence of a compound type with given tp.parents */
def compoundBaseTypeSeq(tp: Type): BaseTypeSeq = {
val tsym = tp.typeSymbol
val parents = tp.parents
diff --git a/src/reflect/scala/reflect/internal/Definitions.scala b/src/reflect/scala/reflect/internal/Definitions.scala
index 7e2d124486..9f4ec3e6d1 100644
--- a/src/reflect/scala/reflect/internal/Definitions.scala
+++ b/src/reflect/scala/reflect/internal/Definitions.scala
@@ -514,6 +514,8 @@ trait Definitions extends api.StandardDefinitions {
lazy val ScalaSignatureAnnotation = requiredClass[scala.reflect.ScalaSignature]
lazy val ScalaLongSignatureAnnotation = requiredClass[scala.reflect.ScalaLongSignature]
+ lazy val MethodHandle = getClassIfDefined("java.lang.invoke.MethodHandle")
+
// Option classes
lazy val OptionClass: ClassSymbol = requiredClass[Option[_]]
lazy val OptionModule: ModuleSymbol = requiredModule[scala.Option.type]
@@ -931,7 +933,7 @@ trait Definitions extends api.StandardDefinitions {
// members of class scala.Any
- // TODO these aren't final! They are now overriden in AnyRef/Object. Prior to the fix
+ // TODO these aren't final! They are now overridden in AnyRef/Object. Prior to the fix
// for SI-8129, they were actually *overloaded* by the members in AnyRef/Object.
// We should unfinalize these, override in AnyValClass, and make the overrides final.
// Refchecks never actually looks at these, so its just for consistency.
@@ -1508,6 +1510,9 @@ trait Definitions extends api.StandardDefinitions {
lazy val PartialManifestClass = getTypeMember(ReflectPackage, tpnme.ClassManifest)
lazy val ManifestSymbols = Set[Symbol](PartialManifestClass, FullManifestClass, OptManifestClass)
+
+ def isPolymorphicSignature(sym: Symbol) = PolySigMethods(sym)
+ private lazy val PolySigMethods: Set[Symbol] = Set[Symbol](MethodHandle.info.decl(sn.Invoke), MethodHandle.info.decl(sn.InvokeExact)).filter(_.exists)
}
}
}
diff --git a/src/reflect/scala/reflect/internal/Mirrors.scala b/src/reflect/scala/reflect/internal/Mirrors.scala
index 4a35e024de..0cbb976a98 100644
--- a/src/reflect/scala/reflect/internal/Mirrors.scala
+++ b/src/reflect/scala/reflect/internal/Mirrors.scala
@@ -277,7 +277,7 @@ trait Mirrors extends api.Mirrors {
// TODO - having these as objects means they elude the attempt to
// add synchronization in SynchronizedSymbols. But we should either
- // flip on object overrides or find some other accomodation, because
+ // flip on object overrides or find some other accommodation, because
// lazy vals are unnecessarily expensive relative to objects and it
// is very beneficial for a handful of bootstrap symbols to have
// first class identities
diff --git a/src/reflect/scala/reflect/internal/Names.scala b/src/reflect/scala/reflect/internal/Names.scala
index b50f324074..32d12d305e 100644
--- a/src/reflect/scala/reflect/internal/Names.scala
+++ b/src/reflect/scala/reflect/internal/Names.scala
@@ -131,11 +131,11 @@ trait Names extends api.Names {
newTermName(cs, offset, len, cachedString).toTypeName
/** Create a term name from string. */
- @deprecatedOverriding("To synchronize, use `override def synchronizeNames = true`", "2.11.0") // overriden in https://github.com/scala-ide/scala-ide/blob/master/org.scala-ide.sdt.core/src/scala/tools/eclipse/ScalaPresentationCompiler.scala
+ @deprecatedOverriding("To synchronize, use `override def synchronizeNames = true`", "2.11.0") // overridden in https://github.com/scala-ide/scala-ide/blob/master/org.scala-ide.sdt.core/src/scala/tools/eclipse/ScalaPresentationCompiler.scala
def newTermName(s: String): TermName = newTermName(s.toCharArray(), 0, s.length(), null)
/** Create a type name from string. */
- @deprecatedOverriding("To synchronize, use `override def synchronizeNames = true`", "2.11.0") // overriden in https://github.com/scala-ide/scala-ide/blob/master/org.scala-ide.sdt.core/src/scala/tools/eclipse/ScalaPresentationCompiler.scala
+ @deprecatedOverriding("To synchronize, use `override def synchronizeNames = true`", "2.11.0") // overridden in https://github.com/scala-ide/scala-ide/blob/master/org.scala-ide.sdt.core/src/scala/tools/eclipse/ScalaPresentationCompiler.scala
def newTypeName(s: String): TypeName = newTermName(s).toTypeName
/** Create a term name from the UTF8 encoded bytes in bs[offset..offset+len-1]. */
diff --git a/src/reflect/scala/reflect/internal/Positions.scala b/src/reflect/scala/reflect/internal/Positions.scala
index c16d8778d9..4d0e31b037 100644
--- a/src/reflect/scala/reflect/internal/Positions.scala
+++ b/src/reflect/scala/reflect/internal/Positions.scala
@@ -204,7 +204,7 @@ trait Positions extends api.Positions { self: SymbolTable =>
/** Set position of all children of a node
* @param pos A target position.
* Uses the point of the position as the point of all positions it assigns.
- * Uses the start of this position as an Offset position for unpositioed trees
+ * Uses the start of this position as an Offset position for unpositioned trees
* without children.
* @param trees The children to position. All children must be positionable.
*/
diff --git a/src/reflect/scala/reflect/internal/Printers.scala b/src/reflect/scala/reflect/internal/Printers.scala
index c4953b2c1f..98b2c48379 100644
--- a/src/reflect/scala/reflect/internal/Printers.scala
+++ b/src/reflect/scala/reflect/internal/Printers.scala
@@ -546,10 +546,11 @@ trait Printers extends api.Printers { self: SymbolTable =>
import Chars._
val decName = name.decoded
val bslash = '\\'
+ val isDot = (x: Char) => x == '.'
val brackets = List('[',']','(',')','{','}')
def addBackquotes(s: String) =
- if (decoded && (decName.exists(ch => brackets.contains(ch) || isWhitespace(ch)) ||
+ if (decoded && (decName.exists(ch => brackets.contains(ch) || isWhitespace(ch) || isDot(ch)) ||
(name.isOperatorName && decName.exists(isOperatorPart) && decName.exists(isScalaLetter) && !decName.contains(bslash))))
s"`$s`" else s
diff --git a/src/reflect/scala/reflect/internal/StdAttachments.scala b/src/reflect/scala/reflect/internal/StdAttachments.scala
index 614e71b597..cca33253be 100644
--- a/src/reflect/scala/reflect/internal/StdAttachments.scala
+++ b/src/reflect/scala/reflect/internal/StdAttachments.scala
@@ -27,7 +27,7 @@ trait StdAttachments {
def importAttachment(importer: Importer): this.type
}
- /** Attachment that doesn't contain any reflection artificats and can be imported as-is. */
+ /** Attachment that doesn't contain any reflection artifacts and can be imported as-is. */
trait PlainAttachment extends ImportableAttachment {
def importAttachment(importer: Importer): this.type = this
}
@@ -42,7 +42,7 @@ trait StdAttachments {
*/
case object BackquotedIdentifierAttachment extends PlainAttachment
- /** Identifies trees are either result or intermidiate value of for loop desugaring.
+ /** Identifies trees are either result or intermediate value of for loop desugaring.
*/
case object ForAttachment extends PlainAttachment
diff --git a/src/reflect/scala/reflect/internal/StdNames.scala b/src/reflect/scala/reflect/internal/StdNames.scala
index 667ff7c4b4..c94ee996e4 100644
--- a/src/reflect/scala/reflect/internal/StdNames.scala
+++ b/src/reflect/scala/reflect/internal/StdNames.scala
@@ -1147,6 +1147,7 @@ trait StdNames {
final val GetClassLoader: TermName = newTermName("getClassLoader")
final val GetMethod: TermName = newTermName("getMethod")
final val Invoke: TermName = newTermName("invoke")
+ final val InvokeExact: TermName = newTermName("invokeExact")
val Boxed = immutable.Map[TypeName, TypeName](
tpnme.Boolean -> BoxedBoolean,
diff --git a/src/reflect/scala/reflect/internal/Symbols.scala b/src/reflect/scala/reflect/internal/Symbols.scala
index 8e86e6fad9..d5fc52abbf 100644
--- a/src/reflect/scala/reflect/internal/Symbols.scala
+++ b/src/reflect/scala/reflect/internal/Symbols.scala
@@ -682,7 +682,7 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
* to fix the core of the compiler risk stability a few weeks before the final release.
* upd. Haha, "a few weeks before the final release". This surely sounds familiar :)
*
- * However we do need to fix this for runtime reflection, since this idionsynchrazy is not something
+ * However we do need to fix this for runtime reflection, since this idiosyncrasy is not something
* we'd like to expose to reflection users. Therefore a proposed solution is to check whether we're in a
* runtime reflection universe, and if yes and if we've not yet loaded the requested info, then to commence initialization.
*/
@@ -740,7 +740,7 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
*
* Note: the lateMETHOD flag is added lazily in the info transformer of the RefChecks phase.
* This means that forcing the `sym.info` may change the value of `sym.isMethod`. Forcing the
- * info is in the responsability of the caller. Doing it eagerly here was tried (0ccdb151f) but
+ * info is in the responsibility of the caller. Doing it eagerly here was tried (0ccdb151f) but
* has proven to lead to bugs (SI-8907).
*
* Here's an example where one can see all four of FF FT TF TT for (isStatic, isMethod) at
@@ -2054,7 +2054,11 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
* where it is the outer class of the enclosing class.
*/
final def outerClass: Symbol =
- if (owner.isClass) owner
+ if (this == NoSymbol) {
+ // ideally we shouldn't get here, but its better to harden against this than suffer the infinite loop in SI-9133
+ devWarningDumpStack("NoSymbol.outerClass", 15)
+ NoSymbol
+ } else if (owner.isClass) owner
else if (isClassLocalToConstructor) owner.enclClass.outerClass
else owner.outerClass
@@ -2812,7 +2816,7 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
override def outerSource: Symbol =
// SI-6888 Approximate the name to workaround the deficiencies in `nme.originalName`
- // in the face of clases named '$'. SI-2806 remains open to address the deeper problem.
+ // in the face of classes named '$'. SI-2806 remains open to address the deeper problem.
if (originalName endsWith (nme.OUTER)) initialize.referenced
else NoSymbol
@@ -3570,7 +3574,7 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
* @param syms the prototypical symbols
* @param symFn the function to create new symbols
* @param tpe the prototypical type
- * @return the new symbol-subsituted type
+ * @return the new symbol-substituted type
*/
def deriveType(syms: List[Symbol], symFn: Symbol => Symbol)(tpe: Type): Type = {
val syms1 = deriveSymbols(syms, symFn)
@@ -3585,7 +3589,7 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
* @param as arguments to be passed to symFn together with symbols from syms (must be same length)
* @param symFn the function to create new symbols based on `as`
* @param tpe the prototypical type
- * @return the new symbol-subsituted type
+ * @return the new symbol-substituted type
*/
def deriveType2[A](syms: List[Symbol], as: List[A], symFn: (Symbol, A) => Symbol)(tpe: Type): Type = {
val syms1 = deriveSymbols2(syms, as, symFn)
diff --git a/src/reflect/scala/reflect/internal/TreeGen.scala b/src/reflect/scala/reflect/internal/TreeGen.scala
index 6e8e992d16..b3e11a826e 100644
--- a/src/reflect/scala/reflect/internal/TreeGen.scala
+++ b/src/reflect/scala/reflect/internal/TreeGen.scala
@@ -713,7 +713,7 @@ abstract class TreeGen {
val rhsUnchecked = mkUnchecked(rhs)
- // TODO: clean this up -- there is too much information packked into mkPatDef's `pat` argument
+ // TODO: clean this up -- there is too much information packed into mkPatDef's `pat` argument
// when it's a simple identifier (case Some((name, tpt)) -- above),
// pat should have the type ascription that was specified by the user
// however, in `case None` (here), we must be careful not to generate illegal pattern trees (such as `(a, b): Tuple2[Int, String]`)
diff --git a/src/reflect/scala/reflect/internal/TreeInfo.scala b/src/reflect/scala/reflect/internal/TreeInfo.scala
index c521277f69..4657fa0000 100644
--- a/src/reflect/scala/reflect/internal/TreeInfo.scala
+++ b/src/reflect/scala/reflect/internal/TreeInfo.scala
@@ -588,7 +588,7 @@ abstract class TreeInfo {
private def hasNoSymbol(t: Tree) = t.symbol == null || t.symbol == NoSymbol
- /** Is this pattern node a synthetic catch-all case, added during PartialFuction synthesis before we know
+ /** Is this pattern node a synthetic catch-all case, added during PartialFunction synthesis before we know
* whether the user provided cases are exhaustive. */
def isSyntheticDefaultCase(cdef: CaseDef) = cdef match {
case CaseDef(Bind(nme.DEFAULT_CASE, _), EmptyTree, _) => true
@@ -815,7 +815,7 @@ abstract class TreeInfo {
object Unapplied {
// Duplicated with `spliceApply`
def unapply(tree: Tree): Option[Tree] = tree match {
- // SI-7868 Admit Select() to account for numeric widening, e.g. <unappplySelector>.toInt
+ // SI-7868 Admit Select() to account for numeric widening, e.g. <unapplySelector>.toInt
case Apply(fun, (Ident(nme.SELECTOR_DUMMY)| Select(Ident(nme.SELECTOR_DUMMY), _)) :: Nil)
=> Some(fun)
case Apply(fun, _) => unapply(fun)
diff --git a/src/reflect/scala/reflect/internal/Trees.scala b/src/reflect/scala/reflect/internal/Trees.scala
index 35de3adff6..fd918b8595 100644
--- a/src/reflect/scala/reflect/internal/Trees.scala
+++ b/src/reflect/scala/reflect/internal/Trees.scala
@@ -1576,6 +1576,7 @@ trait Trees extends api.Trees {
*/
class TreeSymSubstituter(from: List[Symbol], to: List[Symbol]) extends Transformer {
val symSubst = new SubstSymMap(from, to)
+ private var mutatedSymbols: List[Symbol] = Nil
override def transform(tree: Tree): Tree = {
def subst(from: List[Symbol], to: List[Symbol]) {
if (!from.isEmpty)
@@ -1594,6 +1595,7 @@ trait Trees extends api.Trees {
|TreeSymSubstituter: updated info of symbol ${tree.symbol}
| Old: ${showRaw(tree.symbol.info, printTypes = true, printIds = true)}
| New: ${showRaw(newInfo, printTypes = true, printIds = true)}""")
+ mutatedSymbols ::= tree.symbol
tree.symbol updateInfo newInfo
}
case _ =>
@@ -1613,7 +1615,23 @@ trait Trees extends api.Trees {
} else
super.transform(tree)
}
- def apply[T <: Tree](tree: T): T = transform(tree).asInstanceOf[T]
+ def apply[T <: Tree](tree: T): T = {
+ val tree1 = transform(tree)
+ invalidateSingleTypeCaches(tree1)
+ tree1.asInstanceOf[T]
+ }
+ private def invalidateSingleTypeCaches(tree: Tree): Unit = {
+ if (mutatedSymbols.nonEmpty)
+ for (t <- tree if t.tpe != null)
+ for (tp <- t.tpe) {
+ tp match {
+ case s: SingleType if mutatedSymbols contains s.sym =>
+ s.underlyingPeriod = NoPeriod
+ s.underlyingCache = NoType
+ case _ =>
+ }
+ }
+ }
override def toString() = "TreeSymSubstituter/" + substituterString("Symbol", "Symbol", from, to)
}
diff --git a/src/reflect/scala/reflect/internal/Types.scala b/src/reflect/scala/reflect/internal/Types.scala
index a95f626a0b..ce36f7efa3 100644
--- a/src/reflect/scala/reflect/internal/Types.scala
+++ b/src/reflect/scala/reflect/internal/Types.scala
@@ -731,7 +731,7 @@ trait Types
* `substThis(from, to).substSym(symsFrom, symsTo)`.
*
* `SubstThisAndSymMap` performs a breadth-first map over this type, which meant that
- * symbol substitution occured before `ThisType` substitution. Consequently, in substitution
+ * symbol substitution occurred before `ThisType` substitution. Consequently, in substitution
* of a `SingleType(ThisType(`from`), sym), symbols were rebound to `from` rather than `to`.
*/
def substThisAndSym(from: Symbol, to: Type, symsFrom: List[Symbol], symsTo: List[Symbol]): Type =
@@ -1687,7 +1687,7 @@ trait Types
*/
private var refs: Array[RefMap] = _
- /** The initialization state of the class: UnInialized --> Initializing --> Initialized
+ /** The initialization state of the class: UnInitialized --> Initializing --> Initialized
* Syncnote: This var need not be protected with synchronized, because
* it is accessed only from expansiveRefs, which is called only from
* Typer.
@@ -1972,7 +1972,7 @@ trait Types
require(sym.isNonClassType, sym)
/* Syncnote: These are pure caches for performance; no problem to evaluate these
- * several times. Hence, no need to protected with synchronzied in a mutli-threaded
+ * several times. Hence, no need to protected with synchronized in a multi-threaded
* usage scenario.
*/
private var relativeInfoCache: Type = _
@@ -2643,7 +2643,7 @@ trait Types
* nowhere inside a type argument
* - no quantified type argument contains a quantified variable in its bound
* - the typeref's symbol is not itself quantified
- * - the prefix is not quanitified
+ * - the prefix is not quantified
*/
def isRepresentableWithWildcards = {
val qset = quantified.toSet
@@ -3101,7 +3101,7 @@ trait Types
// addressed here: all lower bounds are retained and their intersection calculated when the
// bounds are solved.
//
- // In a side-effect free universe, checking tp and tp.parents beofre checking tp.baseTypeSeq
+ // In a side-effect free universe, checking tp and tp.parents before checking tp.baseTypeSeq
// would be pointless. In this case, each check we perform causes us to lose specificity: in
// the end the best we'll do is the least specific type we tested against, since the typevar
// does not see these checks as "probes" but as requirements to fulfill.
@@ -3332,7 +3332,7 @@ trait Types
*
* SI-6385 Erasure's creation of bridges considers method signatures `exitingErasure`,
* which contain `ErasedValueType`-s. In order to correctly consider the overriding
- * and overriden signatures as equivalent in `run/t6385.scala`, it is critical that
+ * and overridden signatures as equivalent in `run/t6385.scala`, it is critical that
* this type contains the erasure of the wrapped type, rather than the unerased type
* of the value class itself, as was originally done.
*
diff --git a/src/reflect/scala/reflect/internal/Variances.scala b/src/reflect/scala/reflect/internal/Variances.scala
index 12b765b7a6..ef22df3f2e 100644
--- a/src/reflect/scala/reflect/internal/Variances.scala
+++ b/src/reflect/scala/reflect/internal/Variances.scala
@@ -32,7 +32,7 @@ trait Variances {
/** Is every symbol in the owner chain between `site` and the owner of `sym`
* either a term symbol or private[this]? If not, add `sym` to the set of
- * esacped locals.
+ * escaped locals.
* @pre sym.isLocalToThis
*/
@tailrec final def checkForEscape(sym: Symbol, site: Symbol) {
diff --git a/src/reflect/scala/reflect/internal/annotations/uncheckedBounds.scala b/src/reflect/scala/reflect/internal/annotations/uncheckedBounds.scala
index a44bb54734..662d841c91 100644
--- a/src/reflect/scala/reflect/internal/annotations/uncheckedBounds.scala
+++ b/src/reflect/scala/reflect/internal/annotations/uncheckedBounds.scala
@@ -5,7 +5,7 @@ package annotations
/**
* An annotation that designates the annotated type should not be checked for violations of
* type parameter bounds in the `refchecks` phase of the compiler. This can be used by synthesized
- * code the uses an inferred type of an expression as the type of an artifict val/def (for example,
+ * code the uses an inferred type of an expression as the type of an artifact val/def (for example,
* a temporary value introduced by an ANF transform). See [[https://issues.scala-lang.org/browse/SI-7694]].
*
* @since 2.10.3
diff --git a/src/reflect/scala/reflect/internal/pickling/ByteCodecs.scala b/src/reflect/scala/reflect/internal/pickling/ByteCodecs.scala
index 8615e34fad..241638e88e 100644
--- a/src/reflect/scala/reflect/internal/pickling/ByteCodecs.scala
+++ b/src/reflect/scala/reflect/internal/pickling/ByteCodecs.scala
@@ -196,10 +196,10 @@ object ByteCodecs {
*
* Sometimes returns (length+1) of the decoded array. Example:
*
- * scala> val enc = scala.reflect.generic.ByteCodecs.encode(Array(1,2,3))
+ * scala> val enc = scala.reflect.internal.pickling.ByteCodecs.encode(Array(1,2,3))
* enc: Array[Byte] = Array(2, 5, 13, 1)
*
- * scala> scala.reflect.generic.ByteCodecs.decode(enc)
+ * scala> scala.reflect.internal.pickling.ByteCodecs.decode(enc)
* res43: Int = 4
*
* scala> enc
diff --git a/src/reflect/scala/reflect/internal/tpe/FindMembers.scala b/src/reflect/scala/reflect/internal/tpe/FindMembers.scala
index de54f3768e..42b13944f6 100644
--- a/src/reflect/scala/reflect/internal/tpe/FindMembers.scala
+++ b/src/reflect/scala/reflect/internal/tpe/FindMembers.scala
@@ -12,7 +12,7 @@ import TypesStats._
trait FindMembers {
this: SymbolTable =>
- /** Implementatation of `Type#{findMember, findMembers}` */
+ /** Implementation of `Type#{findMember, findMembers}` */
private[internal] abstract class FindMemberBase[T](tpe: Type, name: Name, excludedFlags: Long, requiredFlags: Long) {
protected val initBaseClasses: List[Symbol] = tpe.baseClasses
diff --git a/src/reflect/scala/reflect/internal/tpe/TypeConstraints.scala b/src/reflect/scala/reflect/internal/tpe/TypeConstraints.scala
index c1c43178e5..f79099213a 100644
--- a/src/reflect/scala/reflect/internal/tpe/TypeConstraints.scala
+++ b/src/reflect/scala/reflect/internal/tpe/TypeConstraints.scala
@@ -75,7 +75,7 @@ private[internal] trait TypeConstraints {
/* Syncnote: Type constraints are assumed to be used from only one
* thread. They are not exposed in api.Types and are used only locally
* in operations that are exposed from types. Hence, no syncing of any
- * variables should be ncessesary.
+ * variables should be necessary.
*/
/** Guard these lists against AnyClass and NothingClass appearing,
diff --git a/src/reflect/scala/reflect/internal/util/WeakHashSet.scala b/src/reflect/scala/reflect/internal/util/WeakHashSet.scala
index a9a7c7780d..3a7a7626fb 100644
--- a/src/reflect/scala/reflect/internal/util/WeakHashSet.scala
+++ b/src/reflect/scala/reflect/internal/util/WeakHashSet.scala
@@ -7,13 +7,13 @@ import scala.collection.generic.Clearable
import scala.collection.mutable.{Set => MSet}
/**
- * A HashSet where the elements are stored weakly. Elements in this set are elligible for GC if no other
+ * A HashSet where the elements are stored weakly. Elements in this set are eligible for GC if no other
* hard references are associated with them. Its primary use case is as a canonical reference
* identity holder (aka "hash-consing") via findEntryOrUpdate
*
* This Set implementation cannot hold null. Any attempt to put a null in it will result in a NullPointerException
*
- * This set implmeentation is not in general thread safe without external concurrency control. However it behaves
+ * This set implementation is not in general thread safe without external concurrency control. However it behaves
* properly when GC concurrently collects elements in this set.
*/
final class WeakHashSet[A <: AnyRef](val initialCapacity: Int, val loadFactor: Double) extends Set[A] with Function1[A, Boolean] with MSet[A] {
@@ -26,7 +26,7 @@ final class WeakHashSet[A <: AnyRef](val initialCapacity: Int, val loadFactor: D
/**
* queue of Entries that hold elements scheduled for GC
- * the removeStaleEntries() method works through the queue to remeove
+ * the removeStaleEntries() method works through the queue to remove
* stale entries from the table
*/
private[this] val queue = new ReferenceQueue[A]
@@ -62,7 +62,7 @@ final class WeakHashSet[A <: AnyRef](val initialCapacity: Int, val loadFactor: D
private[this] def computeThreshHold: Int = (table.size * loadFactor).ceil.toInt
/**
- * find the bucket associated with an elements's hash code
+ * find the bucket associated with an element's hash code
*/
private[this] def bucketFor(hash: Int): Int = {
// spread the bits around to try to avoid accidental collisions using the
diff --git a/src/reflect/scala/reflect/macros/Enclosures.scala b/src/reflect/scala/reflect/macros/Enclosures.scala
index 69ede42cc7..1eb6832b5b 100644
--- a/src/reflect/scala/reflect/macros/Enclosures.scala
+++ b/src/reflect/scala/reflect/macros/Enclosures.scala
@@ -47,7 +47,7 @@ trait Enclosures {
/** Tries to guess a position for the enclosing application.
* But that is simple, right? Just dereference `pos` of `macroApplication`? Not really.
- * If we're in a synthetic macro expansion (no positions), we must do our best to infer the position of something that triggerd this expansion.
+ * If we're in a synthetic macro expansion (no positions), we must do our best to infer the position of something that triggered this expansion.
* Surprisingly, quite often we can do this by navigation the `enclosingMacros` stack.
*/
def enclosingPosition: Position
diff --git a/src/reflect/scala/reflect/macros/Universe.scala b/src/reflect/scala/reflect/macros/Universe.scala
index 1eb67215bb..3b57169565 100644
--- a/src/reflect/scala/reflect/macros/Universe.scala
+++ b/src/reflect/scala/reflect/macros/Universe.scala
@@ -44,7 +44,7 @@ abstract class Universe extends scala.reflect.api.Universe {
* it is imperative that you either call `untypecheck` or do `changeOwner(tree, x, y)`.
*
* Since at the moment `untypecheck` has fundamental problem that can sometimes lead to tree corruption,
- * `changeOwner` becomes an indispensible tool in building 100% robust macros.
+ * `changeOwner` becomes an indispensable tool in building 100% robust macros.
* Future versions of the reflection API might obviate the need in taking care of
* these low-level details, but at the moment this is what we've got.
*/
diff --git a/src/reflect/scala/reflect/runtime/JavaMirrors.scala b/src/reflect/scala/reflect/runtime/JavaMirrors.scala
index a0da3f3bbf..1c751fb93b 100644
--- a/src/reflect/scala/reflect/runtime/JavaMirrors.scala
+++ b/src/reflect/scala/reflect/runtime/JavaMirrors.scala
@@ -38,7 +38,7 @@ private[scala] trait JavaMirrors extends internal.SymbolTable with api.JavaUnive
override lazy val rootMirror: Mirror = createMirror(NoSymbol, rootClassLoader)
- // overriden by ReflectGlobal
+ // overridden by ReflectGlobal
def rootClassLoader: ClassLoader = this.getClass.getClassLoader
trait JavaClassCompleter
diff --git a/src/reflect/scala/reflect/runtime/JavaUniverseForce.scala b/src/reflect/scala/reflect/runtime/JavaUniverseForce.scala
index c87b810bdd..1c0aa7cf6d 100644
--- a/src/reflect/scala/reflect/runtime/JavaUniverseForce.scala
+++ b/src/reflect/scala/reflect/runtime/JavaUniverseForce.scala
@@ -310,6 +310,7 @@ trait JavaUniverseForce { self: runtime.JavaUniverse =>
definitions.QuasiquoteClass_api_unapply
definitions.ScalaSignatureAnnotation
definitions.ScalaLongSignatureAnnotation
+ definitions.MethodHandle
definitions.OptionClass
definitions.OptionModule
definitions.SomeClass
diff --git a/src/reflect/scala/reflect/runtime/SynchronizedSymbols.scala b/src/reflect/scala/reflect/runtime/SynchronizedSymbols.scala
index 6d0cb0df45..4f0c0253e9 100644
--- a/src/reflect/scala/reflect/runtime/SynchronizedSymbols.scala
+++ b/src/reflect/scala/reflect/runtime/SynchronizedSymbols.scala
@@ -39,7 +39,7 @@ private[reflect] trait SynchronizedSymbols extends internal.Symbols { self: Symb
* Reasons for that differ from artifact to artifact. In some cases it's quite bad (e.g. types use a number
* of non-concurrent compiler caches, so we need to serialize certain operations on types in order to make
* sure that things stay deterministic). However, in case of symbols there's hope, because it's only during
- * initializaton that symbols are thread-unsafe. After everything's set up, symbols become immutable
+ * initialization that symbols are thread-unsafe. After everything's set up, symbols become immutable
* (sans a few deterministic caches that can be populated simultaneously by multiple threads) and therefore thread-safe.
*
* Note that by saying "symbols become immutable" I mean literally that. In a very common case of PackageClassSymbol's,
@@ -102,10 +102,10 @@ private[reflect] trait SynchronizedSymbols extends internal.Symbols { self: Symb
*
* Just a volatile var is fine, because:
* 1) Status can only be changed in a single-threaded fashion (this is enforced by gilSynchronized
- * that effecively guards `Symbol.initialize`), which means that there can't be update conflicts.
+ * that effectively guards `Symbol.initialize`), which means that there can't be update conflicts.
* 2) If someone reads a stale value of status, then the worst thing that might happen is that this someone
- * is going to spuriously call `initialize`, which is either a gil-protected operation (if the symbol isn't inited yet)
- * or a no-op (if the symbol is already inited), and that is fine in both cases.
+ * is going to spuriously call `initialize`, which is either a gil-protected operation (if the symbol isn't initialized yet)
+ * or a no-op (if the symbol is already initialized), and that is fine in both cases.
*
* upd. It looks like we also need to keep track of a mask of initialized flags to make sure
* that normal symbol initialization routines don't trigger auto-init in Symbol.flags-related routines (e.g. Symbol.getFlag).
diff --git a/src/repl/scala/tools/nsc/interpreter/AbstractOrMissingHandler.scala b/src/repl/scala/tools/nsc/interpreter/AbstractOrMissingHandler.scala
index e66e4eff29..df49e6a2e4 100644
--- a/src/repl/scala/tools/nsc/interpreter/AbstractOrMissingHandler.scala
+++ b/src/repl/scala/tools/nsc/interpreter/AbstractOrMissingHandler.scala
@@ -30,7 +30,7 @@ class AbstractOrMissingHandler[T](onError: String => Unit, value: T) extends Par
|Failed to initialize compiler: %s not found.
|** Note that as of 2.8 scala does not assume use of the java classpath.
|** For the old behavior pass -usejavacp to scala, or if using a Settings
- |** object programatically, settings.usejavacp.value = true.""".stripMargin.format(x.req)
+ |** object programmatically, settings.usejavacp.value = true.""".stripMargin.format(x.req)
)
value
}
diff --git a/src/repl/scala/tools/nsc/interpreter/ILoop.scala b/src/repl/scala/tools/nsc/interpreter/ILoop.scala
index 4fd5768b79..4d71e0e09e 100644
--- a/src/repl/scala/tools/nsc/interpreter/ILoop.scala
+++ b/src/repl/scala/tools/nsc/interpreter/ILoop.scala
@@ -12,6 +12,7 @@ import scala.annotation.tailrec
import Predef.{ println => _, _ }
import interpreter.session._
import StdReplTags._
+import scala.tools.asm.ClassReader
import scala.util.Properties.{ jdkHome, javaVersion, versionString, javaVmName }
import scala.tools.nsc.util.{ ClassPath, Exceptional, stringFromWriter, stringFromStream }
import scala.reflect.classTag
@@ -633,28 +634,29 @@ class ILoop(in0: Option[BufferedReader], protected val out: JPrintWriter)
* the interpreter and replays all interpreter expressions.
*/
def require(arg: String): Unit = {
- class InfoClassLoader extends java.lang.ClassLoader {
- def classOf(arr: Array[Byte]): Class[_] =
- super.defineClass(null, arr, 0, arr.length)
- }
-
val f = File(arg).normalize
- if (f.isDirectory) {
- echo("Adding directories to the classpath is not supported. Add a jar instead.")
+ val jarFile = AbstractFile.getDirectory(new java.io.File(arg))
+ if (jarFile == null) {
+ echo(s"Cannot load '$arg'")
return
}
- val jarFile = AbstractFile.getDirectory(new java.io.File(arg))
-
def flatten(f: AbstractFile): Iterator[AbstractFile] =
if (f.isClassContainer) f.iterator.flatMap(flatten)
else Iterator(f)
val entries = flatten(jarFile)
- val cloader = new InfoClassLoader
- def classNameOf(classFile: AbstractFile): String = cloader.classOf(classFile.toByteArray).getName
+ def classNameOf(classFile: AbstractFile): String = {
+ val input = classFile.input
+ try {
+ val reader = new ClassReader(input)
+ reader.getClassName.replace('/', '.')
+ } finally {
+ input.close()
+ }
+ }
def alreadyDefined(clsName: String) = intp.classLoader.tryToLoadClass(clsName).isDefined
val exists = entries.filter(_.hasExtension("class")).map(classNameOf).exists(alreadyDefined)
diff --git a/src/repl/scala/tools/nsc/interpreter/IMain.scala b/src/repl/scala/tools/nsc/interpreter/IMain.scala
index f9f7388363..0347622cf4 100644
--- a/src/repl/scala/tools/nsc/interpreter/IMain.scala
+++ b/src/repl/scala/tools/nsc/interpreter/IMain.scala
@@ -45,7 +45,7 @@ import java.io.File
* all variables defined by that code. To extract the result of an
* interpreted line to show the user, a second "result object" is created
* which imports the variables exported by the above object and then
- * exports members called "$eval" and "$print". To accomodate user expressions
+ * exports members called "$eval" and "$print". To accommodate user expressions
* that read from variables or methods defined in previous statements, "import"
* statements are used.
*
diff --git a/src/repl/scala/tools/nsc/interpreter/InteractiveReader.scala b/src/repl/scala/tools/nsc/interpreter/InteractiveReader.scala
index 28ddf2939c..ed69d449cb 100644
--- a/src/repl/scala/tools/nsc/interpreter/InteractiveReader.scala
+++ b/src/repl/scala/tools/nsc/interpreter/InteractiveReader.scala
@@ -23,6 +23,7 @@ trait InteractiveReader {
def readYesOrNo(prompt: String, alt: => Boolean): Boolean = readOneKey(prompt) match {
case 'y' => true
case 'n' => false
+ case -1 => false // EOF
case _ => alt
}
diff --git a/src/repl/scala/tools/nsc/interpreter/JavapClass.scala b/src/repl/scala/tools/nsc/interpreter/JavapClass.scala
index ebca3e7e62..c80b94bf89 100644
--- a/src/repl/scala/tools/nsc/interpreter/JavapClass.scala
+++ b/src/repl/scala/tools/nsc/interpreter/JavapClass.scala
@@ -656,7 +656,7 @@ object JavapClass {
// FunFinder.funs(ks) finds anonfuns
class FunFinder(loader: ScalaClassLoader, intp: Option[IMain]) {
- // manglese for closure: typename, $anonfun or lamba, opt method, digits
+ // manglese for closure: typename, $anonfun or lambda, opt method, digits
val closure = """(.*)\$(\$anonfun|lambda)(?:\$+([^$]+))?\$(\d+)""".r
// manglese for closure
@@ -743,7 +743,7 @@ object JavapClass {
case _ => Nil
}
val res = fs map (_.to[Seq]) getOrElse Seq()
- // on second thought, we don't care about lamba method classes, just the impl methods
+ // on second thought, we don't care about lambda method classes, just the impl methods
val rev =
res flatMap {
case x @ closure(_, "lambda", _, _) => labdaMethod(x, target)
@@ -787,7 +787,7 @@ object JavapClass {
}
}
/** Translate the supplied targets to patterns for anonfuns.
- * Pattern is typename $ label [[$]$func] $n where label is $anonfun or lamba,
+ * Pattern is typename $ label [[$]$func] $n where label is $anonfun or lambda,
* and lambda includes the extra dollar, func is a method name, and n is an int.
* The typename for a nested class is dollar notation, Betty$Bippy.
*
diff --git a/src/repl/scala/tools/nsc/interpreter/LoopCommands.scala b/src/repl/scala/tools/nsc/interpreter/LoopCommands.scala
index f177816b30..9f555aee14 100644
--- a/src/repl/scala/tools/nsc/interpreter/LoopCommands.scala
+++ b/src/repl/scala/tools/nsc/interpreter/LoopCommands.scala
@@ -80,7 +80,7 @@ trait LoopCommands {
def recording(line: String) = Result(keepRunning = true, Option(line))
// most commands do not want to micromanage the Result, but they might want
- // to print something to the console, so we accomodate Unit and String returns.
+ // to print something to the console, so we accommodate Unit and String returns.
implicit def resultFromUnit(x: Unit): Result = default
implicit def resultFromString(msg: String): Result = {
echoCommandMessage(msg)
diff --git a/src/repl/scala/tools/nsc/interpreter/Power.scala b/src/repl/scala/tools/nsc/interpreter/Power.scala
index f69a5b487d..8d8140b638 100644
--- a/src/repl/scala/tools/nsc/interpreter/Power.scala
+++ b/src/repl/scala/tools/nsc/interpreter/Power.scala
@@ -155,7 +155,7 @@ class Power[ReplValsImpl <: ReplVals : ru.TypeTag: ClassTag](val intp: IMain, re
}
object InternalInfo extends LowPriorityInternalInfo { }
- /** Now dealing with the problem of acidentally calling a method on Type
+ /** Now dealing with the problem of accidentally calling a method on Type
* when you're holding a Symbol and seeing the Symbol converted to the
* type of Symbol rather than the type of the thing represented by the
* symbol, by only implicitly installing one method, "?", and the rest
diff --git a/src/scaladoc/scala/tools/ant/Scaladoc.scala b/src/scaladoc/scala/tools/ant/Scaladoc.scala
index 36a1405b11..034416e844 100644
--- a/src/scaladoc/scala/tools/ant/Scaladoc.scala
+++ b/src/scaladoc/scala/tools/ant/Scaladoc.scala
@@ -543,7 +543,7 @@ class Scaladoc extends ScalaMatchingTask {
/** Tests if a file exists and prints a warning in case it doesn't. Always
* returns the file, even if it doesn't exist.
*
- * @param file A file to test for existance.
+ * @param file A file to test for existence.
* @return The same file.
*/
private def existing(file: File): File = {
diff --git a/src/scaladoc/scala/tools/nsc/doc/html/resource/lib/diagrams.js b/src/scaladoc/scala/tools/nsc/doc/html/resource/lib/diagrams.js
index 478f2e38ac..680ead7a59 100644
--- a/src/scaladoc/scala/tools/nsc/doc/html/resource/lib/diagrams.js
+++ b/src/scaladoc/scala/tools/nsc/doc/html/resource/lib/diagrams.js
@@ -25,7 +25,7 @@ $(document).ready(function()
$(".diagram-container").css("display", "block");
$(".diagram").each(function() {
- // store inital dimensions
+ // store initial dimensions
$(this).data("width", $("svg", $(this)).width());
$(this).data("height", $("svg", $(this)).height());
// store unscaled clone of SVG element
diff --git a/src/scaladoc/scala/tools/nsc/doc/model/Entity.scala b/src/scaladoc/scala/tools/nsc/doc/model/Entity.scala
index 6932f01e9a..7fe8903c76 100644
--- a/src/scaladoc/scala/tools/nsc/doc/model/Entity.scala
+++ b/src/scaladoc/scala/tools/nsc/doc/model/Entity.scala
@@ -117,7 +117,7 @@ trait MemberEntity extends Entity {
def toRoot: List[MemberEntity]
/** The templates in which this member has been declared. The first element of the list is the template that contains
- * the currently active declaration of this member, subsequent elements are declarations that have been overriden. If
+ * the currently active declaration of this member, subsequent elements are declarations that have been overridden. If
* the first element is equal to `inTemplate`, the member is declared locally, if not, it has been inherited. All
* elements of this list are in the linearization of `inTemplate`. */
def inDefinitionTemplates: List[TemplateEntity]
diff --git a/test/benchmarks/src/scala/collection/parallel/benchmarks/Bench.scala b/test/benchmarks/src/scala/collection/parallel/benchmarks/Bench.scala
index e8dfe0ac50..c20bbaeef1 100644
--- a/test/benchmarks/src/scala/collection/parallel/benchmarks/Bench.scala
+++ b/test/benchmarks/src/scala/collection/parallel/benchmarks/Bench.scala
@@ -78,7 +78,7 @@ trait Bench extends Benchmark {
}
/**
- * Prints results of the benchmark. May be overidden in benchmarks.
+ * Prints results of the benchmark. May be overridden in benchmarks.
*/
def printResults {}
diff --git a/test/files/jvm/innerClassAttribute/Test.scala b/test/files/jvm/innerClassAttribute/Test.scala
index 1c1a0522e4..3820048cb4 100644
--- a/test/files/jvm/innerClassAttribute/Test.scala
+++ b/test/files/jvm/innerClassAttribute/Test.scala
@@ -84,17 +84,15 @@ object Test extends BytecodeTest {
}
def testA3() = {
- def t(c: String) = {
- val List(b1, b2) = innerClassNodes(c)
- // the outer class for classes nested inside top-level modules is not the module class, but the mirror class.
- // this is a hack for java interop, handled in the backend. see BTypes.scala, comment on "Java Compatibility".
- assertMember(b1, "A3", "B1", flags = publicStatic)
- assertMember(b2, "A3", "B2$", flags = publicStatic)
- }
- t("A3$")
- // the mirror class has the same inner class attributes as the module
- // class (added when the mirror is created in the backend)
- t("A3")
+ // the inner class entries for top-level object members are in the companion class, so nothing in the module class
+ val List() = innerClassNodes("A3$")
+
+ // inner class entries in the companion class (a backend-generated mirror class in this case)
+ val List(b1, b2) = innerClassNodes("A3")
+ // the outer class for classes nested inside top-level modules is not the module class, but the mirror class.
+ // this is a hack for java interop, handled in the backend. see BTypes.scala, comment on "Java Compatibility".
+ assertMember(b1, "A3", "B1", flags = publicStatic)
+ assertMember(b2, "A3", "B2$", flags = publicStatic)
}
def testA4() = {
@@ -164,7 +162,10 @@ object Test extends BytecodeTest {
}
def testA15() = {
- val List(b) = innerClassNodes("A15")
+ // no member classes, only anonymous / local. these are nested in the module class, not the companion.
+ val List() = innerClassNodes("A15")
+
+ val List(b) = innerClassNodes("A15$")
assertLocal(b, "A15$B$3", "B$3")
val List(_, c) = innerClassNodes("A15$B$3")
@@ -283,9 +284,7 @@ object Test extends BytecodeTest {
assertMember(i3c, "A21", "I3$", flags = publicStatic)
assertLocal(j1, "A21$J1$1", "J1$1")
- val List(i2m, i3m, j3, j4, j5) = innerClassNodes("A21$")
- assertMember(i2m, "A21", "I2", flags = publicStatic)
- assertMember(i3m, "A21", "I3$", flags = publicStatic)
+ val List(j3, j4, j5) = innerClassNodes("A21$")
assertLocal(j3, "A21$J3$1", "J3$1")
assertLocal(j4, "A21$J4$1", "J4$1")
assertLocal(j5, "A21$J5$1", "J5$1") // non-static!
diff --git a/test/files/jvm/serialization-new.check b/test/files/jvm/serialization-new.check
index 1555135926..cb26446f40 100644
--- a/test/files/jvm/serialization-new.check
+++ b/test/files/jvm/serialization-new.check
@@ -1,4 +1,4 @@
-warning: there were two deprecation warnings; re-run with -deprecation for details
+warning: there were three deprecation warnings; re-run with -deprecation for details
a1 = Array[1,2,3]
_a1 = Array[1,2,3]
arrayEquals(a1, _a1): true
diff --git a/test/files/jvm/serialization.check b/test/files/jvm/serialization.check
index 1555135926..cb26446f40 100644
--- a/test/files/jvm/serialization.check
+++ b/test/files/jvm/serialization.check
@@ -1,4 +1,4 @@
-warning: there were two deprecation warnings; re-run with -deprecation for details
+warning: there were three deprecation warnings; re-run with -deprecation for details
a1 = Array[1,2,3]
_a1 = Array[1,2,3]
arrayEquals(a1, _a1): true
diff --git a/test/files/jvm/t8582.check b/test/files/jvm/t8582.check
index 564f482ff8..e388366270 100644
--- a/test/files/jvm/t8582.check
+++ b/test/files/jvm/t8582.check
@@ -14,10 +14,10 @@ Reflection can find direct nested classes (A2-B2-C2)
A2$B2: List(class A2$B2$C2)
A2$B2$C2: List()
-Mirror classes have the same InnerClass attributes as the corresponding module class:
- className[p1/p2/Singleton$Singleton$] outerClassName[p1/p2/Singleton] innerName[Singleton$] access[9]
-Module class
+The InnerClass attribute of a mirror class contains the members of the module class:
className[p1/p2/Singleton$Singleton$] outerClassName[p1/p2/Singleton] innerName[Singleton$] access[9]
+The module members are not in the InnerClass table of the module class (unless referenced):
+
An outer class has a InnerClass attribute for direct nested classes
className[A1$B1] outerClassName[A1] innerName[B1] access[1]
diff --git a/test/files/jvm/t8582.scala b/test/files/jvm/t8582.scala
index 8a57ef7952..e9a01f9016 100644
--- a/test/files/jvm/t8582.scala
+++ b/test/files/jvm/t8582.scala
@@ -55,9 +55,9 @@ object Test extends BytecodeTest {
println(nested(classOf[A2#B2]))
println(nested(classOf[A2#B2#C2]))
- nprintln("Mirror classes have the same InnerClass attributes as the corresponding module class:")
+ nprintln("The InnerClass attribute of a mirror class contains the members of the module class:")
printInner("p1.p2.Singleton") // mirror class
- println("Module class")
+ println("The module members are not in the InnerClass table of the module class (unless referenced):")
printInner("p1.p2.Singleton$")
nprintln("An outer class has a InnerClass attribute for direct nested classes")
diff --git a/test/files/jvm/t9044.scala b/test/files/jvm/t9044.scala
new file mode 100644
index 0000000000..b1073325e8
--- /dev/null
+++ b/test/files/jvm/t9044.scala
@@ -0,0 +1,6 @@
+trait A
+trait B
+object Test extends A with B with App {
+ val is = Test.getClass.getInterfaces.mkString(", ")
+ assert(is == "interface A, interface B, interface scala.App", is)
+}
diff --git a/test/files/neg/literate_existentials.scala b/test/files/neg/literate_existentials.scala
index 8580347bf9..5537c50b3a 100644
--- a/test/files/neg/literate_existentials.scala
+++ b/test/files/neg/literate_existentials.scala
@@ -187,7 +187,7 @@ object LiterateExistentials {
//
implicitly[Int <:< (M forSome { type M >: Nothing <: String })] // fails
-// The preceeding line causes the compiler to generate an error message.
+// The preceding line causes the compiler to generate an error message.
diff --git a/test/files/neg/structural.scala b/test/files/neg/structural.scala
index d783399317..00459676a9 100644
--- a/test/files/neg/structural.scala
+++ b/test/files/neg/structural.scala
@@ -11,13 +11,13 @@ object Test extends App {
def f2[C <: Object](x: Object{ type D <: Object; def m[E >: Null <: Object](x: B): Object; val x: B }) = x.m[Tata](x.x) //fail
def f3[C <: Object](x: Object{ type D <: Object; def m[E >: Null <: Object](x: C): Object; val x: C }) = x.m[Tata](x.x) //fail
def f4[C <: Object](x: Object{ type D <: Object; def m[E >: Null <: Object](x: D): Object; val x: D }) = x.m[Tata](x.x) //fail
- def f5[C <: Object](x: Object{ type D <: Object; def m[E >: Null <: Object](x: E): Object; val x: Tata }) = x.m[Tata](x.x) //suceed
+ def f5[C <: Object](x: Object{ type D <: Object; def m[E >: Null <: Object](x: E): Object; val x: Tata }) = x.m[Tata](x.x) //succeeds
- def f6[C <: Object](x: Object{ type D <: Object; def m[E >: Null <: Object](x: Object): A }) = x.m[Tata](null) //suceed
- def f7[C <: Object](x: Object{ type D <: Object; def m[E >: Null <: Object](x: Object): B }) = x.m[Tata](null) //suceed
- def f8[C <: Object](x: Object{ type D <: Object; def m[E >: Null <: Object](x: Object): C }) = x.m[Tata](null) //suceed
+ def f6[C <: Object](x: Object{ type D <: Object; def m[E >: Null <: Object](x: Object): A }) = x.m[Tata](null) //succeeds
+ def f7[C <: Object](x: Object{ type D <: Object; def m[E >: Null <: Object](x: Object): B }) = x.m[Tata](null) //succeeds
+ def f8[C <: Object](x: Object{ type D <: Object; def m[E >: Null <: Object](x: Object): C }) = x.m[Tata](null) //succeeds
def f9[C <: Object](x: Object{ type D <: Object; def m[E >: Null <: Object](x: Object): D }) = x.m[Tata](null) //fail
- def f0[C <: Object](x: Object{ type D <: Object; def m[E >: Null <: Object](x: Object): E }) = x.m[Tata](null) //suceed
+ def f0[C <: Object](x: Object{ type D <: Object; def m[E >: Null <: Object](x: Object): E }) = x.m[Tata](null) //succeeds
}
diff --git a/test/files/neg/t6582_exhaust_big.check b/test/files/neg/t6582_exhaust_big.check
new file mode 100644
index 0000000000..9e2be038b5
--- /dev/null
+++ b/test/files/neg/t6582_exhaust_big.check
@@ -0,0 +1,7 @@
+t6582_exhaust_big.scala:27: warning: match may not be exhaustive.
+It would fail on the following input: Z11()
+ def foo(z: Z) = z match {
+ ^
+error: No warnings can be incurred under -Xfatal-warnings.
+one warning found
+one error found
diff --git a/test/files/neg/t6582_exhaust_big.flags b/test/files/neg/t6582_exhaust_big.flags
new file mode 100644
index 0000000000..b5a8748652
--- /dev/null
+++ b/test/files/neg/t6582_exhaust_big.flags
@@ -0,0 +1 @@
+-Xfatal-warnings -unchecked
diff --git a/test/files/neg/t6582_exhaust_big.scala b/test/files/neg/t6582_exhaust_big.scala
new file mode 100644
index 0000000000..dd639eb56e
--- /dev/null
+++ b/test/files/neg/t6582_exhaust_big.scala
@@ -0,0 +1,32 @@
+sealed abstract class Z
+object Z {
+ object Z0 extends Z
+ case class Z1() extends Z
+ object Z2 extends Z
+ case class Z3() extends Z
+ object Z4 extends Z
+ case class Z5() extends Z
+ object Z6 extends Z
+ case class Z7() extends Z
+ object Z8 extends Z
+ case class Z9() extends Z
+ object Z10 extends Z
+ case class Z11() extends Z
+ object Z12 extends Z
+ case class Z13() extends Z
+ object Z14 extends Z
+ case class Z15() extends Z
+ object Z16 extends Z
+ case class Z17() extends Z
+ object Z18 extends Z
+ case class Z19() extends Z
+}
+
+object Test {
+ import Z._
+ def foo(z: Z) = z match {
+ case Z0 | Z1() | Z2 | Z3() | Z4 | Z5() | Z6 | Z7() | Z8 | Z9() |
+ Z10 | Z12 | Z13() | Z14 | Z15() | Z16 | Z17() | Z18 | Z19()
+ =>
+ }
+}
diff --git a/test/files/neg/t7623.check b/test/files/neg/t7623.check
new file mode 100644
index 0000000000..db368dd369
--- /dev/null
+++ b/test/files/neg/t7623.check
@@ -0,0 +1,21 @@
+t7623.scala:19: warning: A repeated case parameter or extracted sequence should be matched only by a sequence wildcard (_*).
+ def f = "" match { case X(s) => }
+ ^
+t7623.scala:21: warning: A repeated case parameter or extracted sequence should be matched only by a sequence wildcard (_*).
+ def g = "" match { case X(s, t) => }
+ ^
+t7623.scala:23: warning: A repeated case parameter or extracted sequence should be matched only by a sequence wildcard (_*).
+ def h = "" match { case X(s, t, u @ _*) => }
+ ^
+t7623.scala:9: warning: A repeated case parameter or extracted sequence should be matched only by a sequence wildcard (_*).
+ def f = C("") match { case C(s) => }
+ ^
+t7623.scala:11: warning: A repeated case parameter or extracted sequence should be matched only by a sequence wildcard (_*).
+ def g = C("") match { case C(s, t) => }
+ ^
+t7623.scala:13: warning: A repeated case parameter or extracted sequence should be matched only by a sequence wildcard (_*).
+ def h = C("") match { case C(s, t, u @ _*) => }
+ ^
+error: No warnings can be incurred under -Xfatal-warnings.
+6 warnings found
+one error found
diff --git a/test/files/neg/t7623.flags b/test/files/neg/t7623.flags
new file mode 100644
index 0000000000..74c9e38323
--- /dev/null
+++ b/test/files/neg/t7623.flags
@@ -0,0 +1 @@
+-Xlint:stars-align -Xfatal-warnings
diff --git a/test/files/neg/t7623.scala b/test/files/neg/t7623.scala
new file mode 100644
index 0000000000..5c40f37bc1
--- /dev/null
+++ b/test/files/neg/t7623.scala
@@ -0,0 +1,38 @@
+
+
+case class C(s: String, xs: Int*)
+
+object X { def unapplySeq(a: Any): Option[(String, Seq[Int])] = Some("", List(1,2,3)) }
+
+// for case classes with varargs, avoid misaligned patterns
+trait Ctest {
+ def f = C("") match { case C(s) => }
+
+ def g = C("") match { case C(s, t) => }
+
+ def h = C("") match { case C(s, t, u @ _*) => }
+
+ def ok = C("") match { case C(s, u @ _*) => }
+}
+// for extractors that unapplySeq: Option[(Something, Seq[_])], avoid misaligned patterns
+trait Xtest {
+ def f = "" match { case X(s) => }
+
+ def g = "" match { case X(s, t) => }
+
+ def h = "" match { case X(s, t, u @ _*) => }
+
+ def ok = "" match { case X(s, u @ _*) => }
+}
+// for extractors that unapplySeq: Option[Seq[_]], anything goes
+trait Rtest {
+ val r = "(a+)".r
+
+ def f = "" match { case r(s) => }
+
+ def g = "" match { case r(s, t) => }
+
+ def h = "" match { case r(s, t, u @ _*) => }
+
+ def whatever = "" match { case r(u @ _*) => }
+}
diff --git a/test/files/neg/t9041.check b/test/files/neg/t9041.check
new file mode 100644
index 0000000000..669e9434e0
--- /dev/null
+++ b/test/files/neg/t9041.check
@@ -0,0 +1,4 @@
+t9041.scala:11: error: could not find implicit value for parameter cellSetter: CellSetter[scala.math.BigDecimal]
+ def setCell(cell: Cell, data: math.BigDecimal) { cell.setCellValue(data) }
+ ^
+one error found
diff --git a/test/files/neg/t9041.scala b/test/files/neg/t9041.scala
new file mode 100644
index 0000000000..2bdef0d3ae
--- /dev/null
+++ b/test/files/neg/t9041.scala
@@ -0,0 +1,17 @@
+// False negative test, requires overloading in Cell.
+
+trait Cell { def setCellValue(i: Int) = () ; def setCellValue(d: Double) = () }
+
+trait Nope {
+ def f = {
+ trait CellSetter[A] {
+ def setCell(cell: Cell, data: A): Unit
+ }
+ implicit val bigDecimalCellSetter = new CellSetter[math.BigDecimal]() {
+ def setCell(cell: Cell, data: math.BigDecimal) { cell.setCellValue(data) }
+ }
+ implicit class RichCell(cell: Cell) {
+ def setCellValue[A](data: A)(implicit cellSetter: CellSetter[A]) = cellSetter.setCell(cell, data)
+ }
+ }
+}
diff --git a/test/files/neg/t9093.check b/test/files/neg/t9093.check
new file mode 100644
index 0000000000..085a433f0b
--- /dev/null
+++ b/test/files/neg/t9093.check
@@ -0,0 +1,6 @@
+t9093.scala:3: error: polymorphic expression cannot be instantiated to expected type;
+ found : [C](f: C)Null
+ required: Unit
+ val x: Unit = apply2(0)/*(0)*/
+ ^
+one error found
diff --git a/test/files/neg/t9093.scala b/test/files/neg/t9093.scala
new file mode 100644
index 0000000000..d9922ad70e
--- /dev/null
+++ b/test/files/neg/t9093.scala
@@ -0,0 +1,5 @@
+object Main {
+ def apply2[C](fa: Any)(f: C) = null
+ val x: Unit = apply2(0)/*(0)*/
+}
+
diff --git a/test/files/pos/patmat-suppress.flags b/test/files/pos/patmat-suppress.flags
new file mode 100644
index 0000000000..a988a5b807
--- /dev/null
+++ b/test/files/pos/patmat-suppress.flags
@@ -0,0 +1 @@
+-Xfatal-warnings -Xno-patmat-analysis \ No newline at end of file
diff --git a/test/files/pos/patmat-suppress.scala b/test/files/pos/patmat-suppress.scala
new file mode 100644
index 0000000000..7c8aded690
--- /dev/null
+++ b/test/files/pos/patmat-suppress.scala
@@ -0,0 +1,159 @@
+// test that none of these warn due to -Xno-patmat-analysis
+// tests taken from test/files/neg/patmatexhaust.scala, test/files/neg/pat_unreachable.scala
+class TestSealedExhaustive { // compile only
+ sealed abstract class Foo
+
+ case class Bar(x:Int) extends Foo
+ case object Baz extends Foo
+
+ def ma1(x:Foo) = x match {
+ case Bar(_) => // not exhaustive
+ }
+
+ def ma2(x:Foo) = x match {
+ case Baz => // not exhaustive
+ }
+
+ sealed abstract class Mult
+ case class Kult(s:Mult) extends Mult
+ case class Qult() extends Mult
+
+ def ma33(x:Kult) = x match { // exhaustive
+ case Kult(_) => // exhaustive
+ }
+
+ def ma3(x:Mult) = (x,x) match { // not exhaustive
+ case (Kult(_), Qult()) => // Kult missing
+ //case (Kult(_), Kult(_)) =>
+ case (Qult(), Kult(_)) => // Qult missing
+ //case (Qult(), Qult()) =>
+ }
+
+ def ma3u(x:Mult) = ((x,x) : @unchecked) match { // not exhaustive, but not checked!
+ case (Kult(_), Qult()) =>
+ case (Qult(), Kult(_)) =>
+ }
+
+ sealed abstract class Deep
+
+ case object Ga extends Deep
+ sealed class Gp extends Deep
+ case object Gu extends Gp
+
+ def zma3(x:Deep) = x match { // exhaustive!
+ case _ =>
+ }
+ def zma4(x:Deep) = x match { // exhaustive!
+ case Ga =>
+ case _ =>
+ }
+
+ def ma4(x:Deep) = x match { // missing cases: Gu, Gp which is not abstract so must be included
+ case Ga =>
+ }
+
+ def ma5(x:Deep) = x match {
+ case Gu =>
+ case _ if 1 == 0 =>
+ case Ga =>
+ }
+
+ def ma6() = List(1,2) match { // give up
+ case List(1,2) =>
+ case x :: xs =>
+ }
+
+ def ma7() = List(1,2) match { //exhaustive
+ case 1::2::Nil =>
+ case _ =>
+ }
+
+ sealed class B
+ case class B1() extends B
+ case object B2 extends B
+ def ma8(x: B) = x match {
+ case _: B => true
+ }
+ def ma9(x: B) = x match {
+ case B1() => true // missing B, which is not abstract so must be included
+ case B2 => true
+ }
+
+ object ob1 {
+ sealed abstract class C
+ sealed abstract class C1 extends C
+ object C2 extends C
+ case class C3() extends C
+ case object C4 extends C
+
+ def ma10(x: C) = x match { // exhaustive: abstract sealed C1 is dead end.
+ case C3() => true
+ case C2 | C4 => true
+ }
+ }
+
+ object ob2 {
+ sealed abstract class C
+ abstract class C1 extends C
+ object C2 extends C
+ case class C3() extends C
+ case object C4 extends C
+
+ def ma10(x: C) = x match { // not exhaustive: C1 is not sealed.
+ case C3() => true
+ case C2 | C4 => true
+ }
+ }
+ object ob3 {
+ sealed abstract class C
+ sealed abstract class C1 extends C
+ object D1 extends C1
+ case class D2() extends C1
+ object C2 extends C
+ case class C3() extends C
+ case object C4 extends C
+
+ def ma10(x: C) = x match { // not exhaustive: C1 has subclasses.
+ case C3() => true
+ case C2 | C4 => true
+ }
+ }
+ object ob4 {
+ sealed abstract class C
+ sealed class C1 extends C
+ object C2 extends C
+ case class C3() extends C
+ case object C4 extends C
+
+ def ma10(x: C) = x match { // not exhaustive: C1 is not abstract.
+ case C3() => true
+ case C2 | C4 => true
+ }
+ }
+}
+
+object TestUnreachable extends App {
+ def unreachable1(xs:Seq[Char]) = xs match {
+ case Seq(x, y, _*) => x::y::Nil
+ case Seq(x, y, z, w) => List(z,w) // redundant!
+ }
+ def unreachable2(xs:Seq[Char]) = xs match {
+ case Seq(x, y, _*) => x::y::Nil
+ case Seq(x, y) => List(x, y)
+ }
+
+ def not_unreachable(xs:Seq[Char]) = xs match {
+ case Seq(x, y, _*) => x::y::Nil
+ case Seq(x) => List(x)
+ }
+ def not_unreachable2(xs:Seq[Char]) = xs match {
+ case Seq(x, y) => x::y::Nil
+ case Seq(x, y, z, _*) => List(x,y)
+ }
+
+ def contrivedExample[A, B, C](a: A, b: B, c: C): Unit = a match {
+ case b => println("matched b")
+ case c => println("matched c")
+ case _ => println("matched neither")
+ }
+}
diff --git a/test/files/pos/t4070.scala b/test/files/pos/t4070.scala
index a9777f02ed..11af67a529 100644
--- a/test/files/pos/t4070.scala
+++ b/test/files/pos/t4070.scala
@@ -20,7 +20,7 @@ package b {
/*
-// With crash below the clasess:
+// With crash below the classes:
% scalac -Dscalac.debug.tvar ./a.scala
[ create] ?_$1 ( In Foo#crash )
[ setInst] tv[Int] ( In Foo#crash, _$1=tv[Int] )
diff --git a/test/files/pos/t5154.scala b/test/files/pos/t5154.scala
new file mode 100644
index 0000000000..2629308f00
--- /dev/null
+++ b/test/files/pos/t5154.scala
@@ -0,0 +1,9 @@
+
+trait Z {
+ // extra space made the pattern OK
+ def f = <z> {{3}}</z> match { case <z> {{3}}</z> => }
+
+ // lack of space: error: illegal start of simple pattern
+ def g = <z>{{3}}</z> match { case <z>{{3}}</z> => }
+}
+
diff --git a/test/files/pos/t6582_exhaust_big.scala b/test/files/pos/t6582_exhaust_big.scala
new file mode 100644
index 0000000000..7bb8879805
--- /dev/null
+++ b/test/files/pos/t6582_exhaust_big.scala
@@ -0,0 +1,33 @@
+sealed abstract class Z
+object Z {
+ object Z0 extends Z
+ case class Z1() extends Z
+ object Z2 extends Z
+ case class Z3() extends Z
+ object Z4 extends Z
+ case class Z5() extends Z
+ object Z6 extends Z
+ case class Z7() extends Z
+ object Z8 extends Z
+ case class Z9() extends Z
+ object Z10 extends Z
+ case class Z11() extends Z
+ object Z12 extends Z
+ case class Z13() extends Z
+ object Z14 extends Z
+ case class Z15() extends Z
+ object Z16 extends Z
+ case class Z17() extends Z
+ object Z18 extends Z
+ case class Z19() extends Z
+}
+
+// drop any case and it will report an error
+object Test {
+ import Z._
+ def foo(z: Z) = z match {
+ case Z0 | Z1() | Z2 | Z3() | Z4 | Z5() | Z6 | Z7() | Z8 | Z9() |
+ Z10 | Z11() | Z12 | Z13() | Z14 | Z15() | Z16 | Z17() | Z18 | Z19()
+ =>
+ }
+}
diff --git a/test/files/pos/t7459a.scala b/test/files/pos/t7459a.scala
new file mode 100644
index 0000000000..5107715e06
--- /dev/null
+++ b/test/files/pos/t7459a.scala
@@ -0,0 +1,18 @@
+trait SpecialException extends Throwable
+
+object Test {
+ def run() {
+ try {
+ ???
+ } catch {
+ case e: SpecialException => e.isInstanceOf[SpecialException]
+ case e =>
+ }
+
+ // OKAY
+ // (null: Throwable) match {
+ // case e: SpecialException => e.isInstanceOf[SpecialException]
+ // case e =>
+ // }
+ }
+} \ No newline at end of file
diff --git a/test/files/pos/t7459b.scala b/test/files/pos/t7459b.scala
new file mode 100644
index 0000000000..a4b4fd07a9
--- /dev/null
+++ b/test/files/pos/t7459b.scala
@@ -0,0 +1,12 @@
+import scala.concurrent._
+import scala.util._
+
+
+class Test {
+ (null: Any) match {
+ case s @ Some(_) => ???
+ case f @ _ =>
+ () => f
+ ???
+ }
+} \ No newline at end of file
diff --git a/test/files/pos/t7459c.scala b/test/files/pos/t7459c.scala
new file mode 100644
index 0000000000..dc2605abe6
--- /dev/null
+++ b/test/files/pos/t7459c.scala
@@ -0,0 +1,18 @@
+object Test {
+ trait Universe {
+ type Type
+ type TypeTag[A] >: Null <: TypeTagApi[A]
+ trait TypeTagApi[A] { def tpe: Type }
+ }
+ trait JavaUniverse extends Universe
+
+ trait Mirror[U <: Universe] {
+ def universe: U
+ }
+ (null: Mirror[_]).universe match {
+ case ju: JavaUniverse =>
+ val ju1 = ju
+ val f = {() => (null: ju.TypeTag[Nothing]).tpe }
+ }
+ trait M[A]
+}
diff --git a/test/files/pos/t7459d.scala b/test/files/pos/t7459d.scala
new file mode 100644
index 0000000000..7843156885
--- /dev/null
+++ b/test/files/pos/t7459d.scala
@@ -0,0 +1,8 @@
+class Test {
+ (null: Any) match {
+ case s @ Some(_) => ???
+ case f @ _ =>
+ () => f
+ ???
+ }
+}
diff --git a/test/files/pos/t7704.scala b/test/files/pos/t7704.scala
new file mode 100644
index 0000000000..cae88d3324
--- /dev/null
+++ b/test/files/pos/t7704.scala
@@ -0,0 +1,10 @@
+class Attr { type V ; class Val }
+class StrAttr extends Attr { type V = String }
+class BoolAttr extends Attr { type V = Boolean }
+
+object Main {
+ def f(x: Attr) = x match {
+ case v: StrAttr => new v.Val
+ case v: BoolAttr => new v.Val
+ }
+}
diff --git a/test/files/pos/t8828.scala b/test/files/pos/t8828.scala
index 92092b4dd4..182aba54c0 100644
--- a/test/files/pos/t8828.scala
+++ b/test/files/pos/t8828.scala
@@ -11,7 +11,7 @@ package inner {
}
// the trait is sealed and doWork is not
- // and cannot be overriden: no warning
+ // and cannot be overridden: no warning
private[outer] sealed trait C {
def doWork(a: A): A = a
}
diff --git a/test/files/pos/t8999.flags b/test/files/pos/t8999.flags
new file mode 100644
index 0000000000..0f96f1f872
--- /dev/null
+++ b/test/files/pos/t8999.flags
@@ -0,0 +1 @@
+-nowarn \ No newline at end of file
diff --git a/test/files/pos/t8999.scala b/test/files/pos/t8999.scala
new file mode 100644
index 0000000000..99c4b2ad84
--- /dev/null
+++ b/test/files/pos/t8999.scala
@@ -0,0 +1,271 @@
+object Types {
+
+ abstract sealed class Type
+
+ case object AnyType extends Type
+
+ case object NothingType extends Type
+
+ case object UndefType extends Type
+
+ case object BooleanType extends Type
+
+ case object IntType extends Type
+
+ case object LongType extends Type
+
+ case object FloatType extends Type
+
+ case object DoubleType extends Type
+
+ case object StringType extends Type
+
+ case object NullType extends Type
+
+ sealed abstract class ReferenceType extends Type
+
+ final case class ClassType(className: String) extends ReferenceType
+
+ final case class ArrayType(baseClassName: String, dimensions: Int) extends ReferenceType
+
+ final case class RecordType(fields: List[RecordType.Field]) extends Type
+
+ object RecordType {
+ final case class Field(name: String, originalName: Option[String],
+ tpe: Type, mutable: Boolean)
+ }
+
+ case object NoType extends Type
+
+}
+
+
+sealed abstract class ClassKind
+
+object ClassKind {
+
+ case object Class extends ClassKind
+
+ case object ModuleClass extends ClassKind
+
+ case object Interface extends ClassKind
+
+ case object RawJSType extends ClassKind
+
+ case object HijackedClass extends ClassKind
+
+ case object TraitImpl extends ClassKind
+
+}
+
+object Trees {
+
+ import Types._
+
+ abstract sealed class Tree
+
+ case object EmptyTree extends Tree
+
+ sealed trait PropertyName
+ case class Ident(name: String, originalName: Option[String]) extends PropertyName
+ object Ident {
+ def apply(name: String): Ident =
+ new Ident(name, Some(name))
+ }
+
+ case class VarDef(name: Ident, vtpe: Type, mutable: Boolean, rhs: Tree) extends Tree
+
+ case class ParamDef(name: Ident, ptpe: Type, mutable: Boolean) extends Tree
+
+ case class Skip() extends Tree
+
+ class Block private(val stats: List[Tree]) extends Tree
+
+ object Block {
+ def unapply(block: Block): Some[List[Tree]] = Some(block.stats)
+ }
+
+ case class Labeled(label: Ident, tpe: Type, body: Tree) extends Tree
+
+ case class Assign(lhs: Tree, rhs: Tree) extends Tree
+
+ case class Return(expr: Tree, label: Option[Ident] = None) extends Tree
+
+ case class If(cond: Tree, thenp: Tree, elsep: Tree) extends Tree
+
+ case class While(cond: Tree, body: Tree, label: Option[Ident] = None) extends Tree
+
+ case class DoWhile(body: Tree, cond: Tree, label: Option[Ident] = None) extends Tree
+
+ case class Try(block: Tree, errVar: Ident, handler: Tree, finalizer: Tree) extends Tree
+
+ case class Throw(expr: Tree) extends Tree
+
+ case class Continue(label: Option[Ident] = None) extends Tree
+
+ case class Match(selector: Tree, cases: List[(List[Literal], Tree)], default: Tree) extends Tree
+
+ case class Debugger() extends Tree
+
+ case class New(cls: ClassType, ctor: Ident, args: List[Tree]) extends Tree
+
+ case class LoadModule(cls: ClassType) extends Tree
+
+ case class StoreModule(cls: ClassType, value: Tree) extends Tree
+
+ case class Select(qualifier: Tree, item: Ident, mutable: Boolean) extends Tree
+
+ case class Apply(receiver: Tree, method: Ident, args: List[Tree]) extends Tree
+
+ case class StaticApply(receiver: Tree, cls: ClassType, method: Ident, args: List[Tree]) extends Tree
+
+ case class TraitImplApply(impl: ClassType, method: Ident, args: List[Tree]) extends Tree
+
+ case class UnaryOp(op: Int, lhs: Tree) extends Tree
+
+ case class BinaryOp(op: Int, lhs: Tree, rhs: Tree) extends Tree
+
+ case class NewArray(tpe: ArrayType, lengths: List[Tree]) extends Tree
+
+ case class ArrayValue(tpe: ArrayType, elems: List[Tree]) extends Tree
+
+ case class ArrayLength(array: Tree) extends Tree
+
+ case class ArraySelect(array: Tree, index: Tree) extends Tree
+
+ case class RecordValue(tpe: RecordType, elems: List[Tree]) extends Tree
+
+ case class IsInstanceOf(expr: Tree, cls: ReferenceType) extends Tree
+
+ case class AsInstanceOf(expr: Tree, cls: ReferenceType) extends Tree
+
+ case class Unbox(expr: Tree, charCode: Char) extends Tree
+
+ case class GetClass(expr: Tree) extends Tree
+
+ case class CallHelper(helper: String, args: List[Tree]) extends Tree
+
+ case class JSNew(ctor: Tree, args: List[Tree]) extends Tree
+
+ case class JSDotSelect(qualifier: Tree, item: Ident) extends Tree
+
+ case class JSBracketSelect(qualifier: Tree, item: Tree) extends Tree
+
+ case class JSFunctionApply(fun: Tree, args: List[Tree]) extends Tree
+
+ case class JSDotMethodApply(receiver: Tree, method: Ident, args: List[Tree]) extends Tree
+
+ case class JSBracketMethodApply(receiver: Tree, method: Tree, args: List[Tree]) extends Tree
+
+ case class JSDelete(prop: Tree) extends Tree
+
+ case class JSUnaryOp(op: String, lhs: Tree) extends Tree
+
+ case class JSBinaryOp(op: String, lhs: Tree, rhs: Tree) extends Tree
+
+ case class JSArrayConstr(items: List[Tree]) extends Tree
+
+ case class JSObjectConstr(fields: List[(PropertyName, Tree)]) extends Tree
+
+ case class JSEnvInfo() extends Tree
+
+ sealed trait Literal extends Tree
+
+ case class Undefined() extends Literal
+
+ case class UndefinedParam() extends Literal
+
+ case class Null() extends Literal
+
+ case class BooleanLiteral(value: Boolean) extends Literal
+
+ case class IntLiteral(value: Int) extends Literal
+
+ case class LongLiteral(value: Long) extends Literal
+
+ case class FloatLiteral(value: Float) extends Literal
+
+ case class DoubleLiteral(value: Double) extends Literal
+
+ case class StringLiteral(value: String) extends Literal with PropertyName
+
+ case class ClassOf(cls: ReferenceType) extends Literal
+
+ case class VarRef(ident: Ident, mutable: Boolean) extends Tree
+
+ case class This() extends Tree
+
+ case class Closure(captureParams: List[ParamDef], params: List[ParamDef],
+ body: Tree, captureValues: List[Tree]) extends Tree
+
+ case class ClassDef(name: Ident, kind: ClassKind, parent: Option[Ident], ancestors: List[Ident], defs: List[Tree]) extends Tree
+
+ case class MethodDef(name: PropertyName, args: List[ParamDef], resultType: Type, body: Tree) extends Tree
+
+ case class PropertyDef(name: PropertyName, getterBody: Tree, setterArg: ParamDef, setterBody: Tree) extends Tree
+
+ case class ConstructorExportDef(name: String, args: List[ParamDef], body: Tree) extends Tree
+
+ case class ModuleExportDef(fullName: String) extends Tree
+
+ final class TreeHash(val treeHash: Array[Byte], val posHash: Array[Byte])
+}
+
+object Main {
+ import Trees._
+ import Types._
+
+ private def transform(tree: Tree) = {
+ val ObjectClass = "O"
+ tree match {
+ case VarDef(_, _, _, rhs) =>
+ case tree: Block =>
+ case Labeled(ident@Ident(label, _), tpe, body) =>
+ case Assign(lhs, rhs) =>
+ case Return(expr, optLabel) =>
+ case If(cond, thenp, elsep) =>
+ case While(cond, body, optLabel) =>
+ case DoWhile(body, cond, None) =>
+ case Try(block, errVar, EmptyTree, finalizer) =>
+ case Try(block, errVar@Ident(name, originalName), handler, finalizer) =>
+ case Throw(expr) =>
+ case Continue(optLabel) =>
+ case Match(selector, cases, default) =>
+ case New(cls, ctor, args) =>
+ case StoreModule(cls, value) =>
+ case tree: Select =>
+ case tree: Apply =>
+ case tree: StaticApply =>
+ case tree: TraitImplApply =>
+ case tree@UnaryOp(_, arg) =>
+ case tree@BinaryOp(op, lhs, rhs) =>
+ case NewArray(tpe, lengths) =>
+ case ArrayValue(tpe, elems) =>
+ case ArrayLength(array) =>
+ case ArraySelect(array, index) =>
+ case RecordValue(tpe, elems) =>
+ case IsInstanceOf(expr, ClassType(ObjectClass)) =>
+ case IsInstanceOf(expr, tpe) =>
+ case AsInstanceOf(expr, ClassType(ObjectClass)) =>
+ case AsInstanceOf(expr, cls) =>
+ case Unbox(arg, charCode) =>
+ case GetClass(expr) =>
+ case JSNew(ctor, args) =>
+ case JSDotSelect(qualifier, item) =>
+ case JSBracketSelect(qualifier, item) =>
+ case tree: JSFunctionApply =>
+ case JSDotMethodApply(receiver, method, args) =>
+ case JSBracketMethodApply(receiver, method, args) =>
+ case JSDelete(JSDotSelect(obj, prop)) =>
+ case JSDelete(JSBracketSelect(obj, prop)) =>
+ case JSUnaryOp(op, lhs) =>
+ case JSBinaryOp(op, lhs, rhs) =>
+ case JSArrayConstr(items) =>
+ case JSObjectConstr(fields) =>
+ case _: VarRef | _: This =>
+ case Closure(captureParams, params, body, captureValues) =>
+ case _: Skip | _: Debugger | _: LoadModule |
+ _: JSEnvInfo | _: Literal | EmptyTree =>
+ }
+ }
+} \ No newline at end of file
diff --git a/test/files/pos/t9050.scala b/test/files/pos/t9050.scala
new file mode 100644
index 0000000000..b1ab09f901
--- /dev/null
+++ b/test/files/pos/t9050.scala
@@ -0,0 +1,13 @@
+final class Mu[F](val value: Any) extends AnyVal {
+ def cata(f: F) {
+ // crash
+ ((y: Mu[F]) => y.cata(f))
+ // crash
+ def foo(x : Mu[F]) = x.cata(f)
+
+ // // okay
+ def x: Mu[F] = ???
+ (() => x.cata(f))
+ assert(true, cata(f))
+ }
+}
diff --git a/test/files/pos/t9086.scala b/test/files/pos/t9086.scala
new file mode 100644
index 0000000000..fba34ee226
--- /dev/null
+++ b/test/files/pos/t9086.scala
@@ -0,0 +1,8 @@
+class X[A](a: A)
+object Test {
+ implicit val ImplicitBoolean: Boolean = true
+ def local = {
+ implicit object X extends X({ implicitly[Boolean] ; "" })
+ implicitly[X[String]] // failed in 2.11.5
+ }
+}
diff --git a/test/files/pos/t9123.flags b/test/files/pos/t9123.flags
new file mode 100644
index 0000000000..c16e2f71dc
--- /dev/null
+++ b/test/files/pos/t9123.flags
@@ -0,0 +1 @@
+-optimize -Ydelambdafy:method
diff --git a/test/files/pos/t9123.scala b/test/files/pos/t9123.scala
new file mode 100644
index 0000000000..22d55b4351
--- /dev/null
+++ b/test/files/pos/t9123.scala
@@ -0,0 +1,10 @@
+trait Setting {
+ type T
+ def value: T
+}
+
+object Test {
+ def test(x: Some[Setting]) = x match {
+ case Some(dep) => Some(dep.value) map (_ => true)
+ }
+}
diff --git a/test/files/pos/t9135.scala b/test/files/pos/t9135.scala
new file mode 100644
index 0000000000..1e2c97baf9
--- /dev/null
+++ b/test/files/pos/t9135.scala
@@ -0,0 +1,16 @@
+
+class Free[A] {
+
+
+ this match {
+ case a @ Gosub() => gosub(a.a)(x => gosub(???)(???))
+ }
+ def gosub[A, B](a0: Free[A])(f0: A => Any): Free[B] = ???
+}
+
+
+
+ case class Gosub[B]() extends Free[B] {
+ type C
+ def a: Free[C] = ???
+ }
diff --git a/test/files/presentation/visibility/src/Completions.scala b/test/files/presentation/visibility/src/Completions.scala
index 8c07934915..69ec3959ad 100644
--- a/test/files/presentation/visibility/src/Completions.scala
+++ b/test/files/presentation/visibility/src/Completions.scala
@@ -11,7 +11,7 @@ package accessibility {
def secretPublic(): Unit
def someTests(other: Foo) {
- other./*!*/secretPrivate // should be all but scretThis
+ other./*!*/secretPrivate // should be all but secretThis
this./*!*/secretProtected // should hit five completions
}
@@ -25,7 +25,7 @@ package accessibility {
class UnrelatedClass {
def someTests(foo: Foo) {
- foo./*!*/ // should list public and protected[accessiblity]
+ foo./*!*/ // should list public and protected[accessibility]
}
}
diff --git a/test/files/res/t9089.check b/test/files/res/t9089.check
new file mode 100644
index 0000000000..6cf64f734b
--- /dev/null
+++ b/test/files/res/t9089.check
@@ -0,0 +1,4 @@
+
+nsc>
+nsc>
+nsc>
diff --git a/test/files/res/t9089.res b/test/files/res/t9089.res
new file mode 100644
index 0000000000..ab5cc8534d
--- /dev/null
+++ b/test/files/res/t9089.res
@@ -0,0 +1,2 @@
+t9089/A.scala
+t9089/A.scala
diff --git a/test/files/res/t9089/A.scala b/test/files/res/t9089/A.scala
new file mode 100644
index 0000000000..bccf269639
--- /dev/null
+++ b/test/files/res/t9089/A.scala
@@ -0,0 +1 @@
+object O { def f(x: => Int): Int = x }
diff --git a/test/files/run/applydynamic_sip.scala b/test/files/run/applydynamic_sip.scala
index cf918a82ed..47d0c6a303 100644
--- a/test/files/run/applydynamic_sip.scala
+++ b/test/files/run/applydynamic_sip.scala
@@ -40,7 +40,7 @@ object Test extends App {
// qual.sel(arg = a, a2: _*)
// qual.sel(arg, arg2 = "a2", a2: _*)
- // If qual.sel appears immediately on the left-hand side of an assigment
+ // If qual.sel appears immediately on the left-hand side of an assignment
// qual.updateDynamic(“sel”)(expr)
qual.sel = expr
diff --git a/test/files/run/bitsets.check b/test/files/run/bitsets.check
index 41c2ccdcb8..c24fd6238f 100644
--- a/test/files/run/bitsets.check
+++ b/test/files/run/bitsets.check
@@ -1,3 +1,4 @@
+warning: there were three deprecation warnings; re-run with -deprecation for details
ms0 = BitSet(2)
ms1 = BitSet(2)
ms2 = BitSet(2)
diff --git a/test/files/run/icode-reader-dead-code.check b/test/files/run/icode-reader-dead-code.check
index d1739fed3b..c9de93283e 100644
--- a/test/files/run/icode-reader-dead-code.check
+++ b/test/files/run/icode-reader-dead-code.check
@@ -1,4 +1,7 @@
Bytecode for method f
+
+ // access flags 0x11
+ public final f()I
L0
LINENUMBER 4 L0
ICONST_1
@@ -7,7 +10,11 @@ Bytecode for method f
LOCALVARIABLE this Lp/A; L0 L1 0
MAXSTACK = 1
MAXLOCALS = 1
+
Bytecode for method f
+
+ // access flags 0x11
+ public final f()I
L0
LINENUMBER 4 L0
ICONST_1
@@ -17,3 +24,4 @@ Bytecode for method f
LOCALVARIABLE this Lp/A; L0 L1 0
MAXSTACK = 1
MAXLOCALS = 1
+
diff --git a/test/files/run/t5313.scala b/test/files/run/t5313.scala
index 0d7168fa89..7f5af74c3f 100644
--- a/test/files/run/t5313.scala
+++ b/test/files/run/t5313.scala
@@ -11,7 +11,7 @@ object Test extends IcodeComparison {
def bar = {
var kept1 = new Object
val result = new java.lang.ref.WeakReference(kept1)
- kept1 = null // we can't eliminate this assigment because result can observe
+ kept1 = null // we can't eliminate this assignment because result can observe
// when the object has no more references. See SI-5313
kept1 = new Object // but we can eliminate this one because kept1 has already been clobbered
var erased2 = null // we can eliminate this store because it's never used
diff --git a/test/files/run/t6114.scala b/test/files/run/t6114.scala
index cb880ece00..8ad02d5bb2 100644
--- a/test/files/run/t6114.scala
+++ b/test/files/run/t6114.scala
@@ -51,7 +51,7 @@ object Test extends App {
val next = list.asScala ++ List(4,5,6)
assert(next != list.asScala)
- // Note: Clone is hidden at this level, so no overriden cloning.
+ // Note: Clone is hidden at this level, so no overridden cloning.
}
testList
diff --git a/test/files/run/t6502.check b/test/files/run/t6502.check
deleted file mode 100644
index 95d36ee221..0000000000
--- a/test/files/run/t6502.check
+++ /dev/null
@@ -1,8 +0,0 @@
-test1 res1: true
-test1 res2: true
-test2 res1: true
-test2 res2: true
-test3 res1: true
-test3 res2: true
-test4 res1: true
-test4 res2: true
diff --git a/test/files/run/t6502.scala b/test/files/run/t6502.scala
index 4ce034a482..52fabef6b8 100644
--- a/test/files/run/t6502.scala
+++ b/test/files/run/t6502.scala
@@ -46,6 +46,12 @@ object Test extends StoreReporterDirectTest {
}
}"""
+ def app6 = """
+ package test6
+ class A extends Test { println("created test6.A") }
+ class Z extends Test { println("created test6.Z") }
+ trait Test"""
+
def test1(): Unit = {
val jar = "test1.jar"
compileCode(app1, jar)
@@ -53,11 +59,12 @@ object Test extends StoreReporterDirectTest {
val codeToRun = toCodeInSeparateLines(s":require ${testOutput.path}/$jar", "test.Test.test()")
val output = ILoop.run(codeToRun, settings)
val lines = output.split("\n")
- val res1 = lines(4).contains("Added") && lines(4).contains("test1.jar")
- val res2 = lines(lines.length-3).contains("testing...")
-
- println(s"test1 res1: $res1")
- println(s"test1 res2: $res2")
+ assert {
+ lines(4).contains("Added") && lines(4).contains("test1.jar")
+ }
+ assert {
+ lines(lines.length-3).contains("testing...")
+ }
}
def test2(): Unit = {
@@ -69,11 +76,12 @@ object Test extends StoreReporterDirectTest {
val codeToRun = toCodeInSeparateLines(s":require ${testOutput.path}/$jar1", s":require ${testOutput.path}/$jar2")
val output = ILoop.run(codeToRun, settings)
val lines = output.split("\n")
- val res1 = lines(4).contains("Added") && lines(4).contains("test1.jar")
- val res2 = lines(lines.length-3).contains("test2.jar") && lines(lines.length-3).contains("existing classpath entries conflict")
-
- println(s"test2 res1: $res1")
- println(s"test2 res2: $res2")
+ assert {
+ lines(4).contains("Added") && lines(4).contains("test1.jar")
+ }
+ assert {
+ lines(lines.length-3).contains("test2.jar") && lines(lines.length-3).contains("existing classpath entries conflict")
+ }
}
def test3(): Unit = {
@@ -85,11 +93,12 @@ object Test extends StoreReporterDirectTest {
val codeToRun = toCodeInSeparateLines(s":require ${testOutput.path}/$jar1", s":require ${testOutput.path}/$jar3", "test.Test3.test()")
val output = ILoop.run(codeToRun, settings)
val lines = output.split("\n")
- val res1 = lines(4).contains("Added") && lines(4).contains("test1.jar")
- val res2 = lines(lines.length-3).contains("new object in existing package")
-
- println(s"test3 res1: $res1")
- println(s"test3 res2: $res2")
+ assert {
+ lines(4).contains("Added") && lines(4).contains("test1.jar")
+ }
+ assert {
+ lines(lines.length-3).contains("new object in existing package")
+ }
}
def test4(): Unit = {
@@ -98,11 +107,30 @@ object Test extends StoreReporterDirectTest {
val codeToRun = toCodeInSeparateLines(s":require ${testOutput.path}/$jar1", s":require ${testOutput.path}/$jar1")
val output = ILoop.run(codeToRun, settings)
val lines = output.split("\n")
- val res1 = lines(4).contains("Added") && lines(4).contains("test1.jar")
- val res2 = lines(lines.length-3).contains("test1.jar") && lines(lines.length-3).contains("existing classpath entries conflict")
+ assert {
+ lines(4).contains("Added") && lines(4).contains("test1.jar")
+ }
+ assert {
+ lines(lines.length-3).contains("test1.jar") && lines(lines.length-3).contains("existing classpath entries conflict")
+ }
+ }
- println(s"test4 res1: $res1")
- println(s"test4 res2: $res2")
+ def test5(): Unit = {
+ val codeToRun = ":require /does/not/exist.jar"
+ val output = ILoop.run(codeToRun, settings)
+ assert(!output.contains("NullPointerException"), output)
+ assert(output.contains("Cannot load '/does/not/exist.jar'"), output)
+ }
+
+ def test6(): Unit = {
+ // Avoid java.lang.NoClassDefFoundError triggered by the old appoach of using a Java
+ // classloader to parse .class files in order to read their names.
+ val jar = "test6.jar"
+ compileCode(app6, jar)
+ val codeToRun = toCodeInSeparateLines(s":require ${testOutput.path}/$jar", "import test6._; new A; new Z")
+ val output = ILoop.run(codeToRun, settings)
+ assert(output.contains("created test6.A"), output)
+ assert(output.contains("created test6.Z"), output)
}
def show(): Unit = {
@@ -110,7 +138,9 @@ object Test extends StoreReporterDirectTest {
test2()
test3()
test4()
+ test5()
+ test6()
}
- def toCodeInSeparateLines(lines: String*): String = lines.map(_ + "\n").mkString
+ def toCodeInSeparateLines(lines: String*): String = lines mkString "\n"
}
diff --git a/test/files/run/t7459a.scala b/test/files/run/t7459a.scala
new file mode 100644
index 0000000000..e9653c6e79
--- /dev/null
+++ b/test/files/run/t7459a.scala
@@ -0,0 +1,14 @@
+class LM {
+ class Node[B1]
+ case class CC(n: LM)
+
+ // crash
+ val f: (LM => Any) = {
+ case tttt =>
+ new tttt.Node[Any]()
+ }
+}
+
+object Test extends App {
+ new LM().f(new LM())
+}
diff --git a/test/files/run/t7459b-optimize.flags b/test/files/run/t7459b-optimize.flags
new file mode 100644
index 0000000000..49d036a887
--- /dev/null
+++ b/test/files/run/t7459b-optimize.flags
@@ -0,0 +1 @@
+-optimize
diff --git a/test/files/run/t7459b-optimize.scala b/test/files/run/t7459b-optimize.scala
new file mode 100644
index 0000000000..605890962c
--- /dev/null
+++ b/test/files/run/t7459b-optimize.scala
@@ -0,0 +1,21 @@
+class LM {
+ class Node[B1]
+
+ // crash
+ val g: (CC => Any) = {
+ case CC(tttt) =>
+ new tttt.Node[Any]()
+ }
+
+ val h: (Some[CC] => Any) = {
+ case Some(CC(tttt)) =>
+ new tttt.Node[Any]()
+ }
+}
+
+object Test extends App {
+ new LM().g(new CC(new LM()))
+ new LM().h(Some(new CC(new LM())))
+}
+case class CC(n: LM)
+
diff --git a/test/files/run/t7459b.scala b/test/files/run/t7459b.scala
new file mode 100644
index 0000000000..605890962c
--- /dev/null
+++ b/test/files/run/t7459b.scala
@@ -0,0 +1,21 @@
+class LM {
+ class Node[B1]
+
+ // crash
+ val g: (CC => Any) = {
+ case CC(tttt) =>
+ new tttt.Node[Any]()
+ }
+
+ val h: (Some[CC] => Any) = {
+ case Some(CC(tttt)) =>
+ new tttt.Node[Any]()
+ }
+}
+
+object Test extends App {
+ new LM().g(new CC(new LM()))
+ new LM().h(Some(new CC(new LM())))
+}
+case class CC(n: LM)
+
diff --git a/test/files/run/t7459c.scala b/test/files/run/t7459c.scala
new file mode 100644
index 0000000000..144c5d793b
--- /dev/null
+++ b/test/files/run/t7459c.scala
@@ -0,0 +1,16 @@
+class LM {
+ class Node[B1]
+
+ // crash
+ val g: (CC => Any) = {
+ case CC(tttt) =>
+ tttt.## // no crash
+ new tttt.Node[Any]()
+ }
+}
+
+object Test extends App {
+ new LM().g(new CC(new LM()))
+}
+case class CC(n: LM)
+
diff --git a/test/files/run/t7459d.scala b/test/files/run/t7459d.scala
new file mode 100644
index 0000000000..3263701f9d
--- /dev/null
+++ b/test/files/run/t7459d.scala
@@ -0,0 +1,15 @@
+class LM {
+ class Node[B1]
+ case class CC(n: LM)
+
+ // crash
+ val f: (LM => Any) = {
+ case tttt =>
+ val uuuu: (tttt.type, Any) = (tttt, 0)
+ new uuuu._1.Node[Any]()
+ }
+}
+
+object Test extends App {
+ new LM().f(new LM())
+}
diff --git a/test/files/run/t7459f.scala b/test/files/run/t7459f.scala
new file mode 100644
index 0000000000..63e2109560
--- /dev/null
+++ b/test/files/run/t7459f.scala
@@ -0,0 +1,12 @@
+object Test extends App {
+ class C
+
+ case class FooSeq(x: Int, y: String, z: C*)
+
+ FooSeq(1, "a", new C()) match {
+ case FooSeq(1, "a", x@_* ) =>
+ //println(x.toList)
+ x.asInstanceOf[x.type]
+ assert(x.isInstanceOf[x.type])
+ }
+}
diff --git a/test/files/run/t7965.scala b/test/files/run/t7965.scala
new file mode 100644
index 0000000000..df80d4b5bb
--- /dev/null
+++ b/test/files/run/t7965.scala
@@ -0,0 +1,54 @@
+// Test that scala doesn't apply boxing or varargs conversions to the
+// @PolymorphicSignature magical methods, MethodHandle#{invoke, invokeExact}
+object Test {
+ val code = """
+
+object O {
+ private def foo = "foo"
+ private def bar(x: Int): Int = -x
+ private def baz(x: Box): Unit = x.a = "present"
+ val lookup = java.lang.invoke.MethodHandles.lookup
+}
+
+import java.lang.invoke._
+class Box(var a: Any)
+
+object Test {
+ def main(args: Array[String]): Unit = {
+ def lookup(name: String, params: Array[Class[_]], ret: Class[_]) = {
+ val mt = MethodType.methodType(ret, params)
+ O.lookup.findVirtual(O.getClass, name, mt)
+ }
+ val fooResult = (lookup("foo", Array(), classOf[String]).invokeExact(O): Int)
+ assert(fooResult == "foo")
+
+ val barResult = (lookup("bar", Array(classOf[Int]), classOf[Int]).invokeExact(O, 42): Int)
+ assert(barResult == -42)
+
+ val box = new Box(null)
+ (lookup("baz", Array(classOf[Box]), Void.TYPE).invokeExact(O, box) : Unit)
+ assert(box.a == "present")
+
+ // Note: Application in statement position in a block in Java also infers return type of Unit,
+ // but we don't support that, ascribe the type to Unit as above.
+ // as done in Java.
+ // lookup("baz", Array(classOf[Box]), Void.TYPE).invokeExact(O, box)
+ ()
+ }
+}
+
+"""
+ def main(args: Array[String]): Unit = {
+ if (util.Properties.isJavaAtLeast("1.7")) test()
+ }
+
+ def test() {
+ import scala.reflect.runtime._
+ import scala.tools.reflect.ToolBox
+
+ val m = currentMirror
+ val tb = m.mkToolBox()
+ import tb._
+ eval(parse(code))
+ }
+}
diff --git a/test/files/run/t8253.scala b/test/files/run/t8253.scala
index c4800b4491..a00d8b91a4 100644
--- a/test/files/run/t8253.scala
+++ b/test/files/run/t8253.scala
@@ -10,5 +10,5 @@ object Test extends App {
show("<sample xmlns:foo={identity(ns1)}/>", q"<sample xmlns:foo={ns1}/>")
// `identity(foo)` used to match the overly permissive match in SymbolXMLBuilder
- // which was intented to more specifically match `_root_.scala.xml.Text(...)`
+ // which was intended to more specifically match `_root_.scala.xml.Text(...)`
}
diff --git a/test/files/run/t9030.scala b/test/files/run/t9030.scala
new file mode 100644
index 0000000000..48d24e5b54
--- /dev/null
+++ b/test/files/run/t9030.scala
@@ -0,0 +1,19 @@
+object Test extends App {
+
+ // For these methods, the compiler emits calls to BoxesRuntime.equalsNumNum/equalsNumChar/equalsNumObject directly
+
+ def numNum(a: java.lang.Number, b: java.lang.Number) = assert(a == b)
+ def numChar(a: java.lang.Number, b: java.lang.Character) = assert(a == b)
+ def numObject(a: java.lang.Number, b: java.lang.Object) = assert(a == b)
+
+ // The compiler doesn't use equalsCharObject directly, but still adding an example for completeness
+
+ def charObject(a: java.lang.Character, b: java.lang.Object) = assert(a == b)
+
+ numNum(new Integer(1), new Integer(1))
+ numChar(new Integer(97), new Character('a'))
+ numObject(new Integer(1), new Integer(1))
+ numObject(new Integer(97), new Character('a'))
+
+ charObject(new Character('a'), new Integer(97))
+}
diff --git a/test/files/run/t9097.scala b/test/files/run/t9097.scala
new file mode 100644
index 0000000000..d2bf55fc44
--- /dev/null
+++ b/test/files/run/t9097.scala
@@ -0,0 +1,34 @@
+import scala.tools.partest._
+import java.io.{Console => _, _}
+
+object Test extends StoreReporterDirectTest {
+
+ override def extraSettings: String = List(
+ "-usejavacp",
+ "-Xfatal-warnings",
+ "-Ybackend:GenBCode",
+ "-Ydelambdafy:method",
+ "-Xprint:delambdafy",
+ s"-d ${testOutput.path}"
+ ) mkString " "
+
+ override def code = """package o
+ |package a {
+ | class C {
+ | def hihi = List(1,2).map(_ * 2)
+ | }
+ |}
+ |package object a {
+ | def f = 1
+ |}
+ |""".stripMargin.trim
+
+ override def show(): Unit = {
+ val baos = new java.io.ByteArrayOutputStream()
+ Console.withOut(baos)(Console.withErr(baos)(compile()))
+ assert(!storeReporter.hasErrors, message = filteredInfos map (_.msg) mkString "; ")
+ val out = baos.toString("UTF-8")
+ // was 2 before the fix, the two PackageDefs for a would both contain the ClassDef for the closure
+ assert(out.lines.count(_ contains "class hihi$1") == 1, out)
+ }
+}
diff --git a/test/files/scalacheck/nan-ordering.scala b/test/files/scalacheck/nan-ordering.scala
index 2094a46e37..05e97a13c9 100644
--- a/test/files/scalacheck/nan-ordering.scala
+++ b/test/files/scalacheck/nan-ordering.scala
@@ -42,16 +42,16 @@ object Test extends Properties("NaN-Ordering") {
property("Float equiv") = forAll(specFloats, specFloats) { (d1, d2) => numFloat.equiv(d1, d2) == (d1 == d2) }
property("Float reverse.min") = forAll(specFloats, specFloats) { (d1, d2) => {
- val mathmin = math.min(d1, d2)
+ val mathmax = math.max(d1, d2)
val numericmin = numFloat.reverse.min(d1, d2)
- mathmin == numericmin || mathmin.isNaN && numericmin.isNaN
+ mathmax == numericmin || mathmax.isNaN && numericmin.isNaN
}
}
property("Float reverse.max") = forAll(specFloats, specFloats) { (d1, d2) => {
- val mathmax = math.max(d1, d2)
+ val mathmin = math.min(d1, d2)
val numericmax = numFloat.reverse.max(d1, d2)
- mathmax == numericmax || mathmax.isNaN && numericmax.isNaN
+ mathmin == numericmax || mathmin.isNaN && numericmax.isNaN
}
}
@@ -105,16 +105,16 @@ object Test extends Properties("NaN-Ordering") {
property("Double equiv") = forAll(specDoubles, specDoubles) { (d1, d2) => numDouble.equiv(d1, d2) == (d1 == d2) }
property("Double reverse.min") = forAll(specDoubles, specDoubles) { (d1, d2) => {
- val mathmin = math.min(d1, d2)
+ val mathmax = math.max(d1, d2)
val numericmin = numDouble.reverse.min(d1, d2)
- mathmin == numericmin || mathmin.isNaN && numericmin.isNaN
+ mathmax == numericmin || mathmax.isNaN && numericmin.isNaN
}
}
property("Double reverse.max") = forAll(specDoubles, specDoubles) { (d1, d2) => {
- val mathmax = math.max(d1, d2)
+ val mathmin = math.min(d1, d2)
val numericmax = numDouble.reverse.max(d1, d2)
- mathmax == numericmax || mathmax.isNaN && numericmax.isNaN
+ mathmin == numericmax || mathmin.isNaN && numericmax.isNaN
}
}
diff --git a/test/files/scalacheck/parallel-collections/ParallelIterableCheck.scala b/test/files/scalacheck/parallel-collections/ParallelIterableCheck.scala
index 774d6f428b..468bcb6dd1 100644
--- a/test/files/scalacheck/parallel-collections/ParallelIterableCheck.scala
+++ b/test/files/scalacheck/parallel-collections/ParallelIterableCheck.scala
@@ -36,7 +36,7 @@ abstract class ParallelIterableCheck[T](collName: String) extends Properties(col
// used to check if constructed collection is valid
def checkDataStructureInvariants(orig: Traversable[T], cf: AnyRef) = {
- // can be overriden in subclasses
+ // can be overridden in subclasses
true
}
diff --git a/test/instrumented/library/scala/runtime/ScalaRunTime.scala b/test/instrumented/library/scala/runtime/ScalaRunTime.scala
index e474ae737c..6b45a4e9f3 100644
--- a/test/instrumented/library/scala/runtime/ScalaRunTime.scala
+++ b/test/instrumented/library/scala/runtime/ScalaRunTime.scala
@@ -261,7 +261,7 @@ object ScalaRunTime {
*
* The primary motivation for this method is to provide a means for
* correctly obtaining a String representation of a value, while
- * avoiding the pitfalls of naïvely calling toString on said value.
+ * avoiding the pitfalls of naively calling toString on said value.
* In particular, it addresses the fact that (a) toString cannot be
* called on null and (b) depending on the apparent type of an
* array, toString may or may not print it in a human-readable form.
diff --git a/test/junit/scala/StringContextTest.scala b/test/junit/scala/StringContextTest.scala
index 608b82bd96..7e9e775d58 100644
--- a/test/junit/scala/StringContextTest.scala
+++ b/test/junit/scala/StringContextTest.scala
@@ -65,14 +65,23 @@ class StringContextTest {
@Test def fIf() = {
val res = f"${if (true) 2.5 else 2.5}%.2f"
- assertEquals("2.50", res)
+ val expected = formatUsingCurrentLocale(2.50)
+ assertEquals(expected, res)
}
+
@Test def fIfNot() = {
val res = f"${if (false) 2.5 else 3.5}%.2f"
- assertEquals("3.50", res)
+ val expected = formatUsingCurrentLocale(3.50)
+ assertEquals(expected, res)
}
+
@Test def fHeteroArgs() = {
val res = f"${3.14}%.2f rounds to ${3}%d"
- assertEquals("3.14 rounds to 3", res)
+ val expected = formatUsingCurrentLocale(3.14) + " rounds to 3"
+ assertEquals(expected, res)
}
+
+ // Use this method to avoid problems with a locale-dependent decimal mark.
+ // The string interpolation is not used here intentionally as this method is used to test string interpolation.
+ private def formatUsingCurrentLocale(number: Double, decimalPlaces: Int = 2) = ("%." + decimalPlaces + "f").format(number)
}
diff --git a/test/junit/scala/collection/IterableViewLikeTest.scala b/test/junit/scala/collection/IterableViewLikeTest.scala
index 55da02744b..ab09c4930b 100644
--- a/test/junit/scala/collection/IterableViewLikeTest.scala
+++ b/test/junit/scala/collection/IterableViewLikeTest.scala
@@ -4,6 +4,7 @@ import org.junit.Assert._
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.runners.JUnit4
+import language.postfixOps
@RunWith(classOf[JUnit4])
class IterableViewLikeTest {
diff --git a/test/junit/scala/collection/TraversableOnceTest.scala b/test/junit/scala/collection/TraversableOnceTest.scala
index 56d8312336..196174c199 100644
--- a/test/junit/scala/collection/TraversableOnceTest.scala
+++ b/test/junit/scala/collection/TraversableOnceTest.scala
@@ -43,8 +43,8 @@ class TraversableOnceTest {
def testReturnTheFirstMatch() = {
val d = List(1, 2, 3, 4, 5, 6, 7, 8)
def f(x: Int) = x % 3;
- assert(d.maxBy(f) == 2, "If multiple elements evaluted to the largest value, maxBy should return the first one.")
- assert(d.minBy(f) == 3, "If multiple elements evaluted to the largest value, minBy should return the first one.")
+ assert(d.maxBy(f) == 2, "If multiple elements evaluated to the largest value, maxBy should return the first one.")
+ assert(d.minBy(f) == 3, "If multiple elements evaluated to the largest value, minBy should return the first one.")
}
// Make sure it evaluates f no more than list.length times.
@@ -56,7 +56,7 @@ class TraversableOnceTest {
evaluatedCountOfMaxBy += 1
x * 10
})
- assert(evaluatedCountOfMaxBy == list.length, s"maxBy: should evaluate f only ${list.length} times, but it evaluted $evaluatedCountOfMaxBy times.")
+ assert(evaluatedCountOfMaxBy == list.length, s"maxBy: should evaluate f only ${list.length} times, but it evaluated $evaluatedCountOfMaxBy times.")
var evaluatedCountOfMinBy = 0
@@ -64,7 +64,7 @@ class TraversableOnceTest {
evaluatedCountOfMinBy += 1
x * 10
})
- assert(evaluatedCountOfMinBy == list.length, s"minBy: should evaluate f only ${list.length} times, but it evaluted $evaluatedCountOfMinBy times.")
+ assert(evaluatedCountOfMinBy == list.length, s"minBy: should evaluate f only ${list.length} times, but it evaluated $evaluatedCountOfMinBy times.")
}
}
diff --git a/test/junit/scala/collection/immutable/StringLikeTest.scala b/test/junit/scala/collection/immutable/StringLikeTest.scala
new file mode 100644
index 0000000000..3722bdfe4d
--- /dev/null
+++ b/test/junit/scala/collection/immutable/StringLikeTest.scala
@@ -0,0 +1,37 @@
+package scala.collection.immutable
+
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.JUnit4
+
+import scala.tools.testing.AssertUtil
+import scala.util.Random
+
+/* Test for SI-8988 */
+@RunWith(classOf[JUnit4])
+class StringLikeTest {
+ @Test
+ def testStringSplitWithChar: Unit = {
+ val chars = (0 to 255).map(_.toChar)
+ def randString = Random.nextString(30)
+
+ for (c <- chars) {
+ val s = randString
+ val jString = new java.lang.String(s)
+
+ // make sure we can match a literal character done by Java's split
+ val jSplit = jString.split("\\Q" + c.toString + "\\E")
+ val sSplit = s.split(c)
+ AssertUtil.assertSameElements(jSplit, sSplit, s"Not same result as Java split for char $c in string $s")
+ }
+ }
+
+ @Test
+ def testSplitEdgeCases: Unit = {
+ AssertUtil.assertSameElements("abcd".split('d'), Array("abc")) // not Array("abc", "")
+ AssertUtil.assertSameElements("abccc".split('c'), Array("ab")) // not Array("ab", "", "", "")
+ AssertUtil.assertSameElements("xxx".split('x'), Array[String]()) // not Array("", "", "", "")
+ AssertUtil.assertSameElements("".split('x'), Array("")) // not Array()
+ AssertUtil.assertSameElements("--ch--omp--".split("-"), Array("", "", "ch", "", "omp")) // All the cases!
+ }
+}
diff --git a/test/junit/scala/collection/immutable/VectorTest.scala b/test/junit/scala/collection/immutable/VectorTest.scala
new file mode 100644
index 0000000000..e7edba3e43
--- /dev/null
+++ b/test/junit/scala/collection/immutable/VectorTest.scala
@@ -0,0 +1,20 @@
+package scala.collection.immutable
+
+import org.junit.{Assert, Test}
+import org.junit.runner.RunWith
+import org.junit.runners.JUnit4
+
+@RunWith(classOf[JUnit4])
+class VectorTest {
+ /**
+ * Test Vector ++ with a small parallel collection concatenation (SI-9072).
+ *
+ */
+ @Test
+ def testPlusPlus(): Unit = {
+ val smallVec = (0 to 1)
+ val smallParVec = smallVec.par
+ val testElementsSize = (0 to 1000).map( _ => Vector.empty ++ smallParVec )
+ Assert.assertTrue(testElementsSize.forall( v => v.size == 2 ))
+ }
+}
diff --git a/test/junit/scala/collection/mutable/ArrayBufferTest.scala b/test/junit/scala/collection/mutable/ArrayBufferTest.scala
new file mode 100644
index 0000000000..8c83164027
--- /dev/null
+++ b/test/junit/scala/collection/mutable/ArrayBufferTest.scala
@@ -0,0 +1,36 @@
+package scala.collection.mutable
+
+import org.junit.runner.RunWith
+import org.junit.runners.JUnit4
+import org.junit.{Assert, Test}
+
+import scala.tools.testing.AssertUtil
+
+/* Test for SI-9043 */
+@RunWith(classOf[JUnit4])
+class ArrayBufferTest {
+ @Test
+ def testInsertAll: Unit = {
+ val traver = ArrayBuffer(2, 4, 5, 7)
+ val testSeq = List(1, 3, 6, 9)
+
+ def insertAt(x: Int) = {
+ val clone = traver.clone()
+ clone.insertAll(x, testSeq)
+ clone
+ }
+
+ // Just insert some at position 0
+ Assert.assertEquals(ArrayBuffer(1, 3, 6, 9, 2, 4, 5, 7), insertAt(0))
+
+ // Insert in the middle
+ Assert.assertEquals(ArrayBuffer(2, 4, 1, 3, 6, 9, 5, 7), insertAt(2))
+
+ // No strange last position weirdness
+ Assert.assertEquals(ArrayBuffer(2, 4, 5, 7, 1, 3, 6, 9), insertAt(traver.size))
+
+ // Overflow is caught
+ AssertUtil.assertThrows[IndexOutOfBoundsException] { insertAt(-1) }
+ AssertUtil.assertThrows[IndexOutOfBoundsException] { insertAt(traver.size + 10) }
+ }
+}
diff --git a/test/junit/scala/collection/mutable/LinkedHashMapTest.scala b/test/junit/scala/collection/mutable/LinkedHashMapTest.scala
new file mode 100644
index 0000000000..37dcd028a5
--- /dev/null
+++ b/test/junit/scala/collection/mutable/LinkedHashMapTest.scala
@@ -0,0 +1,25 @@
+package scala.collection.mutable
+
+import org.junit.runner.RunWith
+import org.junit.runners.JUnit4
+import org.junit.{ Assert, Test }
+
+import scala.collection.mutable
+
+/* Test for SI-9095 */
+@RunWith(classOf[JUnit4])
+class LinkedHashMapTest {
+ class TestClass extends mutable.LinkedHashMap[String, Int] {
+ def lastItemRef = lastEntry
+ }
+
+ @Test
+ def testClear: Unit = {
+ val lhm = new TestClass
+ Seq("a" -> 8, "b" -> 9).foreach(kv => lhm.put(kv._1, kv._2))
+
+ Assert.assertNotNull(lhm.lastItemRef)
+ lhm.clear()
+ Assert.assertNull(lhm.lastItemRef)
+ }
+}
diff --git a/test/junit/scala/collection/mutable/LinkedHashSetTest.scala b/test/junit/scala/collection/mutable/LinkedHashSetTest.scala
new file mode 100644
index 0000000000..b419ad37ec
--- /dev/null
+++ b/test/junit/scala/collection/mutable/LinkedHashSetTest.scala
@@ -0,0 +1,25 @@
+package scala.collection.mutable
+
+import org.junit.runner.RunWith
+import org.junit.runners.JUnit4
+import org.junit.{ Assert, Test }
+
+import scala.collection.mutable
+
+/* Test for SI-9095 */
+@RunWith(classOf[JUnit4])
+class LinkedHashSetTest {
+ class TestClass extends mutable.LinkedHashSet[String] {
+ def lastItemRef = lastEntry
+ }
+
+ @Test
+ def testClear: Unit = {
+ val lhs = new TestClass
+ Seq("a", "b").foreach(k => lhs.add(k))
+
+ Assert.assertNotNull(lhs.lastItemRef)
+ lhs.clear()
+ Assert.assertNull(lhs.lastItemRef)
+ }
+}
diff --git a/test/junit/scala/collection/mutable/MutableListTest.scala b/test/junit/scala/collection/mutable/MutableListTest.scala
new file mode 100644
index 0000000000..ac6d30def0
--- /dev/null
+++ b/test/junit/scala/collection/mutable/MutableListTest.scala
@@ -0,0 +1,37 @@
+package scala.collection.mutable
+
+import org.junit.runner.RunWith
+import org.junit.runners.JUnit4
+import org.junit.Test
+import org.junit.Assert._
+
+import scala.tools.testing.AssertUtil._
+
+@RunWith(classOf[JUnit4])
+class MutableListTest {
+
+ // Tests SI-8976
+ @Test def tailIteratorMustTerminateAtLength(): Unit = {
+ val is = MutableList(1,2,3)
+ val tl = is.tail
+ assertEquals(tl.length, tl.iterator.length)
+ is += 5
+ assertEquals(tl.length, tl.iterator.length)
+ assertSameElements(tl, tl.iterator)
+ }
+ @Test def iteratorMustFailEventually(): Unit = assertThrows[NoSuchElementException] {
+ MutableList[Unit]().iterator.next()
+ }
+ // was: Root empty iterator held reference
+ @Test def iteratorMustNotHoldOntoLast(): Unit = {
+ val is = MutableList(Some(1), Some(2))
+ val it = is.iterator
+ val x = Some(3)
+ is += x
+ assertNotReachable(x, it) {
+ it.next()
+ it.next()
+ }
+ assertTrue(it.isEmpty)
+ }
+}
diff --git a/test/junit/scala/io/SourceTest.scala b/test/junit/scala/io/SourceTest.scala
new file mode 100644
index 0000000000..3138a4589c
--- /dev/null
+++ b/test/junit/scala/io/SourceTest.scala
@@ -0,0 +1,86 @@
+
+package scala.io
+
+import org.junit.Test
+import org.junit.Assert._
+import org.junit.runner.RunWith
+import org.junit.runners.JUnit4
+
+import scala.tools.testing.AssertUtil._
+
+import java.io.{ Console => _, _ }
+
+@RunWith(classOf[JUnit4])
+class SourceTest {
+
+ private implicit val `our codec` = Codec.UTF8
+ private val charSet = Codec.UTF8.charSet.name
+
+ private def sampler = """
+ |Big-endian and little-endian approaches aren't
+ |readily interchangeable in general, because the
+ |laws of arithmetic send signals leftward from
+ |the bits that are "least significant."
+ |""".stripMargin.trim
+
+ private def in = new ByteArrayInputStream(sampler.getBytes)
+
+ @Test def canIterateLines() = {
+ assertEquals(sampler.lines.size, (Source fromString sampler).getLines.size)
+ }
+ @Test def canCustomizeReporting() = {
+ class CapitalReporting(is: InputStream) extends BufferedSource(is) {
+ override def report(pos: Int, msg: String, out: PrintStream): Unit = {
+ out print f"$pos%04x: ${msg.toUpperCase}"
+ }
+ class OffsetPositioner extends Positioner(null) {
+ override def next(): Char = {
+ ch = iter.next()
+ pos = pos + 1
+ ch
+ }
+ }
+ withPositioning(new OffsetPositioner)
+ }
+ val s = new CapitalReporting(in)
+ // skip to next line and report an error
+ do {
+ val c = s.next()
+ } while (s.ch != '\n')
+ s.next()
+ val out = new ByteArrayOutputStream
+ val ps = new PrintStream(out, true, charSet)
+ s.reportError(s.pos, "That doesn't sound right.", ps)
+ assertEquals("0030: THAT DOESN'T SOUND RIGHT.", out.toString(charSet))
+ }
+ @Test def canAltCustomizeReporting() = {
+ class CapitalReporting(is: InputStream)(implicit codec: Codec) extends Source {
+ override val iter = {
+ val r = new InputStreamReader(is, codec.decoder)
+ Iterator continually (codec wrap r.read()) takeWhile (_ != -1) map (_.toChar)
+ }
+ override def report(pos: Int, msg: String, out: PrintStream): Unit = {
+ out print f"$pos%04x: ${msg.toUpperCase}"
+ }
+ private[this] var _pos: Int = _
+ override def pos = _pos
+ private[this] var _ch: Char = _
+ override def ch = _ch
+ override def next = {
+ _ch = iter.next()
+ _pos += 1
+ _ch
+ }
+ }
+ val s = new CapitalReporting(in)
+ // skip to next line and report an error
+ do {
+ val c = s.next()
+ } while (s.ch != '\n')
+ s.next()
+ val out = new ByteArrayOutputStream
+ val ps = new PrintStream(out, true, charSet)
+ s.reportError(s.pos, "That doesn't sound right.", ps)
+ assertEquals("0030: THAT DOESN'T SOUND RIGHT.", out.toString(charSet))
+ }
+}
diff --git a/test/junit/scala/math/OrderingTest.scala b/test/junit/scala/math/OrderingTest.scala
new file mode 100644
index 0000000000..218622b8b4
--- /dev/null
+++ b/test/junit/scala/math/OrderingTest.scala
@@ -0,0 +1,61 @@
+package scala.math
+
+import org.junit.Assert._
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.JUnit4
+
+@RunWith(classOf[JUnit4])
+class OrderingTest {
+
+ /* Test for SI-9077 */
+ @Test
+ def testReverseOrdering {
+ def check[T: Ordering](t1: T, t2: T): Unit = {
+ val O = Ordering[T]
+ val R = O.reverse
+ assertEquals(O.min(t1, t2), R.max(t1, t2))
+ assertEquals(O.max(t1, t2), R.min(t1, t2))
+
+ assertEquals(O.lteq(t1, t2), R.lteq(t2, t1))
+ assertEquals(O.lt(t1, t2), R.lt(t2, t1))
+ assertEquals(O.gteq(t1, t2), R.gteq(t2, t1))
+ assertEquals(O.gt(t1, t2), R.gt(t2, t1))
+ assertEquals(O.compare(t1, t2), R.compare(t2, t1))
+
+ assertEquals(O.equiv(t1, t2), R.equiv(t1, t2))
+
+ assertEquals(O.on((x: T) => x).min(t1, t2), R.on((x: T) => x).max(t1, t2))
+
+ assertEquals(O.tryCompare(t1, t2), R.tryCompare(t2, t1))
+
+ assertEquals(O.mkOrderingOps(t1).<(t2), R.mkOrderingOps(t2).<(t1))
+ assertEquals(O.mkOrderingOps(t1).<=(t2), R.mkOrderingOps(t2).<=(t1))
+ assertEquals(O.mkOrderingOps(t1).>(t2), R.mkOrderingOps(t2).>(t1))
+ assertEquals(O.mkOrderingOps(t1).>=(t2), R.mkOrderingOps(t2).>=(t1))
+
+ assertEquals(O.mkOrderingOps(t1).min(t2), R.mkOrderingOps(t1).max(t2))
+ assertEquals(O.mkOrderingOps(t1).max(t2), R.mkOrderingOps(t1).min(t2))
+ }
+ def checkAll[T: Ordering](ts: T*): Unit = {
+ for (t1 <- ts; t2 <- ts) check(t1, t2)
+ }
+ checkAll[Unit](())
+ checkAll[Boolean](true, false)
+ checkAll[Byte](Byte.MinValue, -1.toByte, 0.toByte, 1.toByte, Byte.MaxValue)
+ checkAll[Char](Char.MinValue, -1.toChar, 0.toChar, 1.toChar, Char.MaxValue)
+ checkAll[Short](Short.MinValue, -1, 0, 1, Short.MaxValue)
+ checkAll[Int](Int.MinValue, -1, 0, 1, Int.MaxValue)
+ checkAll[Double](Double.MinValue, -1, -0, 0, 1, Double.MaxValue)
+ checkAll[Float](Float.MinValue, -1, -0, 0, 1, Float.MaxValue)
+
+ checkAll[BigInt](Int.MinValue, -1, 0, 1, Int.MaxValue)
+ checkAll[BigDecimal](Int.MinValue, -1, -0, 1, Int.MaxValue)
+ checkAll[String]("", "a", "b", "bb")
+ checkAll[String]("", "a", "b", "bb")
+ checkAll[Option[Int]](None, Some(1), Some(2))
+ checkAll[Iterable[Int]](Nil, List(1), List(1, 2))
+ checkAll[(Int, Int)]((1, 2), (1, 3), (4, 5))
+ }
+}
+
diff --git a/test/junit/scala/reflect/internal/PrintersTest.scala b/test/junit/scala/reflect/internal/PrintersTest.scala
index 7043c26d5e..9bfe6eecb8 100644
--- a/test/junit/scala/reflect/internal/PrintersTest.scala
+++ b/test/junit/scala/reflect/internal/PrintersTest.scala
@@ -125,6 +125,8 @@ trait BasePrintTests {
@Test def testName19 = assertPrintedCode("""class `class`""")
@Test def testName20 = assertPrintedCode("""class `test name`""")
+
+ @Test def testName21 = assertPrintedCode("""class `test.name`""")
@Test def testIfExpr1 = assertResultCode(code = sm"""
|val a = 1
diff --git a/test/junit/scala/tools/nsc/backend/jvm/BTypesTest.scala b/test/junit/scala/tools/nsc/backend/jvm/BTypesTest.scala
index 221aad6536..2347e8288e 100644
--- a/test/junit/scala/tools/nsc/backend/jvm/BTypesTest.scala
+++ b/test/junit/scala/tools/nsc/backend/jvm/BTypesTest.scala
@@ -19,7 +19,7 @@ class BTypesTest {
val btypes = new BTypesFromSymbols[g.type](g)
import btypes._
- duringBackend(btypes.intializeCoreBTypes())
+ duringBackend(btypes.initializeCoreBTypes())
def classBTypeFromSymbol(sym: Symbol) = duringBackend(btypes.classBTypeFromSymbol(sym))
diff --git a/test/junit/scala/tools/nsc/backend/jvm/opt/BTypesFromClassfileTest.scala b/test/junit/scala/tools/nsc/backend/jvm/opt/BTypesFromClassfileTest.scala
new file mode 100644
index 0000000000..2975bd060d
--- /dev/null
+++ b/test/junit/scala/tools/nsc/backend/jvm/opt/BTypesFromClassfileTest.scala
@@ -0,0 +1,95 @@
+package scala.tools.nsc
+package backend.jvm
+package opt
+
+import org.junit.runner.RunWith
+import org.junit.runners.JUnit4
+import org.junit.Test
+import scala.tools.asm.Opcodes._
+import org.junit.Assert._
+
+import scala.tools.nsc.backend.jvm.BTypes.InternalName
+import scala.tools.testing.AssertUtil._
+
+import CodeGenTools._
+import scala.tools.partest.ASMConverters
+import ASMConverters._
+
+import scala.collection.convert.decorateAsScala._
+
+@RunWith(classOf[JUnit4])
+class BTypesFromClassfileTest {
+ val compiler = newCompiler(extraArgs = "-Ybackend:GenBCode")
+
+ import compiler._
+ import definitions._
+ import genBCode.bTypes
+ import bTypes._
+
+ def duringBackend[T](f: => T) = compiler.exitingDelambdafy(f)
+
+ val run = new compiler.Run() // initializes some of the compiler
+ duringBackend(bTypes.initializeCoreBTypes())
+
+ def clearCache() = bTypes.classBTypeFromInternalName.clear()
+
+ def sameBType(fromSym: ClassBType, fromClassfile: ClassBType, checked: Set[InternalName] = Set.empty): Set[InternalName] = {
+ if (checked(fromSym.internalName)) checked
+ else {
+ assert(fromSym == fromClassfile, s"$fromSym != $fromClassfile")
+ sameInfo(fromSym.info, fromClassfile.info, checked + fromSym.internalName)
+ }
+ }
+
+ def sameBTypes(fromSyms: Iterable[ClassBType], fromClassfiles: Iterable[ClassBType], checked: Set[InternalName]): Set[InternalName] = {
+ assert(fromSyms.size == fromClassfiles.size, s"\n$fromSyms\n$fromClassfiles")
+ (fromSyms, fromClassfiles).zipped.foldLeft(checked) {
+ case (chk, (fromSym, fromClassfile)) => sameBType(fromSym, fromClassfile, chk)
+ }
+ }
+
+ def sameInfo(fromSym: ClassInfo, fromClassfile: ClassInfo, checked: Set[InternalName]): Set[InternalName] = {
+ assert({
+ // Nested class symbols can undergo makeNotPrivate (ExplicitOuter). But this is only applied
+ // for symbols of class symbols that are being compiled, not those read from a pickle.
+ // So a class may be public in bytecode, but the symbol still says private.
+ if (fromSym.nestedInfo.isEmpty) fromSym.flags == fromClassfile.flags
+ else (fromSym.flags | ACC_PRIVATE | ACC_PUBLIC) == (fromClassfile.flags | ACC_PRIVATE | ACC_PUBLIC)
+ }, s"class flags differ\n$fromSym\n$fromClassfile")
+
+ val chk1 = sameBTypes(fromSym.superClass, fromClassfile.superClass, checked)
+
+ val chk2 = sameBTypes(fromSym.interfaces, fromClassfile.interfaces, chk1)
+
+ // The fromSym info has only member classes, no local or anonymous. The symbol is read from the
+ // Scala pickle data and only member classes are created / entered.
+ // (This is different for symbols that are being compiled, there flatten will enter all local
+ // and anonymous classes as members of the outer class. But not for unpickled symbols).
+ // The fromClassfile info has all nested classes, including anonymous and local. So we filter
+ // them out: member classes are identified by having the `outerName` defined.
+ val memberClassesFromClassfile = fromClassfile.nestedClasses.filter(_.info.nestedInfo.get.outerName.isDefined)
+ // Sorting is required: the backend sorts all InnerClass entries by internalName before writing
+ // them to the classfile (to make it deterministic: the entries are collected in a Set during
+ // code generation).
+ val chk3 = sameBTypes(fromSym.nestedClasses.sortBy(_.internalName), memberClassesFromClassfile.sortBy(_.internalName), chk2)
+ sameBTypes(fromSym.nestedInfo.map(_.enclosingClass), fromClassfile.nestedInfo.map(_.enclosingClass), chk3)
+ }
+
+ def check(classSym: Symbol): Unit = duringBackend {
+ clearCache()
+ val fromSymbol = classBTypeFromSymbol(classSym)
+ clearCache()
+ val fromClassfile = bTypes.classBTypeFromParsedClassfile(fromSymbol.internalName)
+ sameBType(fromSymbol, fromClassfile)
+ }
+
+ @Test
+ def compareClassBTypes(): Unit = {
+ // Note that not only these classes are tested, but also all their parents and all nested
+ // classes in their InnerClass attributes.
+ check(ObjectClass)
+ check(JavaNumberClass)
+ check(ConsClass)
+ check(ListModule.moduleClass)
+ }
+}
diff --git a/test/junit/scala/tools/nsc/backend/jvm/opt/MethodLevelOpts.scala b/test/junit/scala/tools/nsc/backend/jvm/opt/MethodLevelOpts.scala
index 5b0f0f238a..5430e33d6c 100644
--- a/test/junit/scala/tools/nsc/backend/jvm/opt/MethodLevelOpts.scala
+++ b/test/junit/scala/tools/nsc/backend/jvm/opt/MethodLevelOpts.scala
@@ -74,7 +74,7 @@ class MethodLevelOpts {
""".stripMargin
val m = singleMethod(methodOptCompiler)(code)
assertTrue(m.handlers.length == 2)
- assertSameCode(m.instructions.dropNonOp, // drop line numbers and lables that are only used by line numbers
+ assertSameCode(m.instructions.dropNonOp, // drop line numbers and labels that are only used by line numbers
// one single label left :-)
List(Op(ICONST_1), VarOp(ISTORE, 2), Jump(GOTO, Label(20)), Op(POP), Op(ICONST_2), VarOp(ISTORE, 2), Jump(GOTO, Label(20)), VarOp(ASTORE, 3), Op(ICONST_2), Op(IRETURN), Label(20), Op(ICONST_2), Op(IRETURN))
diff --git a/test/junit/scala/tools/nsc/symtab/StdNamesTest.scala b/test/junit/scala/tools/nsc/symtab/StdNamesTest.scala
index 524d2e45e0..91f94e09b6 100644
--- a/test/junit/scala/tools/nsc/symtab/StdNamesTest.scala
+++ b/test/junit/scala/tools/nsc/symtab/StdNamesTest.scala
@@ -19,7 +19,7 @@ class StdNamesTest {
}
@Test
- def testNewTermNameNegativeLenght(): Unit = {
+ def testNewTermNameNegativeLength(): Unit = {
assertEquals(nme.EMPTY, newTermName("foo".toCharArray, 0, -1))
assertEquals(nme.EMPTY, newTermName("foo".toCharArray, 0, 0))
}
diff --git a/test/junit/scala/tools/nsc/symtab/SymbolTableTest.scala b/test/junit/scala/tools/nsc/symtab/SymbolTableTest.scala
index 11e955a4bb..895ad9d683 100644
--- a/test/junit/scala/tools/nsc/symtab/SymbolTableTest.scala
+++ b/test/junit/scala/tools/nsc/symtab/SymbolTableTest.scala
@@ -44,4 +44,9 @@ class SymbolTableTest {
assertFalse("Foo should be a superclass of Foo", fooSymbol.tpe <:< barSymbol.tpe)
}
+ @Test
+ def noSymbolOuterClass_t9133: Unit = {
+ import symbolTable._
+ assert(NoSymbol.outerClass == NoSymbol)
+ }
}
diff --git a/test/junit/scala/tools/nsc/transform/patmat/SolvingTest.scala b/test/junit/scala/tools/nsc/transform/patmat/SolvingTest.scala
new file mode 100644
index 0000000000..1fff9c9a32
--- /dev/null
+++ b/test/junit/scala/tools/nsc/transform/patmat/SolvingTest.scala
@@ -0,0 +1,555 @@
+package scala.tools.nsc.transform.patmat
+
+import org.junit.Assert._
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.JUnit4
+
+import scala.collection.mutable
+import scala.tools.nsc.{Global, Settings}
+
+object TestSolver extends Logic with Solving {
+
+ val global: Global = new Global(new Settings())
+
+ // disable max recursion depth in order to get all solutions
+ global.settings.YpatmatExhaustdepth.tryToSet("off" :: Nil)
+
+ object TestSolver extends Solver {
+
+ class Const {
+ override def toString: String = "Const"
+ }
+
+ val NullConst = new Const
+ type Type = Int
+
+ case class TypeConst(i: Int) extends Const
+
+ object TypeConst extends TypeConstExtractor
+
+ case class ValueConst(i: Int) extends Const
+
+ object ValueConst extends ValueConstExtractor {
+ def apply(t: Tree): Const = ???
+ }
+
+ case class Tree(name: String)
+
+ class Var(val x: Tree) extends AbsVar {
+
+ override def equals(other: scala.Any): Boolean = other match {
+ case that: Var => this.x == that.x
+ case _ => false
+ }
+
+ override def hashCode(): Int = x.hashCode()
+
+ override def toString: String = {
+ s"Var($x)"
+ }
+
+ def domainSyms = None
+
+ def implications = Nil
+
+ def mayBeNull = false
+
+ def propForEqualsTo(c: Const): Prop = ???
+
+ def registerEquality(c: Const) = ()
+
+ def registerNull() = ()
+
+ def symForStaticTp = None
+ }
+
+ object Var extends VarExtractor {
+ def apply(x: Tree): Var = new Var(x)
+
+ def unapply(v: Var): Some[Tree] = Some(v.x)
+ }
+
+ def prepareNewAnalysis() = {}
+
+ def reportWarning(msg: String) = sys.error(msg)
+
+ /**
+ * The DPLL procedure only returns a minimal mapping from literal to value
+ * such that the CNF formula is satisfied.
+ * E.g. for:
+ * `(a \/ b)`
+ * The DPLL procedure will find either {a = true} or {b = true}
+ * as solution.
+ *
+ * The expansion step will amend both solutions with the unassigned variable
+ * i.e., {a = true} will be expanded to {a = true, b = true} and
+ * {a = true, b = false}.
+ */
+ def expandUnassigned(solution: Solution): List[Model] = {
+ import solution._
+
+ // the number of solutions is doubled for every unassigned variable
+ val expandedModels = 1 << unassigned.size
+ var current = mutable.ArrayBuffer[Model]()
+ var next = mutable.ArrayBuffer[Model]()
+ current.sizeHint(expandedModels)
+ next.sizeHint(expandedModels)
+
+ current += model
+
+ // we use double buffering:
+ // read from `current` and create a two models for each model in `next`
+ for {
+ s <- unassigned
+ } {
+ for {
+ model <- current
+ } {
+ def force(s: Sym, pol: Boolean) = model + (s -> pol)
+
+ next += force(s, pol = true)
+ next += force(s, pol = false)
+ }
+
+ val tmp = current
+ current = next
+ next = tmp
+
+ next.clear()
+ }
+
+ current.toList
+ }
+
+ /**
+ * Old CNF conversion code, used for reference:
+ * - convert formula into NNF
+ * (i.e., no negated terms, only negated variables)
+ * - use distributive laws to convert into CNF
+ */
+ def eqFreePropToSolvableViaDistribution(p: Prop) = {
+ val symbolMapping = new SymbolMapping(gatherSymbols(p))
+
+ type Formula = Array[TestSolver.Clause]
+
+ def formula(c: Clause*): Formula = c.toArray
+
+ def merge(a: Clause, b: Clause) = a ++ b
+
+ def negationNormalFormNot(p: Prop): Prop = p match {
+ case And(ps) => Or(ps map negationNormalFormNot)
+ case Or(ps) => And(ps map negationNormalFormNot)
+ case Not(p) => negationNormalForm(p)
+ case True => False
+ case False => True
+ case s: Sym => Not(s)
+ }
+
+ def negationNormalForm(p: Prop): Prop = p match {
+ case Or(ps) => Or(ps map negationNormalForm)
+ case And(ps) => And(ps map negationNormalForm)
+ case Not(negated) => negationNormalFormNot(negated)
+ case True
+ | False
+ | (_: Sym) => p
+ }
+
+ val TrueF: Formula = Array()
+ val FalseF = Array(clause())
+ def lit(sym: Sym) = Array(clause(symbolMapping.lit(sym)))
+ def negLit(sym: Sym) = Array(clause(-symbolMapping.lit(sym)))
+
+ def conjunctiveNormalForm(p: Prop): Formula = {
+ def distribute(a: Formula, b: Formula): Formula =
+ (a, b) match {
+ // true \/ _ = true
+ // _ \/ true = true
+ case (trueA, trueB) if trueA.size == 0 || trueB.size == 0 => TrueF
+ // lit \/ lit
+ case (a, b) if a.size == 1 && b.size == 1 => formula(merge(a(0), b(0)))
+ // (c1 /\ ... /\ cn) \/ d = ((c1 \/ d) /\ ... /\ (cn \/ d))
+ // d \/ (c1 /\ ... /\ cn) = ((d \/ c1) /\ ... /\ (d \/ cn))
+ case (cs, ds) =>
+ val (big, small) = if (cs.size > ds.size) (cs, ds) else (ds, cs)
+ big flatMap (c => distribute(formula(c), small))
+ }
+
+ p match {
+ case True => TrueF
+ case False => FalseF
+ case s: Sym => lit(s)
+ case Not(s: Sym) => negLit(s)
+ case And(ps) =>
+ ps.toArray flatMap conjunctiveNormalForm
+ case Or(ps) =>
+ ps map conjunctiveNormalForm reduceLeft { (a, b) =>
+ distribute(a, b)
+ }
+ }
+ }
+ val cnf = conjunctiveNormalForm(negationNormalForm(p))
+ Solvable(cnf, symbolMapping)
+ }
+
+ }
+
+}
+
+/**
+ * Testing CNF conversion via Tseitin vs NNF & expansion.
+ */
+@RunWith(classOf[JUnit4])
+class SolvingTest {
+
+ import scala.tools.nsc.transform.patmat.TestSolver.TestSolver._
+
+ implicit val Ord: Ordering[TestSolver.TestSolver.Model] = Ordering.by {
+ _.toSeq.sortBy(_.toString()).toIterable
+ }
+
+ private def sym(name: String) = Sym(Var(Tree(name)), NullConst)
+
+ @Test
+ def testSymCreation() {
+ val s1 = sym("hello")
+ val s2 = sym("hello")
+ assertEquals(s1, s2)
+ }
+
+ /**
+ * Simplest possible test: solve a formula and check the solution(s)
+ */
+ @Test
+ def testUnassigned() {
+ val pSym = sym("p")
+ val solvable = propToSolvable(Or(pSym, Not(pSym)))
+ val solutions = TestSolver.TestSolver.findAllModelsFor(solvable)
+ val expected = List(Solution(Map(), List(pSym)))
+ assertEquals(expected, solutions)
+ }
+
+ /**
+ * Unassigned variables must be expanded
+ * for stable results
+ */
+ @Test
+ def testNoUnassigned() {
+ val pSym = sym("p")
+ val qSym = sym("q")
+ val solvable = propToSolvable(Or(pSym, Not(qSym)))
+ val solutions = findAllModelsFor(solvable)
+ val expanded = solutions.flatMap(expandUnassigned).sorted
+ val expected = Seq(
+ Map(pSym -> false, qSym -> false),
+ Map(pSym -> true, qSym -> false),
+ Map(pSym -> true, qSym -> true)
+ ).sorted
+
+ assertEquals(expected, expanded)
+ }
+
+ @Test
+ def testTseitinVsExpansionFrom_t7020() {
+ val formulas = Seq(
+ And(And(And(Not(sym("V1=null")),
+ sym("V1=scala.collection.immutable.::[?]")), And(Not(sym("V1=null")),
+ And(Or(sym("V2=4"), Or(sym("V2=5"), sym("V2=6"))), sym("V3=Nil")))),
+ And(And(Or(Not(sym("V1=scala.collection.immutable.::[?]")),
+ Not(sym("V1=null"))), And(Or(sym("V3=scala.collection.immutable.::[?]"),
+ Or(sym("V3=Nil"), sym("V3=null"))), And(Or(Not(sym("V3=Nil")),
+ Not(sym("V3=null"))),
+ And(Or(Not(sym("V3=scala.collection.immutable.::[?]")),
+ Not(sym("V3=null"))), And(Or(Not(sym("V1=Nil")), Not(sym("V1=null"))),
+ Or(sym("V1=scala.collection.immutable.::[?]"), Or(sym("V1=Nil"),
+ sym("V1=null")))))))), And(Or(Or(sym("V1=null"),
+ Not(sym("V1=scala.collection.immutable.::[?]"))), Or(sym("V1=null"),
+ Or(Not(sym("V2=1")), Not(sym("V3=Nil"))))), Or(Or(sym("V1=null"),
+ Not(sym("V1=scala.collection.immutable.::[?]"))), Or(sym("V1=null"),
+ Or(Not(sym("V2=2")), Not(sym("V3=Nil")))))))),
+
+ And(And(And(Not(sym("V1=null")),
+ sym("V1=scala.collection.immutable.::[?]")), And(Not(sym("V1=null")),
+ And(sym("V2=7"), sym("V3=Nil")))),
+ And(And(Or(Not(sym("V1=scala.collection.immutable.::[?]")),
+ Not(sym("V1=null"))), And(Or(sym("V3=scala.collection.immutable.::[?]"),
+ Or(sym("V3=Nil"), sym("V3=null"))), And(Or(Not(sym("V3=Nil")),
+ Not(sym("V3=null"))),
+ And(Or(Not(sym("V3=scala.collection.immutable.::[?]")),
+ Not(sym("V3=null"))), And(Or(Not(sym("V1=Nil")), Not(sym("V1=null"))),
+ Or(sym("V1=scala.collection.immutable.::[?]"), Or(sym("V1=Nil"),
+ sym("V1=null")))))))), And(And(Or(Or(sym("V1=null"),
+ Not(sym("V1=scala.collection.immutable.::[?]"))), Or(sym("V1=null"),
+ Or(Not(sym("V2=1")), Not(sym("V3=Nil"))))), Or(Or(sym("V1=null"),
+ Not(sym("V1=scala.collection.immutable.::[?]"))), Or(sym("V1=null"),
+ Or(Not(sym("V2=2")), Not(sym("V3=Nil")))))), Or(Or(sym("V1=null"),
+ Not(sym("V1=scala.collection.immutable.::[?]"))), Or(sym("V1=null"),
+ Or(And(Not(sym("V2=4")), And(Not(sym("V2=5")), Not(sym("V2=6")))),
+ Not(sym("V3=Nil")))))))),
+
+ And(And(Not(sym("V1=null")),
+ sym("V1=scala.collection.immutable.::[?]")), And(Not(sym("V1=null")),
+ And(Or(sym("V2=4"), Or(sym("V2=5"), sym("V2=6"))), sym("V3=Nil")))),
+
+ And(And(Not(sym("V1=null")), sym("V1=scala.collection.immutable.::[?]")),
+ And(Not(sym("V1=null")), And(sym("V2=7"), sym("V3=Nil")))),
+
+ And(And(Or(Not(sym("V1=scala.collection.immutable.::[?]")),
+ Not(sym("V1=null"))), And(Or(sym("V3=scala.collection.immutable.::[?]"),
+ Or(sym("V3=Nil"), sym("V3=null"))), And(Or(Not(sym("V3=Nil")),
+ Not(sym("V3=null"))),
+ And(Or(Not(sym("V3=scala.collection.immutable.::[?]")),
+ Not(sym("V3=null"))), And(Or(Not(sym("V1=Nil")), Not(sym("V1=null"))),
+ Or(sym("V1=scala.collection.immutable.::[?]"), Or(sym("V1=Nil"),
+ sym("V1=null")))))))), And(And(Or(Or(sym("V1=null"),
+ Not(sym("V1=scala.collection.immutable.::[?]"))), Or(sym("V1=null"),
+ Or(Not(sym("V2=1")), Not(sym("V3=Nil"))))), Or(Or(sym("V1=null"),
+ Not(sym("V1=scala.collection.immutable.::[?]"))), Or(sym("V1=null"),
+ Or(Not(sym("V2=2")), Not(sym("V3=Nil")))))), Or(Or(sym("V1=null"),
+ Not(sym("V1=scala.collection.immutable.::[?]"))), Or(sym("V1=null"),
+ Or(And(Not(sym("V2=4")), And(Not(sym("V2=5")), Not(sym("V2=6")))),
+ Not(sym("V3=Nil"))))))),
+
+ And(And(Or(Not(sym("V1=scala.collection.immutable.::[?]")),
+ Not(sym("V1=null"))), And(Or(sym("V3=scala.collection.immutable.::[?]"),
+ Or(sym("V3=Nil"), sym("V3=null"))), And(Or(Not(sym("V3=Nil")),
+ Not(sym("V3=null"))),
+ And(Or(Not(sym("V3=scala.collection.immutable.::[?]")),
+ Not(sym("V3=null"))), And(Or(Not(sym("V1=Nil")), Not(sym("V1=null"))),
+ Or(sym("V1=scala.collection.immutable.::[?]"), Or(sym("V1=Nil"),
+ sym("V1=null")))))))), And(Or(Or(sym("V1=null"),
+ Not(sym("V1=scala.collection.immutable.::[?]"))), Or(sym("V1=null"),
+ Or(Not(sym("V2=1")), Not(sym("V3=Nil"))))), Or(Or(sym("V1=null"),
+ Not(sym("V1=scala.collection.immutable.::[?]"))), Or(sym("V1=null"),
+ Or(Not(sym("V2=2")), Not(sym("V3=Nil"))))))),
+
+ And(And(Or(Not(sym("V1=scala.collection.immutable.::[?]")),
+ Not(sym("V1=null"))), And(Or(sym("V3=scala.collection.immutable.::[?]"),
+ Or(sym("V3=Nil"), sym("V3=null"))), And(Or(Not(sym("V3=Nil")),
+ Not(sym("V3=null"))),
+ And(Or(Not(sym("V3=scala.collection.immutable.::[?]")),
+ Not(sym("V3=null"))), And(Or(Not(sym("V1=Nil")), Not(sym("V1=null"))),
+ Or(sym("V1=scala.collection.immutable.::[?]"), Or(sym("V1=Nil"),
+ sym("V1=null")))))))), And(sym("V1=Nil"), And(Or(Or(sym("V1=null"),
+ Not(sym("V1=scala.collection.immutable.::[?]"))), Or(sym("V1=null"),
+ Or(And(Not(sym("V2=4")), And(Not(sym("V2=5")), Not(sym("V2=6")))),
+ Not(sym("V3=Nil"))))), And(Or(Or(sym("V1=null"),
+ Not(sym("V1=scala.collection.immutable.::[?]"))), Or(sym("V1=null"),
+ Or(Not(sym("V2=1")), Not(sym("V3=Nil"))))), Or(Or(sym("V1=null"),
+ Not(sym("V1=scala.collection.immutable.::[?]"))), Or(sym("V1=null"),
+ Or(Not(sym("V2=2")), Not(sym("V3=Nil"))))))))),
+
+ And(And(Or(Or(False,
+ Not(sym("V1=scala.collection.immutable.::[?]"))), Or(False,
+ Or(Not(sym("V2=1")), Not(sym("V3=Nil"))))), Or(Or(False,
+ Not(sym("V1=scala.collection.immutable.::[?]"))), Or(False,
+ Or(Not(sym("V2=2")), Not(sym("V3=Nil")))))), And(Or(Or(False,
+ Not(sym("V1=scala.collection.immutable.::[?]"))), Or(False,
+ Or(And(Not(sym("V2=4")), And(Not(sym("V2=5")), Not(sym("V2=6")))),
+ Not(sym("V3=Nil"))))), And(Or(Or(False,
+ Not(sym("V1=scala.collection.immutable.::[?]"))), Or(False,
+ Or(Not(sym("V2=7")), Not(sym("V3=Nil"))))), Not(sym("V1=Nil"))))),
+
+ And(And(Or(Or(sym("V1=null"),
+ Not(sym("V1=scala.collection.immutable.::[?]"))), Or(sym("V1=null"),
+ Or(Not(sym("V2=1")), Not(sym("V3=Nil"))))), Or(Or(sym("V1=null"),
+ Not(sym("V1=scala.collection.immutable.::[?]"))), Or(sym("V1=null"),
+ Or(Not(sym("V2=2")), Not(sym("V3=Nil")))))), Or(Or(sym("V1=null"),
+ Not(sym("V1=scala.collection.immutable.::[?]"))), Or(sym("V1=null"),
+ Or(And(Not(sym("V2=4")), And(Not(sym("V2=5")), Not(sym("V2=6")))),
+ Not(sym("V3=Nil")))))),
+
+ And(And(Or(sym("V3=scala.collection.immutable.::[?]"), sym("V3=Nil")),
+ Or(sym("V1=scala.collection.immutable.::[?]"), sym("V1=Nil"))),
+ And(And(Or(Or(False, Not(sym("V1=scala.collection.immutable.::[?]"))),
+ Or(False, Or(Not(sym("V2=1")), Not(sym("V3=Nil"))))), Or(Or(False,
+ Not(sym("V1=scala.collection.immutable.::[?]"))), Or(False,
+ Or(Not(sym("V2=2")), Not(sym("V3=Nil")))))), And(Or(Or(False,
+ Not(sym("V1=scala.collection.immutable.::[?]"))), Or(False,
+ Or(And(Not(sym("V2=4")), And(Not(sym("V2=5")), Not(sym("V2=6")))),
+ Not(sym("V3=Nil"))))), And(Or(Or(False,
+ Not(sym("V1=scala.collection.immutable.::[?]"))), Or(False,
+ Or(Not(sym("V2=7")), Not(sym("V3=Nil"))))), Not(sym("V1=Nil")))))),
+
+ And(Not(sym("V1=null")), And(Or(sym("V2=4"), Or(sym("V2=5"), sym("V2=6"))),
+ sym("V3=Nil"))),
+
+ And(Not(sym("V1=null")), And(sym("V2=7"), sym("V3=Nil"))),
+
+ And(Not(sym("V1=null")), sym("V1=scala.collection.immutable.::[?]")),
+
+ And(Not(sym("V2=4")), And(Not(sym("V2=5")), Not(sym("V2=6")))),
+
+ And(Not(sym("V2=5")), Not(sym("V2=6"))),
+
+ And(Or(Not(sym("V1=Nil")), Not(sym("V1=null"))),
+ Or(sym("V1=scala.collection.immutable.::[?]"), Or(sym("V1=Nil"),
+ sym("V1=null")))),
+
+ And(Or(Not(sym("V1=scala.collection.immutable.::[?]")),
+ Not(sym("V1=null"))), And(Or(sym("V3=scala.collection.immutable.::[?]"),
+ Or(sym("V3=Nil"), sym("V3=null"))), And(Or(Not(sym("V3=Nil")),
+ Not(sym("V3=null"))),
+ And(Or(Not(sym("V3=scala.collection.immutable.::[?]")),
+ Not(sym("V3=null"))), And(Or(Not(sym("V1=Nil")), Not(sym("V1=null"))),
+ Or(sym("V1=scala.collection.immutable.::[?]"), Or(sym("V1=Nil"),
+ sym("V1=null")))))))),
+
+ And(Or(Not(sym("V3=Nil")), Not(sym("V3=null"))),
+ And(Or(Not(sym("V3=scala.collection.immutable.::[?]")),
+ Not(sym("V3=null"))), And(Or(Not(sym("V1=Nil")), Not(sym("V1=null"))),
+ Or(sym("V1=scala.collection.immutable.::[?]"), Or(sym("V1=Nil"),
+ sym("V1=null")))))),
+
+ And(Or(Not(sym("V3=scala.collection.immutable.::[?]")),
+ Not(sym("V3=null"))), And(Or(Not(sym("V1=Nil")), Not(sym("V1=null"))),
+ Or(sym("V1=scala.collection.immutable.::[?]"), Or(sym("V1=Nil"),
+ sym("V1=null"))))),
+
+ And(Or(Or(False,
+ Not(sym("V1=scala.collection.immutable.::[?]"))), Or(False,
+ Or(And(Not(sym("V2=4")), And(Not(sym("V2=5")), Not(sym("V2=6")))),
+ Not(sym("V3=Nil"))))), And(Or(Or(False,
+ Not(sym("V1=scala.collection.immutable.::[?]"))), Or(False,
+ Or(Not(sym("V2=7")), Not(sym("V3=Nil"))))), Not(sym("V1=Nil")))),
+
+ And(Or(Or(False, Not(sym("V1=scala.collection.immutable.::[?]"))), Or(False,
+ Or(Not(sym("V2=1")), Not(sym("V3=Nil"))))), Or(Or(False,
+ Not(sym("V1=scala.collection.immutable.::[?]"))), Or(False,
+ Or(Not(sym("V2=2")), Not(sym("V3=Nil")))))),
+
+ And(Or(Or(False,
+ Not(sym("V1=scala.collection.immutable.::[?]"))), Or(False,
+ Or(Not(sym("V2=7")), Not(sym("V3=Nil"))))), Not(sym("V1=Nil"))),
+
+ And(Or(Or(sym("V1=null"), Not(sym("V1=scala.collection.immutable.::[?]"))),
+ Or(sym("V1=null"), Or(And(Not(sym("V2=4")), And(Not(sym("V2=5")),
+ Not(sym("V2=6")))), Not(sym("V3=Nil"))))), And(Or(Or(sym("V1=null"),
+ Not(sym("V1=scala.collection.immutable.::[?]"))), Or(sym("V1=null"),
+ Or(Not(sym("V2=1")), Not(sym("V3=Nil"))))), Or(Or(sym("V1=null"),
+ Not(sym("V1=scala.collection.immutable.::[?]"))), Or(sym("V1=null"),
+ Or(Not(sym("V2=2")), Not(sym("V3=Nil"))))))),
+
+ And(Or(Or(sym("V1=null"),
+ Not(sym("V1=scala.collection.immutable.::[?]"))), Or(sym("V1=null"),
+ Or(Not(sym("V2=1")), Not(sym("V3=Nil"))))), Or(Or(sym("V1=null"),
+ Not(sym("V1=scala.collection.immutable.::[?]"))), Or(sym("V1=null"),
+ Or(Not(sym("V2=2")), Not(sym("V3=Nil")))))),
+
+ And(Or(Or(sym("V1=null"),
+ Not(sym("V1=scala.collection.immutable.::[?]"))), Or(sym("V1=null"),
+ Or(Not(sym("V2=7")), Not(sym("V3=Nil"))))),
+ And(And(Or(Not(sym("V1=scala.collection.immutable.::[?]")),
+ Not(sym("V1=null"))), And(Or(sym("V3=scala.collection.immutable.::[?]"),
+ Or(sym("V3=Nil"), sym("V3=null"))), And(Or(Not(sym("V3=Nil")),
+ Not(sym("V3=null"))),
+ And(Or(Not(sym("V3=scala.collection.immutable.::[?]")),
+ Not(sym("V3=null"))), And(Or(Not(sym("V1=Nil")), Not(sym("V1=null"))),
+ Or(sym("V1=scala.collection.immutable.::[?]"), Or(sym("V1=Nil"),
+ sym("V1=null")))))))), And(sym("V1=Nil"), And(Or(Or(sym("V1=null"),
+ Not(sym("V1=scala.collection.immutable.::[?]"))), Or(sym("V1=null"),
+ Or(And(Not(sym("V2=4")), And(Not(sym("V2=5")), Not(sym("V2=6")))),
+ Not(sym("V3=Nil"))))), And(Or(Or(sym("V1=null"),
+ Not(sym("V1=scala.collection.immutable.::[?]"))), Or(sym("V1=null"),
+ Or(Not(sym("V2=1")), Not(sym("V3=Nil"))))), Or(Or(sym("V1=null"),
+ Not(sym("V1=scala.collection.immutable.::[?]"))), Or(sym("V1=null"),
+ Or(Not(sym("V2=2")), Not(sym("V3=Nil")))))))))),
+
+ And(Or(sym("V2=4"), Or(sym("V2=5"), sym("V2=6"))), sym("V3=Nil")),
+
+ And(Or(sym("V3=scala.collection.immutable.::[?]"), Or(sym("V3=Nil"),
+ sym("V3=null"))), And(Or(Not(sym("V3=Nil")), Not(sym("V3=null"))),
+ And(Or(Not(sym("V3=scala.collection.immutable.::[?]")),
+ Not(sym("V3=null"))), And(Or(Not(sym("V1=Nil")), Not(sym("V1=null"))),
+ Or(sym("V1=scala.collection.immutable.::[?]"), Or(sym("V1=Nil"),
+ sym("V1=null"))))))),
+
+ And(Or(sym("V3=scala.collection.immutable.::[?]"),
+ sym("V3=Nil")), Or(sym("V1=scala.collection.immutable.::[?]"),
+ sym("V1=Nil"))),
+
+ And(sym("V1=Nil"), And(Or(Or(sym("V1=null"),
+ Not(sym("V1=scala.collection.immutable.::[?]"))), Or(sym("V1=null"),
+ Or(And(Not(sym("V2=4")), And(Not(sym("V2=5")), Not(sym("V2=6")))),
+ Not(sym("V3=Nil"))))), And(Or(Or(sym("V1=null"),
+ Not(sym("V1=scala.collection.immutable.::[?]"))), Or(sym("V1=null"),
+ Or(Not(sym("V2=1")), Not(sym("V3=Nil"))))), Or(Or(sym("V1=null"),
+ Not(sym("V1=scala.collection.immutable.::[?]"))), Or(sym("V1=null"),
+ Or(Not(sym("V2=2")), Not(sym("V3=Nil")))))))),
+
+ And(sym("V2=7"), sym("V3=Nil")),
+
+ False,
+
+ Not(sym("V1=Nil")),
+
+ Or(And(Not(sym("V2=4")),
+ And(Not(sym("V2=5")), Not(sym("V2=6")))), Not(sym("V3=Nil"))),
+
+ Or(False, Not(sym("V1=scala.collection.immutable.::[?]"))),
+
+ Or(False,
+ Or(And(Not(sym("V2=4")), And(Not(sym("V2=5")), Not(sym("V2=6")))),
+ Not(sym("V3=Nil")))),
+
+ Or(False, Or(Not(sym("V2=1")), Not(sym("V3=Nil")))),
+
+ Or(Not(sym("V1=Nil")), Not(sym("V1=null"))),
+
+ Or(Not(sym("V3=scala.collection.immutable.::[?]")), Not(sym("V3=null"))),
+
+ Or(Or(False, Not(sym("V1=scala.collection.immutable.::[?]"))), Or(False,
+ Or(And(Not(sym("V2=4")), And(Not(sym("V2=5")), Not(sym("V2=6")))),
+ Not(sym("V3=Nil"))))),
+
+ Or(Or(False,
+ Not(sym("V1=scala.collection.immutable.::[?]"))), Or(False,
+ Or(Not(sym("V2=1")), Not(sym("V3=Nil"))))),
+
+ Or(Or(sym("V1=null"),
+ Not(sym("V1=scala.collection.immutable.::[?]"))), Or(sym("V1=null"),
+ Or(And(Not(sym("V2=4")), And(Not(sym("V2=5")), Not(sym("V2=6")))),
+ Not(sym("V3=Nil"))))),
+
+ Or(Or(sym("V1=null"),
+ Not(sym("V1=scala.collection.immutable.::[?]"))), Or(sym("V1=null"),
+ Or(Not(sym("V2=1")), Not(sym("V3=Nil"))))),
+
+ Or(sym("V1=null"), Not(sym("V1=scala.collection.immutable.::[?]"))),
+
+ Or(sym("V1=null"),
+ Or(And(Not(sym("V2=4")), And(Not(sym("V2=5")), Not(sym("V2=6")))),
+ Not(sym("V3=Nil")))),
+
+ Or(sym("V1=null"), Or(Not(sym("V2=1")), Not(sym("V3=Nil")))),
+
+ Or(sym("V1=scala.collection.immutable.::[?]"),
+ Or(sym("V1=Nil"), sym("V1=null"))),
+
+ Or(sym("V1=scala.collection.immutable.::[?]"), sym("V1=Nil")),
+
+ Or(sym("V2=4"), Or(sym("V2=5"), sym("V2=6"))),
+
+ sym("V3=scala.collection.immutable.::[?]")
+ )
+
+ formulas foreach {
+ f =>
+ // build CNF
+ val tseitinCnf = propToSolvable(f)
+ val expansionCnf = eqFreePropToSolvableViaDistribution(f)
+
+ // ALL-SAT
+ val tseitinSolutions = findAllModelsFor(tseitinCnf)
+ val expansionSolutins = findAllModelsFor(expansionCnf)
+
+ // expand unassigned variables
+ // (otherwise solutions can not be compared)
+ val tseitinNoUnassigned = tseitinSolutions.flatMap(expandUnassigned).sorted
+ val expansionNoUnassigned = expansionSolutins.flatMap(expandUnassigned).sorted
+ assertEquals(tseitinNoUnassigned, expansionNoUnassigned)
+ }
+ }
+}
+
+
diff --git a/test/junit/scala/tools/testing/AssertThrowsTest.scala b/test/junit/scala/tools/testing/AssertThrowsTest.scala
index d91e450bac..76758f51d2 100644
--- a/test/junit/scala/tools/testing/AssertThrowsTest.scala
+++ b/test/junit/scala/tools/testing/AssertThrowsTest.scala
@@ -38,6 +38,6 @@ class AssertThrowsTest {
} catch {
case e: AssertionError => return
}
- assert(false, "assertThrows should error if the tested expression does not throw anything")
+ fail("assertThrows should error if the tested expression does not throw anything")
}
}
diff --git a/test/junit/scala/tools/testing/AssertUtil.scala b/test/junit/scala/tools/testing/AssertUtil.scala
index 83a637783f..d29f9a473f 100644
--- a/test/junit/scala/tools/testing/AssertUtil.scala
+++ b/test/junit/scala/tools/testing/AssertUtil.scala
@@ -2,18 +2,42 @@ package scala.tools
package testing
import org.junit.Assert
-import Assert.fail
+import Assert._
import scala.runtime.ScalaRunTime.stringOf
import scala.collection.{ GenIterable, IterableLike }
+import scala.collection.JavaConverters._
+import scala.collection.mutable
+import java.lang.ref._
+import java.lang.reflect._
+import java.util.IdentityHashMap
/** This module contains additional higher-level assert statements
* that are ultimately based on junit.Assert primitives.
*/
object AssertUtil {
- /**
- * Check if throwable T (or a subclass) was thrown during evaluation of f, and that its message
- * satisfies the `checkMessage` predicate.
- * If any other exception will be re-thrown.
+ private final val timeout = 60 * 1000L // wait a minute
+
+ private implicit class `ref helper`[A](val r: Reference[A]) extends AnyVal {
+ def isEmpty: Boolean = r.get == null
+ def nonEmpty: Boolean = !isEmpty
+ }
+ private implicit class `class helper`(val clazz: Class[_]) extends AnyVal {
+ def allFields: List[Field] = {
+ def loop(k: Class[_]): List[Field] =
+ if (k == null) Nil
+ else k.getDeclaredFields.toList ::: loop(k.getSuperclass)
+ loop(clazz)
+ }
+ }
+ private implicit class `field helper`(val f: Field) extends AnyVal {
+ def follow(o: AnyRef): AnyRef = {
+ f setAccessible true
+ f get o
+ }
+ }
+
+ /** Check if throwable T (or a subclass) was thrown during evaluation of f, and that its message
+ * satisfies the `checkMessage` predicate. If any other exception will be re-thrown.
*/
def assertThrows[T <: Throwable](f: => Any,
checkMessage: String => Boolean = s => true)
@@ -41,4 +65,29 @@ object AssertUtil {
*/
def assertSameElements[A, B >: A](expected: IterableLike[A, _], actual: Iterator[B]): Unit =
assertSameElements(expected, actual.toList, "")
+
+ /** Value is not strongly reachable from roots after body is evaluated.
+ */
+ def assertNotReachable[A <: AnyRef](a: => A, roots: AnyRef*)(body: => Unit): Unit = {
+ val wkref = new WeakReference(a)
+ def refs(root: AnyRef): mutable.Set[AnyRef] = {
+ val seen = new IdentityHashMap[AnyRef, Unit]
+ def loop(o: AnyRef): Unit =
+ if (wkref.nonEmpty && o != null && !seen.containsKey(o)) {
+ seen.put(o, ())
+ for {
+ f <- o.getClass.allFields
+ if !Modifier.isStatic(f.getModifiers)
+ if !f.getType.isPrimitive
+ if !classOf[Reference[_]].isAssignableFrom(f.getType)
+ } loop(f follow o)
+ }
+ loop(root)
+ seen.keySet.asScala
+ }
+ body
+ for (r <- roots if wkref.nonEmpty) {
+ assertFalse(s"Root $r held reference", refs(r) contains wkref.get)
+ }
+ }
}
diff --git a/test/junit/scala/tools/testing/AssertUtilTest.scala b/test/junit/scala/tools/testing/AssertUtilTest.scala
new file mode 100644
index 0000000000..03d8815ab2
--- /dev/null
+++ b/test/junit/scala/tools/testing/AssertUtilTest.scala
@@ -0,0 +1,21 @@
+package scala.tools
+package testing
+
+import org.junit.Assert._
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.JUnit4
+import AssertUtil._
+
+import java.lang.ref._
+
+@RunWith(classOf[JUnit4])
+class AssertUtilTest {
+
+ @Test def reachableIgnoresReferences(): Unit = {
+ class Holder[A](val ref: SoftReference[A])
+ val o = new Object
+ val r = new SoftReference(o)
+ assertNotReachable(o, new Holder(r)) { }
+ }
+}
diff --git a/test/pending/jvm/cf-attributes.scala b/test/pending/jvm/cf-attributes.scala
index f4964b63b1..2d08f22d8b 100644
--- a/test/pending/jvm/cf-attributes.scala
+++ b/test/pending/jvm/cf-attributes.scala
@@ -62,7 +62,7 @@ object anonymousClasses {
//InnerClass:
// public final #_; //class anonymousClasses$$anon$1 of class anonymousClasses$
val x = new Foo() {
- override def foo() { println("foo (overriden)"); }
+ override def foo() { println("foo (overridden)"); }
def dummy = 0
}
}
diff --git a/test/pending/jvm/timeout.scala b/test/pending/jvm/timeout.scala
index 22b3647dce..8f29f8ddbe 100644
--- a/test/pending/jvm/timeout.scala
+++ b/test/pending/jvm/timeout.scala
@@ -1,4 +1,4 @@
-// Test is in pending because although it suceeds locally,
+// Test is in pending because although it succeeds locally,
// it takes too long on the machine which runs nightly tests.
//
// [partest] EXPECTED: 100 < x < 900
diff --git a/test/scaladoc/resources/SI-3314-diagrams.scala b/test/scaladoc/resources/SI-3314-diagrams.scala
index b80a97b522..7d2cc9447c 100644
--- a/test/scaladoc/resources/SI-3314-diagrams.scala
+++ b/test/scaladoc/resources/SI-3314-diagrams.scala
@@ -7,7 +7,7 @@ package scala.test.scaladoc {
* / / / | \ \ \
* Mon Tue Wed Thu Fri Sat Sun
*
- * - each member should receive an inhertiance diagram:
+ * - each member should receive an inheritance diagram:
* Value
* |
* |
diff --git a/test/scaladoc/resources/implicit-inheritance-override.scala b/test/scaladoc/resources/implicit-inheritance-override.scala
index 5d692f59ad..b59d2f410d 100644
--- a/test/scaladoc/resources/implicit-inheritance-override.scala
+++ b/test/scaladoc/resources/implicit-inheritance-override.scala
@@ -35,7 +35,7 @@ class DerivedC extends Base {
class DerivedD extends Base {
/**
- * @tparam T The overriden type parameter comment
+ * @tparam T The overridden type parameter comment
*/
override def function[T](arg1: T, arg2: String): Double = 3.0d
} \ No newline at end of file
diff --git a/test/scaladoc/resources/implicits-ambiguating-res.scala b/test/scaladoc/resources/implicits-ambiguating-res.scala
index 6ed51366cb..90e43ac2ed 100644
--- a/test/scaladoc/resources/implicits-ambiguating-res.scala
+++ b/test/scaladoc/resources/implicits-ambiguating-res.scala
@@ -1,5 +1,5 @@
/**
- * Test scaladoc implicits distinguishing -- supress all members by implicit conversion that are shadowed by the
+ * Test scaladoc implicits distinguishing -- suppress all members by implicit conversion that are shadowed by the
* class' own members
*
* {{{
diff --git a/test/scaladoc/resources/implicits-shadowing-res.scala b/test/scaladoc/resources/implicits-shadowing-res.scala
index c5e9493bf3..b7f3ceb895 100644
--- a/test/scaladoc/resources/implicits-shadowing-res.scala
+++ b/test/scaladoc/resources/implicits-shadowing-res.scala
@@ -1,5 +1,5 @@
/**
- * Test scaladoc implicits distinguishing -- supress all members by implicit conversion that are shadowed by the
+ * Test scaladoc implicits distinguishing -- suppress all members by implicit conversion that are shadowed by the
* class' own members
*
* {{{
diff --git a/test/scaladoc/scalacheck/HtmlFactoryTest.scala b/test/scaladoc/scalacheck/HtmlFactoryTest.scala
index da0f253a37..51633be440 100644
--- a/test/scaladoc/scalacheck/HtmlFactoryTest.scala
+++ b/test/scaladoc/scalacheck/HtmlFactoryTest.scala
@@ -485,7 +485,7 @@ object Test extends Properties("HtmlFactory") {
""", true),
(Some("DerivedD"),
"""def function[T](arg1: T, arg2: String): Double
- T The overriden type parameter comment
+ T The overridden type parameter comment
arg1 The T term comment
arg2 The string comment
returns The return comment
diff --git a/versions.properties b/versions.properties
index d24a3bb952..62aebc41b2 100644
--- a/versions.properties
+++ b/versions.properties
@@ -4,7 +4,7 @@
# when adding new properties that influence a release,
# also add them to the update.versions mechanism in build.xml,
# which is used by scala-release-2.11.x in scala/jenkins-scripts
-starr.version=2.11.2
+starr.version=2.11.5
starr.use.released=1
# These are the versions of the modules that go with this release.
@@ -14,20 +14,20 @@ starr.use.released=1
scala.binary.version=2.11
# e.g. 2.11.0-RC1, 2.11.0, 2.11.1-RC1, 2.11.1
# this defines the dependency on scala-continuations-plugin in scala-dist's pom
-scala.full.version=2.11.2
+scala.full.version=2.11.5
# external modules shipped with distribution, as specified by scala-library-all's pom
scala-xml.version.number=1.0.3
-scala-parser-combinators.version.number=1.0.2
+scala-parser-combinators.version.number=1.0.3
scala-continuations-plugin.version.number=1.0.2
scala-continuations-library.version.number=1.0.2
scala-swing.version.number=1.0.1
akka-actor.version.number=2.3.4
actors-migration.version.number=1.1.0
-jline.version=2.12
+jline.version=2.12.1
# external modules, used internally (not shipped)
-partest.version.number=1.0.1
+partest.version.number=1.0.3
scalacheck.version.number=1.11.4
# TODO: modularize the compiler