summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CONTRIBUTING.md13
-rw-r--r--build.number2
-rw-r--r--spec/04-basic-declarations-and-definitions.md2
-rw-r--r--spec/05-classes-and-objects.md28
-rw-r--r--spec/15-changelog.md260
-rw-r--r--src/build/InnerObjectTestGen.scala2
-rw-r--r--src/compiler/scala/reflect/quasiquotes/Holes.scala2
-rw-r--r--src/compiler/scala/reflect/quasiquotes/Reifiers.scala2
-rw-r--r--src/compiler/scala/tools/nsc/PhaseAssembly.scala2
-rw-r--r--src/compiler/scala/tools/nsc/Properties.scala2
-rw-r--r--src/compiler/scala/tools/nsc/backend/icode/GenICode.scala4
-rw-r--r--src/compiler/scala/tools/nsc/backend/icode/analysis/TypeFlowAnalysis.scala2
-rw-r--r--src/compiler/scala/tools/nsc/backend/jvm/BCodeAsmCommon.scala52
-rw-r--r--src/compiler/scala/tools/nsc/backend/jvm/BCodeIdiomatic.scala2
-rw-r--r--src/compiler/scala/tools/nsc/backend/jvm/BCodeSkelBuilder.scala4
-rw-r--r--src/compiler/scala/tools/nsc/backend/jvm/BTypes.scala23
-rw-r--r--src/compiler/scala/tools/nsc/backend/jvm/BTypesFromSymbols.scala35
-rw-r--r--src/compiler/scala/tools/nsc/backend/jvm/BackendReporting.scala22
-rw-r--r--src/compiler/scala/tools/nsc/backend/jvm/GenASM.scala8
-rw-r--r--src/compiler/scala/tools/nsc/backend/jvm/GenBCode.scala22
-rw-r--r--src/compiler/scala/tools/nsc/backend/jvm/analysis/InstructionStackEffect.scala4
-rw-r--r--src/compiler/scala/tools/nsc/backend/jvm/analysis/ProdConsAnalyzer.scala450
-rw-r--r--src/compiler/scala/tools/nsc/backend/jvm/opt/ByteCodeRepository.scala4
-rw-r--r--src/compiler/scala/tools/nsc/backend/jvm/opt/BytecodeUtils.scala12
-rw-r--r--src/compiler/scala/tools/nsc/backend/jvm/opt/CallGraph.scala38
-rw-r--r--src/compiler/scala/tools/nsc/backend/jvm/opt/ClosureOptimizer.scala369
-rw-r--r--src/compiler/scala/tools/nsc/backend/jvm/opt/Inliner.scala189
-rw-r--r--src/compiler/scala/tools/nsc/backend/jvm/opt/LocalOpt.scala4
-rw-r--r--src/compiler/scala/tools/nsc/backend/opt/DeadCodeElimination.scala2
-rw-r--r--src/compiler/scala/tools/nsc/javac/JavaParsers.scala24
-rw-r--r--src/compiler/scala/tools/nsc/reporters/Reporter.scala2
-rw-r--r--src/compiler/scala/tools/nsc/settings/ScalaSettings.scala9
-rw-r--r--src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala2
-rw-r--r--src/compiler/scala/tools/nsc/symtab/classfile/ICodeReader.scala2
-rw-r--r--src/compiler/scala/tools/nsc/transform/Delambdafy.scala2
-rw-r--r--src/compiler/scala/tools/nsc/transform/patmat/Logic.scala2
-rw-r--r--src/compiler/scala/tools/nsc/transform/patmat/MatchTreeMaking.scala2
-rw-r--r--src/compiler/scala/tools/nsc/transform/patmat/MatchWarnings.scala2
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/ContextErrors.scala37
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Contexts.scala2
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Implicits.scala2
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Infer.scala2
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/PatternTypers.scala4
-rwxr-xr-xsrc/compiler/scala/tools/nsc/util/DocStrings.scala2
-rw-r--r--src/library/scala/Predef.scala5
-rw-r--r--src/library/scala/collection/generic/Sorted.scala2
-rw-r--r--src/library/scala/collection/immutable/Stream.scala2
-rw-r--r--src/library/scala/collection/immutable/StringOps.scala7
-rw-r--r--src/library/scala/sys/BooleanProp.scala7
-rw-r--r--src/partest-extras/scala/tools/partest/ASMConverters.scala2
-rw-r--r--src/partest-extras/scala/tools/partest/ReplTest.scala12
-rw-r--r--src/reflect/scala/reflect/api/FlagSets.scala2
-rw-r--r--src/reflect/scala/reflect/api/Printers.scala2
-rw-r--r--src/reflect/scala/reflect/internal/ClassfileConstants.scala13
-rw-r--r--src/reflect/scala/reflect/internal/ReificationSupport.scala2
-rw-r--r--src/reflect/scala/reflect/internal/Types.scala4
-rw-r--r--src/reflect/scala/reflect/internal/tpe/TypeConstraints.scala2
-rw-r--r--src/reflect/scala/reflect/internal/tpe/TypeMaps.scala2
-rw-r--r--src/reflect/scala/reflect/internal/util/StripMarginInterpolator.scala2
-rw-r--r--src/reflect/scala/reflect/macros/FrontEnds.scala2
-rw-r--r--src/repl/scala/tools/nsc/interpreter/Formatting.scala27
-rw-r--r--src/repl/scala/tools/nsc/interpreter/ILoop.scala110
-rw-r--r--src/repl/scala/tools/nsc/interpreter/IMain.scala19
-rw-r--r--src/repl/scala/tools/nsc/interpreter/JavapClass.scala6
-rw-r--r--src/repl/scala/tools/nsc/interpreter/Pasted.scala22
-rw-r--r--src/repl/scala/tools/nsc/interpreter/ReplProps.scala11
-rw-r--r--src/scaladoc/scala/tools/nsc/doc/html/page/diagram/DotDiagramGenerator.scala2
-rw-r--r--src/scaladoc/scala/tools/nsc/doc/model/ModelFactory.scala2
-rw-r--r--test/benchmarks/src/scala/collection/parallel/benchmarks/misc/Coder.scala4
-rw-r--r--test/benchmarks/src/scala/collection/parallel/benchmarks/parallel_array/SequentialOps.scala6
-rw-r--r--test/disabled/coder/Coder.scala4
-rw-r--r--test/disabled/run/coder2/Coder2.scala2
-rw-r--r--test/files/jvm/interpreter.check18
-rw-r--r--test/files/jvm/javaReflection/Test.scala2
-rw-r--r--test/files/jvm/protectedacc.scala2
-rw-r--r--test/files/jvm/unreachable/Test.scala2
-rw-r--r--test/files/neg/macro-invalidshape.check5
-rw-r--r--test/files/neg/missing-arg-list.check21
-rw-r--r--test/files/neg/missing-arg-list.scala13
-rw-r--r--test/files/neg/t3995.scala2
-rw-r--r--test/files/neg/t5120.scala2
-rw-r--r--test/files/neg/t8237-default.scala2
-rw-r--r--test/files/neg/t836.scala2
-rw-r--r--test/files/neg/t8431.scala2
-rw-r--r--test/files/neg/t8463.scala2
-rw-r--r--test/files/neg/warn-unused-privates.scala2
-rw-r--r--test/files/pos/SI-4012-b.scala2
-rw-r--r--test/files/pos/delambdafy-patterns.scala2
-rw-r--r--test/files/pos/t7200b.scala2
-rw-r--r--test/files/pos/t8947/Macro_1.scala2
-rw-r--r--test/files/run/ReplacementMatching.scala4
-rw-r--r--test/files/run/blame_eye_triple_eee-double.check2
-rw-r--r--test/files/run/blame_eye_triple_eee-double.scala2
-rw-r--r--test/files/run/blame_eye_triple_eee-float.check2
-rw-r--r--test/files/run/blame_eye_triple_eee-float.scala2
-rw-r--r--test/files/run/constrained-types.check8
-rw-r--r--test/files/run/deeps.scala2
-rw-r--r--test/files/run/finally.check2
-rw-r--r--test/files/run/finally.scala6
-rw-r--r--test/files/run/iq.scala2
-rw-r--r--test/files/run/kind-repl-command.check6
-rw-r--r--test/files/run/names-defaults.scala4
-rw-r--r--test/files/run/nullable-lazyvals.scala2
-rw-r--r--test/files/run/reify-repl-fail-gracefully.check6
-rw-r--r--test/files/run/reify_newimpl_22.check6
-rw-r--r--test/files/run/reify_newimpl_23.check2
-rw-r--r--test/files/run/reify_newimpl_25.check6
-rw-r--r--test/files/run/reify_newimpl_26.check2
-rw-r--r--test/files/run/repl-bare-expr.check36
-rw-r--r--test/files/run/repl-colon-type.check4
-rw-r--r--test/files/run/repl-parens.check36
-rw-r--r--test/files/run/repl-paste-2.check2
-rw-r--r--test/files/run/repl-reset.check24
-rw-r--r--test/files/run/repl-trim-stack-trace.scala6
-rw-r--r--test/files/run/sbt-icode-interface.scala42
-rw-r--r--test/files/run/t0631.scala2
-rw-r--r--test/files/run/t2526.scala2
-rw-r--r--test/files/run/t4542.check2
-rw-r--r--test/files/run/t4594-repl-settings.scala2
-rw-r--r--test/files/run/t5655.check12
-rw-r--r--test/files/run/t6240-universe-code-gen.scala4
-rw-r--r--test/files/run/t6440b.scala2
-rw-r--r--test/files/run/t7319.check18
-rw-r--r--test/files/run/t7582.check5
-rw-r--r--test/files/run/t7582/InlineHolder.scala3
-rw-r--r--test/files/run/t7582b.check5
-rw-r--r--test/files/run/t7582b/InlineHolder.scala3
-rw-r--r--test/files/run/t7747-repl.check96
-rw-r--r--test/files/run/t7817-tree-gen.scala2
-rw-r--r--test/files/run/t8601-closure-elim.scala2
-rw-r--r--test/files/run/t8708_b/Test_2.scala2
-rw-r--r--test/files/run/t9170.scala24
-rw-r--r--test/files/run/t9206.scala39
-rw-r--r--test/files/run/t9359.check18
-rw-r--r--test/files/run/t9359/A_1.java19
-rw-r--r--test/files/run/t9359/B_2.java19
-rw-r--r--test/files/run/t9359/Test_2.scala28
-rw-r--r--test/files/run/xMigration.check18
-rw-r--r--test/files/scalacheck/quasiquotes/RuntimeErrorProps.scala2
-rw-r--r--test/files/specialized/constant_lambda.scala2
-rw-r--r--test/junit/scala/tools/nsc/backend/jvm/CodeGenTools.scala14
-rw-r--r--test/junit/scala/tools/nsc/backend/jvm/DirectCompileTest.scala2
-rw-r--r--test/junit/scala/tools/nsc/backend/jvm/analysis/NullnessAnalyzerTest.scala11
-rw-r--r--test/junit/scala/tools/nsc/backend/jvm/analysis/ProdConsAnalyzerTest.scala249
-rw-r--r--test/junit/scala/tools/nsc/backend/jvm/opt/InlinerTest.scala2
-rw-r--r--test/junit/scala/tools/nsc/backend/jvm/opt/MethodLevelOpts.scala2
-rw-r--r--test/junit/scala/tools/nsc/classpath/FlatClassPathResolverTest.scala2
-rw-r--r--test/scaladoc/run/groups.scala2
-rw-r--r--versions.properties6
149 files changed, 2135 insertions, 727 deletions
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index e9505c26df..54334aea48 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -4,15 +4,19 @@ We follow the standard GitHub [fork & pull](https://help.github.com/articles/usi
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.
## 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.)
+In 2014, 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 was roughly 25/25/50 for you/EPFL/Typesafe.)
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)!
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.)
+By the way, the team at Typesafe is: @adriaanm, @lrytz, @retronym, and @SethTisue.
+
## What kind of PR are you submitting?
-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.
+Regardless of the nature of your Pull Request, we have to ask you to digitally sign the [Scala CLA](http://typesafe.com/contribute/cla/scala), to protect the OSS nature of the code base.
+
+You don't need to submit separate PRs for 2.11.x, 2.12.x, and 2.13.x. Any changes accepted on one of these branches will, in time, be merged into the later branches.
### 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.
@@ -28,9 +32,9 @@ The kind of code we can accept depends on the life cycle for the release you're
#### Bug Fix
-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.
+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.
-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).
+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.
#### Enhancement or New Feature
@@ -49,4 +53,3 @@ A new language feature requires a SIP (Scala Improvement Process) proposal. For
- [Boy Scout Rule](http://programmer.97things.oreilly.com/wiki/index.php/The_Boy_Scout_Rule) should be applied.
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.
-
diff --git a/build.number b/build.number
index f5c5adfc0f..cdba0b70ec 100644
--- a/build.number
+++ b/build.number
@@ -4,7 +4,7 @@
version.major=2
version.minor=11
-version.patch=7
+version.patch=8
# This is the -N part of a version (2.9.1-1). If it's 0, it's dropped from maven versions. It should not be used again.
version.bnum=0
diff --git a/spec/04-basic-declarations-and-definitions.md b/spec/04-basic-declarations-and-definitions.md
index 8437d2ea71..7790428ca8 100644
--- a/spec/04-basic-declarations-and-definitions.md
+++ b/spec/04-basic-declarations-and-definitions.md
@@ -627,7 +627,7 @@ parameters and associate them with their types.
Each value parameter
declaration may optionally define a default argument. The default argument
expression $e$ is type-checked with an expected type $T'$ obtained
-by replacing all occurences of the function's type parameters in $T$ by
+by replacing all occurrences of the function's type parameters in $T$ by
the undefined type.
For every parameter $p_{i,j}$ with a default argument a method named
diff --git a/spec/05-classes-and-objects.md b/spec/05-classes-and-objects.md
index 8be792d3cb..3a70f2a137 100644
--- a/spec/05-classes-and-objects.md
+++ b/spec/05-classes-and-objects.md
@@ -501,14 +501,13 @@ declaration in a template. Such members can be accessed only from
within the directly enclosing template and its companion module or
[companion class](#object-definitions).
-The modifier can be _qualified_ with an identifier $C$ (e.g.
-`private[$C$]`) that must denote a class or package
-enclosing the definition. Members labeled with such a modifier are
-accessible respectively only from code inside the package $C$ or only
-from code inside the class $C$ and its
+A `private` modifier can be _qualified_ with an identifier $C$ (e.g.
+`private[$C$]`) that must denote a class or package enclosing the definition.
+Members labeled with such a modifier are accessible respectively only from code
+inside the package $C$ or only from code inside the class $C$ and its
[companion module](#object-definitions).
-An different form of qualification is `private[this]`. A member
+A different form of qualification is `private[this]`. A member
$M$ marked with this modifier is called _object-protected_; it can be accessed only from within
the object in which it is defined. That is, a selection $p.M$ is only
legal if the prefix is `this` or `$O$.this`, for some
@@ -533,11 +532,10 @@ Protected members of a class can be accessed from within
- all templates that have the defining class as a base class,
- the companion module of any of those classes.
-A `protected` modifier can be qualified with an
-identifier $C$ (e.g. `protected[$C$]`) that must denote a
-class or package enclosing the definition. Members labeled with such
-a modifier are also accessible respectively from all code inside the
-package $C$ or from all code inside the class $C$ and its
+A `protected` modifier can be qualified with an identifier $C$ (e.g.
+`protected[$C$]`) that must denote a class or package enclosing the definition.
+Members labeled with such a modifier are also accessible respectively from all
+code inside the package $C$ or from all code inside the class $C$ and its
[companion module](#object-definitions).
A protected identifier $x$ may be used as a member name in a selection
@@ -744,7 +742,7 @@ which when applied to parameters conforming to types $\mathit{ps}$
initializes instances of type `$c$[$\mathit{tps}\,$]` by evaluating the template
$t$.
-###### Example
+###### Example – `val` and `var` parameters
The following example illustrates `val` and `var` parameters of a class `C`:
```scala
@@ -753,7 +751,7 @@ val c = new C(1, "abc", List())
c.z = c.y :: c.z
```
-### Example Private Constructor
+###### Example – Private Constructor
The following class can be created only from its companion module.
```scala
@@ -835,7 +833,7 @@ This defines a class `LinkedList` with three constructors. The
second constructor constructs an singleton list, while the
third one constructs a list with a given head and tail.
-## Case Classes
+### Case Classes
```ebnf
TmplDef ::= `case' `class' ClassDef
@@ -966,7 +964,7 @@ This form of extensibility can be excluded by declaring the base class
directly extend `Expr` must be in the same source file as
`Expr`.
-### Traits
+## Traits
```ebnf
TmplDef ::= `trait' TraitDef
diff --git a/spec/15-changelog.md b/spec/15-changelog.md
index 54310c921c..3c8739359a 100644
--- a/spec/15-changelog.md
+++ b/spec/15-changelog.md
@@ -122,8 +122,8 @@ when compiling with `-target:jvm-1.4`, a Scala type such as
#### Changes to Case Classes
-The Scala compiler generates now for every case class a companion
-extractor object (). For instance, given the case class:
+The Scala compiler generates a [companion extractor object for every case class]
+(05-classes-and-objects.html#case-classes) now. For instance, given the case class:
case class X(elem: String)
@@ -152,8 +152,9 @@ _(30-Nov-2007)_
#### Mutable variables introduced by pattern binding
-Mutable variables can now be introduced by a pattern matching definition
-(), just like values can. Examples:
+[Mutable variables can now be introduced by a pattern matching definition]
+(04-basic-declarations-and-definitions.html#variable-declarations-and-definitions),
+just like values can. Examples:
var (x, y) = if (positive) (1, 2) else (-1, -3)
var hd :: tl = mylist
@@ -161,7 +162,7 @@ Mutable variables can now be introduced by a pattern matching definition
#### Self-types
Self types can now be introduced without defining an alias name for
-`this` (). Example:
+[`this`](05-classes-and-objects.html#templates). Example:
class C {
type T <: Trait
@@ -175,8 +176,8 @@ _(27-July-2007)_
#### Existential types
-It is now possible to define existential types (). An existential type
-has the form `T forSome {Q}` where `Q` is a sequence of value and/or
+It is now possible to define [existential types](03-types.html#existential-types).
+An existential type has the form `T forSome {Q}` where `Q` is a sequence of value and/or
type declarations. Given the class definitions
class Ref[T]
@@ -189,8 +190,9 @@ one may for example write the following existential types
#### Lazy values
-It is now possible to define lazy value declarations using the new
-modifier `lazy` (). A `lazy` value definition evaluates its right hand
+It is now possible to define lazy value declarations using the new modifier
+[`lazy`](04-basic-declarations-and-definitions.html#value-declarations-and-definitions).
+A `lazy` value definition evaluates its right hand
side \\(e\\) the first time the value is accessed. Example:
import compat.Platform._
@@ -203,8 +205,8 @@ side \\(e\\) the first time the value is accessed. Example:
#### Structural types
-It is now possible to declare structural types using type refinements
-(). For example:
+It is now possible to declare structural types using [type refinements]
+(03-types.html#compound-types). For example:
class File(name: String) {
def getName(): String = name
@@ -230,10 +232,13 @@ Changes in Version 2.5
_(02-May-2007)_
-#### Type constructor polymorphism[^1]
+#### Type constructor polymorphism
-Type parameters () and abstract type members () can now also abstract
-over type constructors ().
+_Implemented by Adriaan Moors_
+
+[Type parameters](04-basic-declarations-and-definitions.html#type-parameters)
+and abstract
+[type members](04-basic-declarations-and-definitions.html#type-declarations-and-type-aliases) can now also abstract over [type constructors](03-types.html#type-constructors).
This allows a more precise `Iterable` interface:
@@ -254,8 +259,9 @@ over a certain structure (e.g., a `List`) will yield the same structure
#### Early object initialization
-It is now possible to initialize some fields of an object before any
-parent constructors are called (). This is particularly useful for
+[Early object initialization](05-classes-and-objects.html#early-definitions)
+makes it possible to initialize some fields of an object before any
+parent constructors are called. This is particularly useful for
traits, which do not have normal constructor parameters. Example:
trait Greeting {
@@ -273,10 +279,11 @@ called. Therefore, field `msg` in class is properly initialized to .
#### For-comprehensions, revised
-The syntax of for-comprehensions has changed (). In the new syntax,
-generators do not start with a anymore, but filters start with an (and
-are called guards). A semicolon in front of a guard is optional. For
-example:
+The syntax of [for-comprehensions](06-expressions.html#for-comprehensions-and-for-loops)
+has changed.
+In the new syntax, generators do not start with a `val` anymore, but filters
+start with an `if` (and are called guards).
+A semicolon in front of a guard is optional. For example:
for (val x <- List(1, 2, 3); x % 2 == 0) println(x)
@@ -288,8 +295,9 @@ The old syntax is still available but will be deprecated in the future.
#### Implicit anonymous functions
-It is now possible to define anonymous functions using underscores in
-parameter position (). For instance, the expressions in the left column
+It is now possible to define [anonymous functions using underscores]
+(06-expressions.html#placeholder-syntax-for-anonymous-functions) in
+parameter position. For instance, the expressions in the left column
are each function values which expand to the anonymous functions on
their right.
@@ -300,8 +308,8 @@ their right.
_.map(f) x => x.map(f)
_.map(_ + 1) x => x.map(y => y + 1)
-As a special case (), a partially unapplied method is now designated
- `m _`   instead of the previous notation  `&m`.
+As a special case, a [partially unapplied method](06-expressions.html#method-values)
+is now designated `m _`   instead of the previous notation  `&m`.
The new notation will displace the special syntax forms `.m()` for
abstracting over method receivers and `&m` for treating an unapplied
@@ -310,8 +318,9 @@ still available, but they will be deprecated in the future.
#### Pattern matching anonymous functions, refined
-It is now possible to use case clauses to define a function value
-directly for functions of arities greater than one (). Previously, only
+It is now possible to use [case clauses to define a function value]
+(08-pattern-matching.html#pattern-matching-anonymous-functions)
+directly for functions of arities greater than one. Previously, only
unary functions could be defined that way. Example:
def scalarProduct(xs: Array[Double], ys: Array[Double]) =
@@ -326,8 +335,9 @@ _(09-Mar-2007)_
#### Object-local private and protected
-The `private` and `protected` modifiers now accept a `[this]` qualifier
-(). A definition \\(M\\) which is labelled `private[this]` is private,
+The `private` and `protected` modifiers now accept a
+[`[this]` qualifier](05-classes-and-objects.html#modifiers).
+A definition \\(M\\) which is labelled `private[this]` is private,
and in addition can be accessed only from within the current object.
That is, the only legal prefixes for \\(M\\) are `this` or `$C$.this`.
Analogously, a definition \\(M\\) which is labelled `protected[this]` is
@@ -348,16 +358,17 @@ Analogously, for any sequence of expressions or patterns \\(x_1
#### Access modifiers for primary constructors
-The primary constructor of a class can now be marked or (). If such an
-access modifier is given, it comes between the name of the class and its
+The primary constructor of a class can now be marked [`private` or `protected`]
+(05-classes-and-objects.html#class-definitions).
+If such an access modifier is given, it comes between the name of the class and its
value parameters. Example:
class C[T] private (x: T) { ... }
#### Annotations
-The support for attributes has been extended and its syntax changed ().
-Attributes are now called <span>*annotations*</span>. The syntax has
+The support for attributes has been extended and its syntax changed.
+Attributes are now called [*annotations*](11-annotations.html). The syntax has
been changed to follow Java’s conventions, e.g. `@attribute` instead of
`[attribute]`. The old syntax is still available but will be deprecated
in the future.
@@ -373,12 +384,13 @@ symbol is accessed.
#### Decidable subtyping
The implementation of subtyping has been changed to prevent infinite
-recursions. Termination of subtyping is now ensured by a new restriction
-of class graphs to be finitary ().
+recursions.
+[Termination of subtyping](05-classes-and-objects.html#inheritance-closure)
+is now ensured by a new restriction of class graphs to be finitary.
#### Case classes cannot be abstract
-It is now explicitly ruled out that case classes can be abstract (). The
+It is now explicitly ruled out that case classes can be abstract. The
specification was silent on this point before, but did not explain how
abstract case classes were treated. The Scala compiler allowed the
idiom.
@@ -386,19 +398,21 @@ idiom.
#### New syntax for self aliases and self types
It is now possible to give an explicit alias name and/or type for the
-self reference (). For instance, in
+[self reference](05-classes-and-objects.html#templates) `this`. For instance, in
class C { self: D =>
...
}
-the name is introduced as an alias for within and the self type () of is
-assumed to be . This construct is introduced now in order to replace
+the name `self` is introduced as an alias for `this` within `C` and the
+[self type](05-classes-and-objects.html#class-definitions) of `C` is
+assumed to be `D`. This construct is introduced now in order to replace
eventually both the qualified this construct and the clause in Scala.
#### Assignment Operators
-It is now possible to combine operators with assignments (). Example:
+It is now possible to [combine operators with assignments]
+(06-expressions.html#assignment-operators). Example:
var x: int = 0
x += 1
@@ -410,8 +424,9 @@ _(23-Jan-2007)_
#### Extractors
-It is now possible to define patterns independently of case classes,
-using methods in extractor objects (). Here is an example:
+It is now possible to define patterns independently of case classes, using
+`unapply` methods in [extractor objects](08-pattern-matching.html#extractor-patterns).
+Here is an example:
object Twice {
def apply(x:Int): int = x*2
@@ -422,25 +437,26 @@ using methods in extractor objects (). Here is an example:
In the example, `Twice` is an extractor object with two methods:
-- The method is used to build even numbers.
+- The `apply` method is used to build even numbers.
-- The method is used to decompose an even number; it is in a sense the
- reverse of . `unapply` methods return option types: for a match that
- suceeds, for a match that fails. Pattern variables are returned as
- the elements of . If there are several variables, they are grouped
- in a tuple.
+- The `unapply` method is used to decompose an even number; it is in a sense
+ the reverse of `apply`. `unapply` methods return option types:
+ `Some(...)` for a match that suceeds, `None` for a match that fails.
+ Pattern variables are returned as the elements of `Some`.
+ If there are several variables, they are grouped in a tuple.
-In the second-to-last line, ’s method is used to construct a number . In
-the last line, is tested against the pattern . This pattern succeeds for
-even numbers and assigns to the variable one half of the number that was
-tested. The pattern match makes use of the method of object . More
-details on extractors can be found in the paper “Matching Objects with
+In the second-to-last line, `Twice`’s method is used to construct a number `x`.
+In the last line, `x` is tested against the pattern `Twice(n)`.
+This pattern succeeds for even numbers and assigns to the variable `n` one half
+of the number that was tested.
+The pattern match makes use of the `unapply` method of object `Twice`.
+More details on extractors can be found in the paper “Matching Objects with
Patterns” by Emir, Odersky and Williams.
#### Tuples
-A new lightweight syntax for tuples has been introduced (). For any
-sequence of types \\(T_1 , … , T_n\\),
+A new [lightweight syntax for tuples](06-expressions.html#tuples) has been introduced.
+For any sequence of types \\(T_1 , … , T_n\\),
\\(\{T_1 , … , T_n \}\\) is a shorthand for `Tuple$n$[$T_1 , … , T_n$]`.
@@ -451,8 +467,8 @@ Analogously, for any sequence of expressions or patterns \\(x_1, … , x_n\\),
#### Infix operators of greater arities
It is now possible to use methods which have more than one parameter as
-infix operators (). In this case, all method arguments are written as a
-normal parameter list in parentheses. Example:
+[infix operators](06-expressions.html#infix-operations). In this case, all
+method arguments are written as a normal parameter list in parentheses. Example:
class C {
def +(x: int, y: String) = ...
@@ -462,9 +478,9 @@ normal parameter list in parentheses. Example:
#### Deprecated attribute
-A new standard attribute `deprecated` is available (11-annotations.html#deprecation-annotations). If a member
-definition is marked with this attribute, any reference to the member
-will cause a “deprecated” warning message to be emitted.
+A new standard attribute [`deprecated`](11-annotations.html#deprecation-annotations)
+is available. If a member definition is marked with this attribute, any
+reference to the member will cause a “deprecated” warning message to be emitted.
Changes in Version 2.3
----------------------
@@ -473,20 +489,23 @@ _(23-Nov-2006)_
#### Procedures
-A simplified syntax for functions returning `unit` has been introduced
-(). Scala now allows the following shorthands:
+A simplified syntax for [methods returning `unit`]
+(04-basic-declarations-and-definitions.html#procedures) has been introduced.
+Scala now allows the following shorthands:
`def f(params)` \\(\mbox{for}\\) `def f(params): unit`
`def f(params) { ... }` \\(\mbox{for}\\) `def f(params): unit = { ... }`
#### Type Patterns
-The syntax of types in patterns has been refined (). Scala now
-distinguishes between type variables (starting with a lower case letter)
-and types as type arguments in patterns. Type variables are bound in the
-pattern. Other type arguments are, as in previous versions, erased. The
-Scala compiler will now issue an “unchecked” warning at places where
-type erasure might compromise type-safety.
+The [syntax of types in patterns](08-pattern-matching.html#type-patterns) has
+been refined.
+Scala now distinguishes between type variables (starting with a lower case
+letter) and types as type arguments in patterns.
+Type variables are bound in the pattern.
+Other type arguments are, as in previous versions, erased.
+The Scala compiler will now issue an “unchecked” warning at places where type
+erasure might compromise type-safety.
#### Standard Types
@@ -505,43 +524,43 @@ _(23-Aug-2006)_
#### Visibility Qualifier for protected
-Protected members can now have a visibility qualifier (), e.g.
-`protected[<qualifier>]`. In particular, one can now simulate package
-protected access as in Java writing
+Protected members can now have a visibility qualifier, e.g.
+[`protected[<qualifier>]`](05-classes-and-objects.html#protected).
+In particular, one can now simulate package protected access as in Java writing
protected[P] def X ...
-where would name the package containing .
+where would name the package containing `X`.
#### Relaxation of Private Acess
-Private members of a class can now be referenced from the companion
-module of the class and vice versa ()
+[Private members of a class](05-classes-and-objects.html#private) can now be
+referenced from the companion module of the class and vice versa.
#### Implicit Lookup
-The lookup method for implicit definitions has been generalized (). When
-searching for an implicit definition matching a type \\(T\\), now are
-considered
+The lookup method for [implicit definitions](07-implicits.html#implicit-parameters)
+has been generalized.
+When searching for an implicit definition matching a type \\(T\\), now are considered
1. all identifiers accessible without prefix, and
2. all members of companion modules of classes associated with \\(T\\).
-(The second clause is more general than before). Here, a class is
-<span>*associated*</span> with a type \\(T\\) if it is referenced by
-some part of \\(T\\), or if it is a base class of some part of \\(T\\).
+(The second clause is more general than before). Here, a class is _associated_
+with a type \\(T\\) if it is referenced by some part of \\(T\\), or if it is a
+base class of some part of \\(T\\).
For instance, to find implicit members corresponding to the type
HashSet[List[Int], String]
-one would now look in the companion modules (aka static parts) of , , ,
-and . Before, it was just the static part of .
+one would now look in the companion modules (aka static parts) of `HashSet`,
+`List`, `Int`, and `String`. Before, it was just the static part of .
#### Tightened Pattern Match
-A typed pattern match with a singleton type now tests whether the
-selector value is reference-equal to p (). Example:
+A typed [pattern match with a singleton type `p.type`](08-pattern-matching.html#type-patterns)
+now tests whether the selector value is reference-equal to `p`. Example:
val p = List(1, 2, 3)
val q = List(1, 2)
@@ -551,8 +570,8 @@ selector value is reference-equal to p (). Example:
case _: q.type => Console.println("q")
}
-This will match the second case and hence will print “”. Before, the
-singleton types were erased to , and therefore the first case would have
+This will match the second case and hence will print “q”. Before, the
+singleton types were erased to `List`, and therefore the first case would have
matched, which is non-sensical.
Changes in Version 2.1.7
@@ -562,8 +581,8 @@ _(19-Jul-2006)_
#### Multi-Line string literals
-It is now possible to write multi-line string-literals enclosed in
-triple quotes (). Example:
+It is now possible to write [multi-line string-literals]
+(01-lexical-syntax.html#string-literals) enclosed in triple quotes. Example:
"""this is a
multi-line
@@ -574,13 +593,14 @@ string literals.
#### Closure Syntax
-The syntax of closures has been slightly restricted (). The form
+The syntax of [closures](06-expressions.html#anonymous-functions)
+has been slightly restricted. The form
x: T => E
is valid only when enclosed in braces, i.e.  `{ x: T => E }`. The
following is illegal, because it might be read as the value x typed with
-the type T =\> E:
+the type `T => E`:
val f = x: T => E
@@ -596,8 +616,9 @@ _(24-May-2006)_
#### Class Literals
-There is a new syntax for class literals (): For any class type \\(C\\),
-`classOf[$C$]` designates the run-time representation of \\(C\\).
+There is a new syntax for [class literals](06-expressions.html#literals):
+For any class type \\(C\\), `classOf[$C$]` designates the run-time
+representation of \\(C\\).
Changes in Version 2.0
----------------------
@@ -612,14 +633,14 @@ changes.
#### New Keywords
The following three words are now reserved; they cannot be used as
-identifiers ()
+[identifiers](01-lexical-syntax.html#identifiers):
implicit match requires
#### Newlines as Statement Separators
-Newlines can now be used as statement separators in place of semicolons
-()
+[Newlines](http://www.scala-lang.org/files/archive/spec/2.11/)
+can now be used as statement separators in place of semicolons.
#### Syntax Restrictions
@@ -649,8 +670,8 @@ is no longer supported. A `with` connective is only allowed following an
class C extends AnyRef with M { ... } .
-However, assuming `M` is a trait (see [sec:traits]), it is also legal to
-write
+However, assuming `M` is a [trait](05-classes-and-objects.html#traits),
+it is also legal to write
class C extends M { ... }
@@ -665,7 +686,7 @@ where `S` is the superclass of `M`.
The only form of regular expression pattern that is currently supported
is a sequence pattern, which might end in a sequence wildcard . Example:
- case List(1, 2, _*) => ... // will match all lists starting with \code{1,2}.
+ case List(1, 2, _*) => ... // will match all lists starting with 1, 2, ...
It is at current not clear whether this is a permanent restriction. We
are evaluating the possibility of re-introducing full regular expression
@@ -686,7 +707,8 @@ old syntax is still available but is considered deprecated.
#### For-comprehensions
-For-comprehensions () now admit value and pattern definitions. Example:
+[For-comprehensions](06-expressions.html#for-comprehensions-and-for-loops)
+now admit value and pattern definitions. Example:
for {
val x <- List.range(1, 100)
@@ -700,8 +722,9 @@ for-comprehension.
#### Conversions
-The rules for implicit conversions of methods to functions () have been
-tightened. Previously, a parameterized method used as a value was always
+The rules for [implicit conversions of methods to functions]
+(06-expressions.html#method-conversions) have been tightened.
+Previously, a parameterized method used as a value was always
implicitly converted to a function. This could lead to unexpected
results when method arguments where forgotten. Consider for instance the
statement below:
@@ -750,10 +773,11 @@ instance, the `show` expression above will now be expanded to
show(x.toString()) .
Scala version 2.0 also relaxes the rules of overriding with respect to
-empty parameter lists. The revised definition of <span>*matching
-members*</span> () makes it now possible to override a method with an
+empty parameter lists. The revised definition of
+[_matching members_](05-classes-and-objects.html#class-members)
+makes it now possible to override a method with an
explicit, but empty parameter list `()` with a parameterless method, and
-<span>*vice versa*</span>. For instance, the following class definition
+_vice versa_. For instance, the following class definition
is now legal:
class C {
@@ -766,26 +790,29 @@ parameter list.
#### Class Parameters
-A class parameter may now be prefixed by `val` or `var` ().
+A [class parameter](05-classes-and-objects.html#class-definitions)
+may now be prefixed by `val` or `var`.
#### Private Qualifiers
Previously, Scala had three levels of visibility:
<span>*private*</span>, <span>*protected*</span> and
<span>*public*</span>. There was no way to restrict accesses to members
-of the current package, as in Java. Scala 2 now defines access
-qualifiers that let one express this level of visibility, among others.
-In the definition
+of the current package, as in Java.
+
+Scala 2 now defines [access qualifiers](05-classes-and-objects.html#modifiers)
+that let one express this level of visibility, among others. In the definition
private[C] def f(...)
access to `f` is restricted to all code within the class or package `C`
-(which must contain the definition of `f`) ()
+(which must contain the definition of `f`).
#### Changes in the Mixin Model
-The model which details mixin composition of classes has changed
-significantly. The main differences are:
+The model which details [mixin composition of classes]
+(05-classes-and-objects.html#templates) has changed significantly.
+The main differences are:
1. We now distinguish between <span>*traits*</span> that are used as
mixin classes and normal classes. The syntax of traits has been
@@ -802,22 +829,19 @@ significantly. The main differences are:
different mixins. This makes method overloading in Scala
conceptually the same as in Java.
-The new mixin model is explained in more detail in .
-
#### Implicit Parameters
Views in Scala 1.0 have been replaced by the more general concept of
-implicit parameters ()
+[implicit parameters](07-implicits.html#implicit-parameters).
#### Flexible Typing of Pattern Matching
The new version of Scala implements more flexible typing rules when it
-comes to pattern matching over heterogeneous class hierarchies (). A
-<span>*heterogeneous class hierarchy*</span> is one where subclasses
+comes to [pattern matching over heterogeneous class hierarchies]
+(08-pattern-matching.html#pattern-matching-expressions).
+A <span>*heterogeneous class hierarchy*</span> is one where subclasses
inherit a common superclass with different parameter types. With the new
rules in Scala version 2.0 one can perform pattern matches over such
hierarchies with more precise typings that keep track of the information
-gained by comparing the types of a selector and a matching pattern ().
+gained by comparing the types of a selector and a matching pattern.
This gives Scala capabilities analogous to guarded algebraic data types.
-
-[^1]: Implemented by Adriaan Moors
diff --git a/src/build/InnerObjectTestGen.scala b/src/build/InnerObjectTestGen.scala
index b66112609c..e0b889c969 100644
--- a/src/build/InnerObjectTestGen.scala
+++ b/src/build/InnerObjectTestGen.scala
@@ -22,7 +22,7 @@ object Contexts extends Enumeration {
* object, or equivalent).
*
* Usage: TestGen <nr of levels>
- * - by default it's 2 leves. Currently, 3-level deep uncovers bugs in the type checker.
+ * - by default it's 2 levels. Currently, 3-level deep uncovers bugs in the type checker.
*
* @author Iulian Dragos
*/
diff --git a/src/compiler/scala/reflect/quasiquotes/Holes.scala b/src/compiler/scala/reflect/quasiquotes/Holes.scala
index 6fa6b9b37a..47084fc317 100644
--- a/src/compiler/scala/reflect/quasiquotes/Holes.scala
+++ b/src/compiler/scala/reflect/quasiquotes/Holes.scala
@@ -151,7 +151,7 @@ trait Holes { self: Quasiquotes =>
else None
}
- /** Map high-rank unquotee onto an expression that eveluates as a list of given rank.
+ /** Map high-rank unquotee onto an expression that evaluates as a list of given rank.
*
* All possible combinations of representations are given in the table below:
*
diff --git a/src/compiler/scala/reflect/quasiquotes/Reifiers.scala b/src/compiler/scala/reflect/quasiquotes/Reifiers.scala
index e753c9787a..8462debe21 100644
--- a/src/compiler/scala/reflect/quasiquotes/Reifiers.scala
+++ b/src/compiler/scala/reflect/quasiquotes/Reifiers.scala
@@ -322,7 +322,7 @@ trait Reifiers { self: Quasiquotes =>
* in the domain of the fill function;
*
* 2. fold the groups into a sequence of lists added together with ++ using
- * fill reification for holeMap and fallback reification for non-holeMap.
+ * fill reification for holeMap and fallback reification for non-holeMap.
*
* Example:
*
diff --git a/src/compiler/scala/tools/nsc/PhaseAssembly.scala b/src/compiler/scala/tools/nsc/PhaseAssembly.scala
index 4b32aab5ee..ef9818c62d 100644
--- a/src/compiler/scala/tools/nsc/PhaseAssembly.scala
+++ b/src/compiler/scala/tools/nsc/PhaseAssembly.scala
@@ -226,7 +226,7 @@ trait PhaseAssembly {
}
/** Given the phases set, will build a dependency graph from the phases set
- * Using the aux. method of the DependencyGraph to create nodes and egdes.
+ * Using the aux. method of the DependencyGraph to create nodes and edges.
*/
private def phasesSetToDepGraph(phsSet: mutable.HashSet[SubComponent]): DependencyGraph = {
val graph = new DependencyGraph()
diff --git a/src/compiler/scala/tools/nsc/Properties.scala b/src/compiler/scala/tools/nsc/Properties.scala
index 9f160e2485..ca7d8776d4 100644
--- a/src/compiler/scala/tools/nsc/Properties.scala
+++ b/src/compiler/scala/tools/nsc/Properties.scala
@@ -13,7 +13,7 @@ object Properties extends scala.util.PropertiesTrait {
// settings based on jar properties, falling back to System prefixed by "scala."
def residentPromptString = scalaPropOrElse("resident.prompt", "\nnsc> ")
- def shellPromptString = scalaPropOrElse("shell.prompt", "\nscala> ")
+ def shellPromptString = scalaPropOrElse("shell.prompt", "%nscala> ")
// message to display at EOF (which by default ends with
// a newline so as not to break the user's terminal)
def shellInterruptedString = scalaPropOrElse("shell.interrupted", f":quit$lineSeparator")
diff --git a/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala b/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala
index 137954b52d..3e23291e92 100644
--- a/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala
+++ b/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala
@@ -1022,7 +1022,7 @@ abstract class GenICode extends SubComponent {
tree match {
case Literal(Constant(null)) if generatedType == NullReference && expectedType != UNIT =>
// literal null on the stack (as opposed to a boxed null, see SI-8233),
- // we can bypass `adapt` which would otherwise emitt a redundant [DROP, CONSTANT(null)]
+ // we can bypass `adapt` which would otherwise emit a redundant [DROP, CONSTANT(null)]
// except one case: when expected type is UNIT (unboxed) where we need to emit just a DROP
case _ =>
adapt(generatedType, expectedType, resCtx, tree.pos)
@@ -2108,7 +2108,7 @@ abstract class GenICode extends SubComponent {
/**
* Represent a label in the current method code. In order
* to support forward jumps, labels can be created without
- * having a deisgnated target block. They can later be attached
+ * having a designated target block. They can later be attached
* by calling `anchor`.
*/
class Label(val symbol: Symbol) {
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 058b6a161d..64c9901a3e 100644
--- a/src/compiler/scala/tools/nsc/backend/icode/analysis/TypeFlowAnalysis.scala
+++ b/src/compiler/scala/tools/nsc/backend/icode/analysis/TypeFlowAnalysis.scala
@@ -387,7 +387,7 @@ abstract class TypeFlowAnalysis {
Moreover, it's often the case that the last CALL_METHOD of interest ("of interest" equates to "being tracked in `isOnWatchlist`) isn't the last instruction on the block.
There are cases where the typeflows computed past this `lastInstruction` are needed, and cases when they aren't.
- The reasoning behind this decsision is described in `populatePerimeter()`. All `blockTransfer()` needs to do (in order to know at which instruction it can stop)
+ The reasoning behind this decision is described in `populatePerimeter()`. All `blockTransfer()` needs to do (in order to know at which instruction it can stop)
is querying `isOnPerimeter`.
Upon visiting a CALL_METHOD that's an inlining candidate, the relevant pieces of information about the pre-instruction typestack are collected for future use.
diff --git a/src/compiler/scala/tools/nsc/backend/jvm/BCodeAsmCommon.scala b/src/compiler/scala/tools/nsc/backend/jvm/BCodeAsmCommon.scala
index eadc404bee..dec5adc9aa 100644
--- a/src/compiler/scala/tools/nsc/backend/jvm/BCodeAsmCommon.scala
+++ b/src/compiler/scala/tools/nsc/backend/jvm/BCodeAsmCommon.scala
@@ -9,6 +9,7 @@ package backend.jvm
import scala.tools.nsc.Global
import scala.tools.nsc.backend.jvm.BTypes.{InternalName, MethodInlineInfo, InlineInfo}
import BackendReporting.ClassSymbolInfoFailureSI9111
+import scala.tools.asm
/**
* This trait contains code shared between GenBCode and GenASM that depends on types defined in
@@ -229,6 +230,44 @@ final class BCodeAsmCommon[G <: Global](val global: G) {
}
/**
+ * Reconstruct the classfile flags from a Java defined class symbol.
+ *
+ * The implementation of this method is slightly different that `javaFlags` in BTypesFromSymbols.
+ * The javaFlags method is primarily used to map Scala symbol flags to sensible classfile flags
+ * that are used in the generated classfiles. For example, all classes emitted by the Scala
+ * compiler have ACC_PUBLIC.
+ *
+ * When building a [[ClassBType]] from a Java class symbol, the flags in the type's `info` have
+ * to correspond exactly to the flags in the classfile. For example, if the class is package
+ * protected (i.e., it doesn't have the ACC_PUBLIC flag), this needs to be reflected in the
+ * ClassBType. For example, the inliner needs the correct flags for access checks.
+ *
+ * Class flags are listed here:
+ * https://docs.oracle.com/javase/specs/jvms/se7/html/jvms-4.html#jvms-4.1-200-E.1
+ */
+ def javaClassfileFlags(classSym: Symbol): Int = {
+ assert(classSym.isJava, s"Expected Java class symbol, got ${classSym.fullName}")
+ import asm.Opcodes._
+ def enumFlags = ACC_ENUM | {
+ // Java enums have the `ACC_ABSTRACT` flag if they have a deferred method.
+ // We cannot trust `hasAbstractFlag`: the ClassfileParser adds `ABSTRACT` and `SEALED` to all
+ // Java enums for exhaustiveness checking.
+ val hasAbstractMethod = classSym.info.decls.exists(s => s.isMethod && s.isDeferred)
+ if (hasAbstractMethod) ACC_ABSTRACT else 0
+ }
+ GenBCode.mkFlags(
+ if (classSym.isPublic) ACC_PUBLIC else 0,
+ if (classSym.isFinal) ACC_FINAL else 0,
+ // see the link above. javac does the same: ACC_SUPER for all classes, but not interfaces.
+ if (classSym.isInterface) ACC_INTERFACE else ACC_SUPER,
+ // for Java enums, we cannot trust `hasAbstractFlag` (see comment in enumFlags)
+ if (!classSym.hasEnumFlag && classSym.hasAbstractFlag) ACC_ABSTRACT else 0,
+ if (classSym.isArtifact) ACC_SYNTHETIC else 0,
+ if (classSym.hasEnumFlag) enumFlags else 0
+ )
+ }
+
+ /**
* The member classes of a class symbol. Note that the result of this method depends on the
* current phase, for example, after lambdalift, all local classes become member of the enclosing
* class.
@@ -399,3 +438,16 @@ final class BCodeAsmCommon[G <: Global](val global: G) {
InlineInfo(traitSelfType, isEffectivelyFinal, methodInlineInfos, warning)
}
}
+
+object BCodeAsmCommon {
+ /**
+ * Valid flags for InnerClass attribute entry.
+ * See http://docs.oracle.com/javase/specs/jvms/se8/html/jvms-4.html#jvms-4.7.6
+ */
+ val INNER_CLASSES_FLAGS = {
+ asm.Opcodes.ACC_PUBLIC | asm.Opcodes.ACC_PRIVATE | asm.Opcodes.ACC_PROTECTED |
+ asm.Opcodes.ACC_STATIC | asm.Opcodes.ACC_FINAL | asm.Opcodes.ACC_INTERFACE |
+ asm.Opcodes.ACC_ABSTRACT | asm.Opcodes.ACC_SYNTHETIC | asm.Opcodes.ACC_ANNOTATION |
+ asm.Opcodes.ACC_ENUM
+ }
+}
diff --git a/src/compiler/scala/tools/nsc/backend/jvm/BCodeIdiomatic.scala b/src/compiler/scala/tools/nsc/backend/jvm/BCodeIdiomatic.scala
index 8f2a17a2bf..eb0da7caef 100644
--- a/src/compiler/scala/tools/nsc/backend/jvm/BCodeIdiomatic.scala
+++ b/src/compiler/scala/tools/nsc/backend/jvm/BCodeIdiomatic.scala
@@ -439,7 +439,7 @@ abstract class BCodeIdiomatic extends SubComponent {
else { emitTypeBased(JCodeMethodN.returnOpcodes, tk) }
}
- /* Emits one of tableswitch or lookoupswitch.
+ /* Emits one of tableswitch or lookupswitch.
*
* can-multi-thread
*/
diff --git a/src/compiler/scala/tools/nsc/backend/jvm/BCodeSkelBuilder.scala b/src/compiler/scala/tools/nsc/backend/jvm/BCodeSkelBuilder.scala
index a2fd22d24c..d2d510e8a9 100644
--- a/src/compiler/scala/tools/nsc/backend/jvm/BCodeSkelBuilder.scala
+++ b/src/compiler/scala/tools/nsc/backend/jvm/BCodeSkelBuilder.scala
@@ -90,7 +90,7 @@ abstract class BCodeSkelBuilder extends BCodeHelpers {
override def getCurrentCUnit(): CompilationUnit = { cunit }
- /* ---------------- helper utils for generating classes and fiels ---------------- */
+ /* ---------------- helper utils for generating classes and fields ---------------- */
def genPlainClass(cd: ClassDef) {
assert(cnode == null, "GenBCode detected nested methods.")
@@ -140,7 +140,7 @@ abstract class BCodeSkelBuilder extends BCodeHelpers {
if (AsmUtils.traceClassEnabled && cnode.name.contains(AsmUtils.traceClassPattern))
AsmUtils.traceClass(cnode)
- if (settings.YoptInlinerEnabled) {
+ if (settings.YoptAddToBytecodeRepository) {
// The inliner needs to find all classes in the code repo, also those being compiled
byteCodeRepository.add(cnode, ByteCodeRepository.CompilationUnit)
}
diff --git a/src/compiler/scala/tools/nsc/backend/jvm/BTypes.scala b/src/compiler/scala/tools/nsc/backend/jvm/BTypes.scala
index e61190bf3a..8720da84e8 100644
--- a/src/compiler/scala/tools/nsc/backend/jvm/BTypes.scala
+++ b/src/compiler/scala/tools/nsc/backend/jvm/BTypes.scala
@@ -44,6 +44,8 @@ abstract class BTypes {
val inliner: Inliner[this.type]
+ val closureOptimizer: ClosureOptimizer[this.type]
+
val callGraph: CallGraph[this.type]
val backendReporting: BackendReporting
@@ -646,7 +648,7 @@ abstract class BTypes {
* JVMS 4.7.7: the attribute must be present "if and only if it represents a local class
* or an anonymous class" (i.e. not for member classes).
*
- * The attribute is mis-named, it should be called "EnclosingClass". It has to be defined for all
+ * The attribute is misnamed, it should be called "EnclosingClass". It has to be defined for all
* local and anonymous classes, no matter if there is an enclosing method or not. Accordingly, the
* "class" field (see below) must be always defined, while the "method" field may be null.
*
@@ -796,7 +798,7 @@ abstract class BTypes {
* 2. The ClassBType should be built from a classfile, but the class could not be found on the
* compilation classpath.
*
- * Note that all ClassBTypes required in a non-optimzied run are built during code generation from
+ * Note that all ClassBTypes required in a non-optimized run are built during code generation from
* the class symbols referenced by the ASTs, so they have a valid info. Therefore the backend
* often invokes `info.get` (which asserts the info to exist) when reading data from the ClassBType.
*
@@ -898,7 +900,7 @@ abstract class BTypes {
// the static flag in the InnerClass table has a special meaning, see InnerClass comment
i.flags & ~Opcodes.ACC_STATIC,
if (isStaticNestedClass) Opcodes.ACC_STATIC else 0
- ) & ClassBType.INNER_CLASSES_FLAGS
+ ) & BCodeAsmCommon.INNER_CLASSES_FLAGS
)
})
@@ -940,7 +942,7 @@ abstract class BTypes {
*/
def jvmWiseLUB(other: ClassBType): Either[NoClassBTypeInfo, ClassBType] = {
def isNotNullOrNothing(c: ClassBType) = !c.isNullType && !c.isNothingType
- assert(isNotNullOrNothing(this) && isNotNullOrNothing(other), s"jvmWiseLub for null or nothing: $this - $other")
+ assert(isNotNullOrNothing(this) && isNotNullOrNothing(other), s"jvmWiseLUB for null or nothing: $this - $other")
tryEither {
val res: ClassBType = (this.isInterface.orThrow, other.isInterface.orThrow) match {
@@ -965,7 +967,7 @@ abstract class BTypes {
firstCommonSuffix(this :: this.superClassesTransitive.orThrow, other :: other.superClassesTransitive.orThrow)
}
- assert(isNotNullOrNothing(res), s"jvmWiseLub computed: $res")
+ assert(isNotNullOrNothing(res), s"jvmWiseLUB computed: $res")
Right(res)
}
}
@@ -987,17 +989,6 @@ abstract class BTypes {
}
object ClassBType {
- /**
- * Valid flags for InnerClass attribute entry.
- * See http://docs.oracle.com/javase/specs/jvms/se8/html/jvms-4.html#jvms-4.7.6
- */
- private val INNER_CLASSES_FLAGS = {
- asm.Opcodes.ACC_PUBLIC | asm.Opcodes.ACC_PRIVATE | asm.Opcodes.ACC_PROTECTED |
- asm.Opcodes.ACC_STATIC | asm.Opcodes.ACC_FINAL | asm.Opcodes.ACC_INTERFACE |
- asm.Opcodes.ACC_ABSTRACT | asm.Opcodes.ACC_SYNTHETIC | asm.Opcodes.ACC_ANNOTATION |
- asm.Opcodes.ACC_ENUM
- }
-
// Primitive classes have no super class. A ClassBType for those is only created when
// they are actually being compiled (e.g., when compiling scala/Boolean.scala).
private val hasNoSuper = Set(
diff --git a/src/compiler/scala/tools/nsc/backend/jvm/BTypesFromSymbols.scala b/src/compiler/scala/tools/nsc/backend/jvm/BTypesFromSymbols.scala
index fffb9286b8..5f8f0e167c 100644
--- a/src/compiler/scala/tools/nsc/backend/jvm/BTypesFromSymbols.scala
+++ b/src/compiler/scala/tools/nsc/backend/jvm/BTypesFromSymbols.scala
@@ -7,7 +7,7 @@ package scala.tools.nsc
package backend.jvm
import scala.tools.asm
-import scala.tools.nsc.backend.jvm.opt.{LocalOpt, CallGraph, Inliner, ByteCodeRepository}
+import scala.tools.nsc.backend.jvm.opt._
import scala.tools.nsc.backend.jvm.BTypes.{InlineInfo, MethodInlineInfo, InternalName}
import BackendReporting._
import scala.tools.nsc.settings.ScalaSettings
@@ -42,6 +42,8 @@ class BTypesFromSymbols[G <: Global](val global: G) extends BTypes {
val inliner: Inliner[this.type] = new Inliner(this)
+ val closureOptimizer: ClosureOptimizer[this.type] = new ClosureOptimizer(this)
+
val callGraph: CallGraph[this.type] = new CallGraph(this)
val backendReporting: BackendReporting = new BackendReportingImpl(global)
@@ -213,35 +215,6 @@ class BTypesFromSymbols[G <: Global](val global: G) extends BTypes {
assert(!primitiveTypeMap.contains(sym) || isCompilingPrimitive, sym)
}
- /**
- * Reconstruct the classfile flags from a Java defined class symbol.
- *
- * The implementation of this method is slightly different that [[javaFlags]]. The javaFlags
- * method is primarily used to map Scala symbol flags to sensible classfile flags that are used
- * in the generated classfiles. For example, all classes emitted by the Scala compiler have
- * ACC_PUBLIC.
- *
- * When building a [[ClassBType]] from a Java class symbol, the flags in the type's `info` have
- * to correspond exactly to the flags in the classfile. For example, if the class is package
- * protected (i.e., it doesn't have the ACC_PUBLIC flag), this needs to be reflected in the
- * ClassBType. For example, the inliner needs the correct flags for access checks.
- *
- * Class flags are listed here:
- * https://docs.oracle.com/javase/specs/jvms/se7/html/jvms-4.html#jvms-4.1-200-E.1
- */
- private def javaClassfileFlags(classSym: Symbol): Int = {
- assert(classSym.isJava, s"Expected Java class symbol, got ${classSym.fullName}")
- import asm.Opcodes._
- GenBCode.mkFlags(
- if (classSym.isPublic) ACC_PUBLIC else 0,
- if (classSym.isFinal) ACC_FINAL else 0,
- if (classSym.isInterface) ACC_INTERFACE else ACC_SUPER, // see the link above. javac does the same: ACC_SUPER for all classes, but not interfaces.
- if (classSym.hasAbstractFlag) ACC_ABSTRACT else 0,
- if (classSym.isArtifact) ACC_SYNTHETIC else 0,
- if (classSym.hasEnumFlag) ACC_ENUM else 0
- )
- }
-
private def setClassInfo(classSym: Symbol, classBType: ClassBType): ClassBType = {
val superClassSym = if (classSym.isImplClass) ObjectClass else classSym.superClass
assert(
@@ -322,7 +295,7 @@ class BTypesFromSymbols[G <: Global](val global: G) extends BTypes {
val javaCompatMembers = {
if (linkedClass != NoSymbol && isTopLevelModuleClass(linkedClass))
// phase travel to exitingPickler: this makes sure that memberClassesForInnerClassTable only sees member
- // classes, not local classes of the companion module (E in the exmaple) that were lifted by lambdalift.
+ // classes, not local classes of the companion module (E in the example) that were lifted by lambdalift.
exitingPickler(memberClassesForInnerClassTable(linkedClass))
else
Nil
diff --git a/src/compiler/scala/tools/nsc/backend/jvm/BackendReporting.scala b/src/compiler/scala/tools/nsc/backend/jvm/BackendReporting.scala
index d641f708d2..4fc05cafdc 100644
--- a/src/compiler/scala/tools/nsc/backend/jvm/BackendReporting.scala
+++ b/src/compiler/scala/tools/nsc/backend/jvm/BackendReporting.scala
@@ -247,6 +247,28 @@ object BackendReporting {
callsiteClass: InternalName, callsiteName: String, callsiteDesc: String) extends CannotInlineWarning
/**
+ * Used in `rewriteClosureApplyInvocations` when a closure apply callsite cannot be rewritten
+ * to the closure body method.
+ */
+ trait RewriteClosureApplyToClosureBodyFailed extends OptimizerWarning {
+ def pos: Position
+
+ override def emitWarning(settings: ScalaSettings): Boolean = this match {
+ case RewriteClosureAccessCheckFailed(_, cause) => cause.emitWarning(settings)
+ case RewriteClosureIllegalAccess(_, _) => settings.YoptWarningEmitAtInlineFailed
+ }
+
+ override def toString: String = this match {
+ case RewriteClosureAccessCheckFailed(_, cause) =>
+ s"Failed to rewrite the closure invocation to its implementation method:\n" + cause
+ case RewriteClosureIllegalAccess(_, callsiteClass) =>
+ s"The closure body invocation cannot be rewritten because the target method is not accessible in class $callsiteClass."
+ }
+ }
+ case class RewriteClosureAccessCheckFailed(pos: Position, cause: OptimizerWarning) extends RewriteClosureApplyToClosureBodyFailed
+ case class RewriteClosureIllegalAccess(pos: Position, callsiteClass: InternalName) extends RewriteClosureApplyToClosureBodyFailed
+
+ /**
* Used in the InlineInfo of a ClassBType, when some issue occurred obtaining the inline information.
*/
sealed trait ClassInlineInfoWarning extends OptimizerWarning {
diff --git a/src/compiler/scala/tools/nsc/backend/jvm/GenASM.scala b/src/compiler/scala/tools/nsc/backend/jvm/GenASM.scala
index 76af40b330..71686fd9d7 100644
--- a/src/compiler/scala/tools/nsc/backend/jvm/GenASM.scala
+++ b/src/compiler/scala/tools/nsc/backend/jvm/GenASM.scala
@@ -479,10 +479,6 @@ abstract class GenASM extends SubComponent with BytecodeWriters { self =>
val CLASS_CONSTRUCTOR_NAME = "<clinit>"
val INSTANCE_CONSTRUCTOR_NAME = "<init>"
- val INNER_CLASSES_FLAGS =
- (asm.Opcodes.ACC_PUBLIC | asm.Opcodes.ACC_PRIVATE | asm.Opcodes.ACC_PROTECTED |
- asm.Opcodes.ACC_STATIC | asm.Opcodes.ACC_INTERFACE | asm.Opcodes.ACC_ABSTRACT | asm.Opcodes.ACC_FINAL)
-
// -----------------------------------------------------------------------------------------
// factory methods
// -----------------------------------------------------------------------------------------
@@ -756,9 +752,9 @@ abstract class GenASM extends SubComponent with BytecodeWriters { self =>
val flagsWithFinal: Int = mkFlags(
// See comment in BTypes, when is a class marked static in the InnerClass table.
if (isOriginallyStaticOwner(innerSym.originalOwner)) asm.Opcodes.ACC_STATIC else 0,
- javaFlags(innerSym),
+ (if (innerSym.isJava) javaClassfileFlags(innerSym) else javaFlags(innerSym)) & ~asm.Opcodes.ACC_STATIC,
if(isDeprecated(innerSym)) asm.Opcodes.ACC_DEPRECATED else 0 // ASM pseudo-access flag
- ) & (INNER_CLASSES_FLAGS | asm.Opcodes.ACC_DEPRECATED)
+ ) & (BCodeAsmCommon.INNER_CLASSES_FLAGS | asm.Opcodes.ACC_DEPRECATED)
val flags = if (innerSym.isModuleClass) flagsWithFinal & ~asm.Opcodes.ACC_FINAL else flagsWithFinal // For SI-5676, object overriding.
val jname = javaName(innerSym) // never null
val oname = outerName(innerSym) // null when method-enclosed
diff --git a/src/compiler/scala/tools/nsc/backend/jvm/GenBCode.scala b/src/compiler/scala/tools/nsc/backend/jvm/GenBCode.scala
index c6ee36d7b2..af962c4ce0 100644
--- a/src/compiler/scala/tools/nsc/backend/jvm/GenBCode.scala
+++ b/src/compiler/scala/tools/nsc/backend/jvm/GenBCode.scala
@@ -167,6 +167,11 @@ abstract class GenBCode extends BCodeSyncAndTry {
)
}
+ // shim for SBT, see https://github.com/sbt/sbt/issues/2076
+ // TODO put this closer to classfile writing once we have closure elimination
+ // TODO create a nicer public API to find out the correspondence between sourcefile and ultimate classfiles
+ currentUnit.icode += new icodes.IClass(cd.symbol)
+
// -------------- mirror class, if needed --------------
val mirrorC =
if (isTopLevelModuleClass(claszSymbol)) {
@@ -216,12 +221,17 @@ abstract class GenBCode extends BCodeSyncAndTry {
class Worker2 {
def runGlobalOptimizations(): Unit = {
import scala.collection.convert.decorateAsScala._
- q2.asScala foreach {
- case Item2(_, _, plain, _, _) =>
- // skip mirror / bean: wd don't inline into tem, and they are not used in the plain class
- if (plain != null) callGraph.addClass(plain)
+ if (settings.YoptBuildCallGraph) {
+ q2.asScala foreach {
+ case Item2(_, _, plain, _, _) =>
+ // skip mirror / bean: wd don't inline into tem, and they are not used in the plain class
+ if (plain != null) callGraph.addClass(plain)
+ }
}
- bTypes.inliner.runInliner()
+ if (settings.YoptInlinerEnabled)
+ bTypes.inliner.runInliner()
+ if (settings.YoptClosureElimination)
+ closureOptimizer.rewriteClosureApplyInvocations()
}
def localOptimizations(classNode: ClassNode): Unit = {
@@ -229,7 +239,7 @@ abstract class GenBCode extends BCodeSyncAndTry {
}
def run() {
- if (settings.YoptInlinerEnabled) runGlobalOptimizations()
+ runGlobalOptimizations()
while (true) {
val item = q2.poll
diff --git a/src/compiler/scala/tools/nsc/backend/jvm/analysis/InstructionStackEffect.scala b/src/compiler/scala/tools/nsc/backend/jvm/analysis/InstructionStackEffect.scala
index 98e93c125b..8d8ea839e6 100644
--- a/src/compiler/scala/tools/nsc/backend/jvm/analysis/InstructionStackEffect.scala
+++ b/src/compiler/scala/tools/nsc/backend/jvm/analysis/InstructionStackEffect.scala
@@ -94,7 +94,7 @@ object InstructionStackEffect {
val isSize2 = peekStack(0).getSize == 2
if (isSize2) t(1, 0) else t(2, 0)
- case DUP => t(0, 1)
+ case DUP => t(1, 2)
case DUP_X1 => t(2, 3)
@@ -104,7 +104,7 @@ object InstructionStackEffect {
case DUP2 =>
val isSize2 = peekStack(0).getSize == 2
- if (isSize2) t(0, 1) else t(0, 2)
+ if (isSize2) t(1, 2) else t(2, 4)
case DUP2_X1 =>
val isSize2 = peekStack(0).getSize == 2
diff --git a/src/compiler/scala/tools/nsc/backend/jvm/analysis/ProdConsAnalyzer.scala b/src/compiler/scala/tools/nsc/backend/jvm/analysis/ProdConsAnalyzer.scala
new file mode 100644
index 0000000000..40f91cbed4
--- /dev/null
+++ b/src/compiler/scala/tools/nsc/backend/jvm/analysis/ProdConsAnalyzer.scala
@@ -0,0 +1,450 @@
+/* NSC -- new Scala compiler
+ * Copyright 2005-2015 LAMP/EPFL
+ * @author Martin Odersky
+ */
+
+package scala.tools.nsc
+package backend.jvm
+package analysis
+
+import java.util
+
+import scala.annotation.switch
+import scala.collection.mutable
+import scala.tools.asm.{Type, MethodVisitor}
+import scala.tools.asm.Opcodes._
+import scala.tools.asm.tree._
+import scala.tools.asm.tree.analysis._
+import scala.tools.nsc.backend.jvm.BTypes.InternalName
+
+import opt.BytecodeUtils._
+
+import scala.collection.convert.decorateAsScala._
+
+/**
+ * This class provides additional queries over ASM's built-in `SourceValue` analysis.
+ *
+ * The analysis computes for each value in a frame a set of source instructions, which are the
+ * potential producers. Most instructions produce either nothing or a stack value. For example,
+ * a `LOAD` instruction is the producer of the value pushed onto the stack. The exception are
+ * `STORE` instructions, which produce a new value for a local variable slot, so they are used
+ * as producers for the value they stored.
+ *
+ * Note that pseudo-instructions are used as initial producers for parameters and local variables.
+ * See the documentation on class InitialProducer.
+ *
+ * This class implements the following queries over the data computed by the SourceValue analysis:
+ *
+ * - producersForValueAt(insn, slot)
+ * - consumersOfValueAt(insn, slot)
+ *
+ * - producersForInputsOf(insn)
+ * - consumersOfOutputsFrom(insn)
+ *
+ * - initialProducersForValueAt(insn, slot)
+ * - ultimateConsumersOfValueAt(insn, slot)
+ *
+ * - initialProducersForInputsOf(insn)
+ * - ultimateConsumersOfOutputsFrom(insn)
+ *
+ * The following operations are considered as copying operations:
+ * - xLOAD, xSTORE
+ * - DUP, DUP2, DUP_X1, DUP_X2, DUP2_X1, DUP2_X2
+ * - SWAP
+ * - CHECKCAST
+ *
+ * If ever needed, we could introduce a mode where primitive conversions (l2i) are considered as
+ * copying operations.
+ */
+class ProdConsAnalyzer(methodNode: MethodNode, classInternalName: InternalName) {
+ val analyzer = new Analyzer(new InitialProducerSourceInterpreter)
+ analyzer.analyze(classInternalName, methodNode)
+
+ def frameAt(insn: AbstractInsnNode) = analyzer.frameAt(insn, methodNode)
+
+ /**
+ * Returns the potential producer instructions of a (local or stack) value in the frame of `insn`.
+ * This method simply returns the producer information computed by the SourceValue analysis.
+ */
+ def producersForValueAt(insn: AbstractInsnNode, slot: Int): Set[AbstractInsnNode] = {
+ frameAt(insn).getValue(slot).insns.asScala.toSet
+ }
+
+ /**
+ * Returns the potential consumer instructions of a (local or stack) value in the frame of `insn`.
+ * This is the counterpart of `producersForValueAt`.
+ */
+ def consumersOfValueAt(insn: AbstractInsnNode, slot: Int): Set[AbstractInsnNode] = {
+ producersForValueAt(insn, slot).flatMap(prod => {
+ val outputNumber = outputValueSlots(prod).indexOf(slot)
+ _consumersOfOutputsFrom.get(prod).map(v => {
+ v(outputNumber)
+ }).getOrElse(Set.empty)
+ })
+ }
+
+ /**
+ * Returns the potential producer instructions of any of the values consumed by `insn`.
+ */
+ def producersForInputsOf(insn: AbstractInsnNode): Set[AbstractInsnNode] = {
+ inputValues(insn).iterator.flatMap(v => v.insns.asScala).toSet
+ }
+
+ def consumersOfOutputsFrom(insn: AbstractInsnNode): Set[AbstractInsnNode] =
+ _consumersOfOutputsFrom.get(insn).map(v => v.indices.flatMap(v.apply)(collection.breakOut): Set[AbstractInsnNode]).getOrElse(Set.empty)
+
+ /**
+ * Returns the potential initial producer instructions of a value in the frame of `insn`.
+ *
+ * Unlike `producersForValueAt`, producers are tracked through copying instructions such as STORE
+ * and LOAD. If the producer of the value is a LOAD, then the producers of the stored value(s) are
+ * returned instead.
+ */
+ def initialProducersForValueAt(insn: AbstractInsnNode, slot: Int): Set[AbstractInsnNode] = {
+ def initialProducers(insn: AbstractInsnNode, producedSlot: Int): Set[AbstractInsnNode] = {
+ if (isCopyOperation(insn)) {
+ _initialProducersCache.getOrElseUpdate((insn, producedSlot), {
+ val (sourceValue, sourceValueSlot) = copyOperationSourceValue(insn, producedSlot)
+ sourceValue.insns.iterator.asScala.flatMap(initialProducers(_, sourceValueSlot)).toSet
+ })
+ } else {
+ Set(insn)
+ }
+ }
+ producersForValueAt(insn, slot).flatMap(initialProducers(_, slot))
+ }
+
+ /**
+ * Returns the potential ultimate consumers of a value in the frame of `insn`. Consumers are
+ * tracked through copying operations such as SOTRE and LOAD.
+ */
+ def ultimateConsumersOfValueAt(insn: AbstractInsnNode, slot: Int): Set[AbstractInsnNode] = {
+ def ultimateConsumers(insn: AbstractInsnNode, consumedSlot: Int): Set[AbstractInsnNode] = {
+ if (isCopyOperation(insn)) {
+ _ultimateConsumersCache.getOrElseUpdate((insn, consumedSlot), {
+ for {
+ producedSlot <- copyOperationProducedValueSlots(insn, consumedSlot)
+ consumer <- consumersOfValueAt(insn.getNext, producedSlot)
+ ultimateConsumer <- ultimateConsumers(consumer, producedSlot)
+ } yield ultimateConsumer
+ })
+ } else {
+ Set(insn)
+ }
+ }
+ consumersOfValueAt(insn, slot).flatMap(ultimateConsumers(_, slot))
+ }
+
+ def initialProducersForInputsOf(insn: AbstractInsnNode): Set[AbstractInsnNode] = {
+ inputValueSlots(insn).flatMap(slot => initialProducersForValueAt(insn, slot)).toSet
+ }
+
+ def ultimateConsumersOfOutputsFrom(insn: AbstractInsnNode): Set[AbstractInsnNode] = {
+ lazy val next = insn.getNext
+ outputValueSlots(insn).flatMap(slot => ultimateConsumersOfValueAt(next, slot)).toSet
+ }
+
+ private def isCopyOperation(insn: AbstractInsnNode): Boolean = {
+ isVarInstruction(insn) || {
+ (insn.getOpcode: @switch) match {
+ case DUP | DUP_X1 | DUP_X2 | DUP2 | DUP2_X1 | DUP2_X2 | SWAP | CHECKCAST => true
+ case _ => false
+ }
+ }
+ }
+
+ /**
+ * Returns the value and its frame slot that `copyOp` copies into `producedSlot`.
+ *
+ * Example:
+ * - copyOp = DUP_X1, assume it produces slots 2,3,4
+ * - producedSlot = 3
+ * - the result is the value at slot 2 in the frame of `copyOp`
+ */
+ private def copyOperationSourceValue(copyOp: AbstractInsnNode, producedSlot: Int): (SourceValue, Int) = {
+ val frame = frameAt(copyOp)
+
+ // Index of the produced value. Example: DUP_X1 produces 3 values, so producedIndex is 0, 1 or 2,
+ // where 0 corresponds to the lowest value on the stack.
+ def producedIndex(numConsumed: Int) = {
+ val numUsedSlotsBeforeCopy = frame.stackTop + 1
+ producedSlot - (numUsedSlotsBeforeCopy - numConsumed)
+ }
+
+ def stackValue(n: Int) = (frame.peekStack(n), frame.stackTop - n)
+
+ def dupX1Case = (producedIndex(2): @switch) match {
+ case 0 | 2 => stackValue(0)
+ case 1 => stackValue(1)
+ }
+
+ // Form 1 of dup_x2
+ def dupX2Case = (producedIndex(3): @switch) match {
+ case 0 | 3 => stackValue(0)
+ case 1 => stackValue(2)
+ case 2 => stackValue(1)
+ }
+
+ // Form 1 of dup2_x1
+ def dup2X1Case = (producedIndex(3): @switch) match {
+ case 0 | 3 => stackValue(1)
+ case 1 | 4 => stackValue(0)
+ case 2 => stackValue(2)
+ }
+
+ if (isLoad(copyOp)) {
+ val slot = copyOp.asInstanceOf[VarInsnNode].`var`
+ (frame.getLocal(slot), slot)
+ } else if (isStore(copyOp)) {
+ stackValue(0)
+ } else (copyOp.getOpcode: @switch) match {
+ case DUP =>
+ stackValue(0) // the current stack top is the source of both produced values
+
+ case DUP_X1 =>
+ dupX1Case
+
+ case DUP_X2 =>
+ if (frame.peekStack(1).getSize == 2) dupX1Case
+ else dupX2Case
+
+ case DUP2 =>
+ if (frame.peekStack(0).getSize == 2) stackValue(0)
+ else {
+ (producedIndex(2): @switch) match {
+ case 0 | 2 => stackValue(1)
+ case 1 | 3 => stackValue(0)
+ }
+ }
+
+ case DUP2_X1 =>
+ if (frame.peekStack(0).getSize == 2) dupX1Case
+ else dup2X1Case
+
+ case DUP2_X2 =>
+ val v1isSize2 = frame.peekStack(0).getSize == 2
+ if (v1isSize2) {
+ val v2isSize2 = frame.peekStack(1).getSize == 2
+ if (v2isSize2) dupX1Case // Form 4
+ else dupX2Case // Form 2
+ } else {
+ val v3isSize2 = frame.peekStack(2).getSize == 2
+ if (v3isSize2) dup2X1Case // Form 3
+ else {
+ // Form 1
+ (producedIndex(4): @switch) match {
+ case 0 | 4 => stackValue(1)
+ case 1 | 5 => stackValue(0)
+ case 2 => stackValue(3)
+ case 3 => stackValue(2)
+ }
+ }
+ }
+
+ case SWAP =>
+ if (producedIndex(2) == 0) stackValue(0)
+ else stackValue(1)
+
+ case CHECKCAST =>
+ stackValue(0)
+ }
+ }
+
+ /**
+ * Returns the value slots into which `copyOp` copies the value at `consumedSlot`.
+ *
+ * Example:
+ * - copyOp = DUP_X1, assume it consumes slots 2,3 and produces 2,3,4
+ * - if consumedSlot == 2, the result is Set(3)
+ * - if consumedSlot == 3, the result is Set(2, 4)
+ */
+ private def copyOperationProducedValueSlots(copyOp: AbstractInsnNode, consumedSlot: Int): Set[Int] = {
+ if (isStore(copyOp)) Set(copyOp.asInstanceOf[VarInsnNode].`var`)
+ else {
+ val nextFrame = frameAt(copyOp.getNext)
+ val top = nextFrame.stackTop
+
+ // Index of the consumed value. Example: DUP_X1 consumes two values, so consumedIndex is
+ // 0 or 1, where 0 corresponds to the lower value on the stack.
+ def consumedIndex(numProduced: Int) = {
+ val numUsedSlotsAfterCopy = top + 1
+ consumedSlot - (numUsedSlotsAfterCopy - numProduced)
+ }
+
+ def dupX1Case = (consumedIndex(3): @switch) match {
+ case 0 => Set(top - 1)
+ case 1 => Set(top - 2, top)
+ }
+
+ def dupX2Case = (consumedIndex(4): @switch) match {
+ case 0 => Set(top - 2)
+ case 1 => Set(top - 1)
+ case 2 => Set(top - 3, top)
+ }
+
+ def dup2X1Case = (consumedIndex(5): @switch) match {
+ case 0 => Set(top - 2)
+ case 1 => Set(top - 4, top - 1)
+ case 2 => Set(top - 3, top)
+ }
+
+ if (isLoad(copyOp)) Set(top)
+ else (copyOp.getOpcode: @switch) match {
+ case DUP =>
+ Set(top - 1, top)
+
+ case DUP_X1 =>
+ dupX1Case
+
+ case DUP_X2 =>
+ if (nextFrame.peekStack(1).getSize == 2) dupX1Case
+ else dupX2Case
+
+ case DUP2 =>
+ if (nextFrame.peekStack(0).getSize == 2) Set(top - 1, top)
+ else (consumedIndex(4): @switch) match {
+ case 0 => Set(top - 3, top - 1)
+ case 1 => Set(top - 2, top)
+ }
+
+ case DUP2_X1 =>
+ if (nextFrame.peekStack(0).getSize == 2) dupX1Case
+ else dup2X1Case
+
+ case DUP2_X2 =>
+ val v1isSize2 = nextFrame.peekStack(0).getSize == 2
+ if (v1isSize2) {
+ val v2isSize2 = nextFrame.peekStack(1).getSize == 2
+ if (v2isSize2) dupX1Case // Form 4
+ else dupX2Case // Form 2
+ } else {
+ val v3isSize2 = nextFrame.peekStack(2).getSize == 2
+ if (v3isSize2) dup2X1Case // Form 3
+ else {
+ // Form 1
+ (consumedIndex(6): @switch) match {
+ case 0 => Set(top - 3)
+ case 1 => Set(top - 2)
+ case 2 => Set(top - 5, top - 1)
+ case 3 => Set(top - 4, top)
+ }
+ }
+ }
+
+ case SWAP =>
+ if (consumedIndex(2) == 0) Set(top)
+ else Set(top - 1)
+
+ case CHECKCAST =>
+ Set(top)
+ }
+ }
+ }
+
+ /** Returns the frame values consumed by executing `insn`. */
+ private def inputValues(insn: AbstractInsnNode): Seq[SourceValue] = {
+ lazy val frame = frameAt(insn)
+ inputValueSlots(insn) map frame.getValue
+ }
+
+ /** Returns the frame slots holding the values consumed by executing `insn`. */
+ private def inputValueSlots(insn: AbstractInsnNode): Seq[Int] = {
+ if (insn.getOpcode == -1) return Seq.empty
+ if (isLoad(insn)) {
+ Seq(insn.asInstanceOf[VarInsnNode].`var`)
+ } else if (insn.getOpcode == IINC) {
+ Seq(insn.asInstanceOf[IincInsnNode].`var`)
+ } else {
+ val frame = frameAt(insn)
+ val stackEffect = InstructionStackEffect(insn, frame)
+ val stackSize = frame.getLocals + frame.getStackSize
+ (stackSize - stackEffect._1) until stackSize
+ }
+ }
+
+ /** Returns the frame slots holding the values produced by executing `insn`. */
+ private def outputValueSlots(insn: AbstractInsnNode): Seq[Int] = insn match {
+ case ParameterProducer(local) => Seq(local)
+ case UninitializedLocalProducer(local) => Seq(local)
+ case ExceptionProducer(frame) => Seq(frame.stackTop)
+ case _ =>
+ if (insn.getOpcode == -1) return Seq.empty
+ if (isStore(insn)) {
+ Seq(insn.asInstanceOf[VarInsnNode].`var`)
+ } else if (insn.getOpcode == IINC) {
+ Seq(insn.asInstanceOf[IincInsnNode].`var`)
+ } else {
+ val frame = frameAt(insn)
+ val stackEffect = InstructionStackEffect(insn, frame)
+ val nextFrame = frameAt(insn.getNext)
+ val stackSize = nextFrame.getLocals + nextFrame.getStackSize
+ (stackSize - stackEffect._2) until stackSize
+ }
+ }
+
+ /** For each instruction, a set of potential consumers of the produced values. */
+ private lazy val _consumersOfOutputsFrom: Map[AbstractInsnNode, Vector[Set[AbstractInsnNode]]] = {
+ var res = Map.empty[AbstractInsnNode, Vector[Set[AbstractInsnNode]]]
+ for {
+ insn <- methodNode.instructions.iterator.asScala
+ frame = frameAt(insn)
+ i <- inputValueSlots(insn)
+ producer <- frame.getValue(i).insns.asScala
+ } {
+ val producedSlots = outputValueSlots(producer)
+ val currentConsumers = res.getOrElse(producer, Vector.fill(producedSlots.size)(Set.empty[AbstractInsnNode]))
+ val outputIndex = producedSlots.indexOf(i)
+ res = res.updated(producer, currentConsumers.updated(outputIndex, currentConsumers(outputIndex) + insn))
+ }
+ res
+ }
+
+ private val _initialProducersCache: mutable.AnyRefMap[(AbstractInsnNode, Int), Set[AbstractInsnNode]] = mutable.AnyRefMap.empty
+ private val _ultimateConsumersCache: mutable.AnyRefMap[(AbstractInsnNode, Int), Set[AbstractInsnNode]] = mutable.AnyRefMap.empty
+}
+
+/**
+ * A class for pseudo-instructions representing the initial producers of local values that have
+ * no producer instruction in the method:
+ * - parameters, including `this`
+ * - uninitialized local variables
+ * - exception values in handlers
+ *
+ * The ASM built-in SourceValue analysis yields an empty producers set for such values. This leads
+ * to ambiguities. Example (in Java one can re-assign parameter):
+ *
+ * void foo(int a) {
+ * if (a == 0) a = 1;
+ * return a;
+ * }
+ *
+ * In the first frame of the method, the SoruceValue for parameter `a` gives an empty set of
+ * producer instructions.
+ *
+ * In the frame of the `IRETURN` instruction, the SoruceValue for parameter `a` lists a single
+ * producer instruction: the `ISTORE 1`. This makes it look as if there was a single producer for
+ * `a`, where in fact it might still hold the parameter's initial value.
+ */
+abstract class InitialProducer extends AbstractInsnNode(-1) {
+ override def getType: Int = throw new UnsupportedOperationException
+ override def clone(labels: util.Map[LabelNode, LabelNode]): AbstractInsnNode = throw new UnsupportedOperationException
+ override def accept(cv: MethodVisitor): Unit = throw new UnsupportedOperationException
+}
+
+case class ParameterProducer(local: Int) extends InitialProducer
+case class UninitializedLocalProducer(local: Int) extends InitialProducer
+case class ExceptionProducer(handlerFrame: Frame[_ <: Value]) extends InitialProducer
+
+class InitialProducerSourceInterpreter extends SourceInterpreter {
+ override def newParameterValue(isInstanceMethod: Boolean, local: Int, tp: Type): SourceValue = {
+ new SourceValue(tp.getSize, ParameterProducer(local))
+ }
+
+ override def newEmptyNonParameterLocalValue(local: Int): SourceValue = {
+ new SourceValue(1, UninitializedLocalProducer(local))
+ }
+
+ override def newExceptionValue(tryCatchBlockNode: TryCatchBlockNode, handlerFrame: Frame[_ <: Value], exceptionType: Type): SourceValue = {
+ new SourceValue(1, ExceptionProducer(handlerFrame))
+ }
+} \ No newline at end of file
diff --git a/src/compiler/scala/tools/nsc/backend/jvm/opt/ByteCodeRepository.scala b/src/compiler/scala/tools/nsc/backend/jvm/opt/ByteCodeRepository.scala
index 607b7145d6..a5b85e54e7 100644
--- a/src/compiler/scala/tools/nsc/backend/jvm/opt/ByteCodeRepository.scala
+++ b/src/compiler/scala/tools/nsc/backend/jvm/opt/ByteCodeRepository.scala
@@ -102,7 +102,7 @@ class ByteCodeRepository(val classPath: ClassFileLookup[AbstractFile], val isJav
}
/**
- * The method node for a method matching `name` and `descriptor`, accessed in class `classInternalName`.
+ * The method node for a method matching `name` and `descriptor`, accessed in class `ownerInternalNameOrArrayDescriptor`.
* 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
@@ -127,7 +127,7 @@ class ByteCodeRepository(val classPath: ClassFileLookup[AbstractFile], val isJav
case Nil => Left(failedClasses)
}
- // In a MethodInsnNode, the `owner` field may be an array descriptor, for exmple when invoking `clone`. We don't have a method node to return in this case.
+ // In a MethodInsnNode, the `owner` field may be an array descriptor, for example when invoking `clone`. We don't have a method node to return in this case.
if (ownerInternalNameOrArrayDescriptor.charAt(0) == '[')
Left(MethodNotFound(name, descriptor, ownerInternalNameOrArrayDescriptor, Nil))
else
diff --git a/src/compiler/scala/tools/nsc/backend/jvm/opt/BytecodeUtils.scala b/src/compiler/scala/tools/nsc/backend/jvm/opt/BytecodeUtils.scala
index 9bd016f964..0ec550981a 100644
--- a/src/compiler/scala/tools/nsc/backend/jvm/opt/BytecodeUtils.scala
+++ b/src/compiler/scala/tools/nsc/backend/jvm/opt/BytecodeUtils.scala
@@ -14,7 +14,6 @@ import scala.tools.asm.commons.CodeSizeEvaluator
import scala.tools.asm.tree.analysis._
import scala.tools.asm.{MethodWriter, ClassWriter, Label, Opcodes}
import scala.tools.asm.tree._
-import scala.collection.convert.decorateAsScala._
import GenBCode._
import scala.collection.convert.decorateAsScala._
import scala.collection.convert.decorateAsJava._
@@ -73,11 +72,18 @@ object BytecodeUtils {
op >= Opcodes.IRETURN && op <= Opcodes.RETURN
}
- def isVarInstruction(instruction: AbstractInsnNode): Boolean = {
+ def isLoad(instruction: AbstractInsnNode): Boolean = {
val op = instruction.getOpcode
- (op >= Opcodes.ILOAD && op <= Opcodes.ALOAD) || (op >= Opcodes.ISTORE && op <= Opcodes.ASTORE)
+ op >= Opcodes.ILOAD && op <= Opcodes.ALOAD
}
+ def isStore(instruction: AbstractInsnNode): Boolean = {
+ val op = instruction.getOpcode
+ op >= Opcodes.ISTORE && op <= Opcodes.ASTORE
+ }
+
+ def isVarInstruction(instruction: AbstractInsnNode): Boolean = isLoad(instruction) || isStore(instruction)
+
def isExecutable(instruction: AbstractInsnNode): Boolean = instruction.getOpcode >= 0
def isConstructor(methodNode: MethodNode): Boolean = {
diff --git a/src/compiler/scala/tools/nsc/backend/jvm/opt/CallGraph.scala b/src/compiler/scala/tools/nsc/backend/jvm/opt/CallGraph.scala
index 0932564b1f..8abecdb261 100644
--- a/src/compiler/scala/tools/nsc/backend/jvm/opt/CallGraph.scala
+++ b/src/compiler/scala/tools/nsc/backend/jvm/opt/CallGraph.scala
@@ -11,6 +11,7 @@ import scala.reflect.internal.util.{NoPosition, Position}
import scala.tools.asm.tree.analysis.{Value, Analyzer, BasicInterpreter}
import scala.tools.asm.{Opcodes, Type}
import scala.tools.asm.tree._
+import scala.collection.concurrent
import scala.collection.convert.decorateAsScala._
import scala.tools.nsc.backend.jvm.BTypes.InternalName
import scala.tools.nsc.backend.jvm.BackendReporting._
@@ -21,14 +22,25 @@ import BytecodeUtils._
class CallGraph[BT <: BTypes](val btypes: BT) {
import btypes._
- val callsites: collection.concurrent.Map[MethodInsnNode, Callsite] = recordPerRunCache(collection.concurrent.TrieMap.empty[MethodInsnNode, Callsite])
+ val callsites: concurrent.Map[MethodInsnNode, Callsite] = recordPerRunCache(concurrent.TrieMap.empty)
+
+ val closureInstantiations: concurrent.Map[InvokeDynamicInsnNode, (MethodNode, ClassBType)] = recordPerRunCache(concurrent.TrieMap.empty)
def addClass(classNode: ClassNode): Unit = {
- for (m <- classNode.methods.asScala; callsite <- analyzeCallsites(m, classBTypeFromClassNode(classNode)))
- callsites(callsite.callsiteInstruction) = callsite
+ val classType = classBTypeFromClassNode(classNode)
+ for {
+ m <- classNode.methods.asScala
+ (calls, closureInits) = analyzeCallsites(m, classType)
+ } {
+ calls foreach (callsite => callsites(callsite.callsiteInstruction) = callsite)
+ closureInits foreach (indy => closureInstantiations(indy) = (m, classType))
+ }
}
- def analyzeCallsites(methodNode: MethodNode, definingClass: ClassBType): List[Callsite] = {
+ /**
+ * Returns a list of callsites in the method, plus a list of closure instantiation indy instructions.
+ */
+ def analyzeCallsites(methodNode: MethodNode, definingClass: ClassBType): (List[Callsite], List[InvokeDynamicInsnNode]) = {
case class CallsiteInfo(safeToInline: Boolean, safeToRewrite: Boolean,
annotatedInline: Boolean, annotatedNoInline: Boolean,
@@ -116,7 +128,10 @@ class CallGraph[BT <: BTypes](val btypes: BT) {
case _ => false
}
- methodNode.instructions.iterator.asScala.collect({
+ val callsites = new collection.mutable.ListBuffer[Callsite]
+ val closureInstantiations = new collection.mutable.ListBuffer[InvokeDynamicInsnNode]
+
+ methodNode.instructions.iterator.asScala foreach {
case call: MethodInsnNode =>
val callee: Either[OptimizerWarning, Callee] = for {
(method, declarationClass) <- byteCodeRepository.methodNode(call.owner, call.name, call.desc): Either[OptimizerWarning, (MethodNode, InternalName)]
@@ -147,7 +162,7 @@ class CallGraph[BT <: BTypes](val btypes: BT) {
receiverNotNullByAnalysis(call, numArgs)
}
- Callsite(
+ callsites += Callsite(
callsiteInstruction = call,
callsiteMethod = methodNode,
callsiteClass = definingClass,
@@ -157,7 +172,14 @@ class CallGraph[BT <: BTypes](val btypes: BT) {
receiverKnownNotNull = receiverNotNull,
callsitePosition = callsitePositions.getOrElse(call, NoPosition)
)
- }).toList
+
+ case indy: InvokeDynamicInsnNode =>
+ if (closureOptimizer.isClosureInstantiation(indy)) closureInstantiations += indy
+
+ case _ =>
+ }
+
+ (callsites.toList, closureInstantiations.toList)
}
/**
@@ -201,7 +223,7 @@ class CallGraph[BT <: BTypes](val btypes: BT) {
* @param calleeDeclarationClass The class in which the callee is declared
* @param safeToInline True if the callee can be safely inlined: it cannot be overridden,
* and the inliner settings (project / global) allow inlining it.
- * @param safeToRewrite True if the callee the interface method of a concrete trait method
+ * @param safeToRewrite True if the callee is the interface method of a concrete trait method
* that can be safely re-written to the static implementation method.
* @param annotatedInline True if the callee is annotated @inline
* @param annotatedNoInline True if the callee is annotated @noinline
diff --git a/src/compiler/scala/tools/nsc/backend/jvm/opt/ClosureOptimizer.scala b/src/compiler/scala/tools/nsc/backend/jvm/opt/ClosureOptimizer.scala
new file mode 100644
index 0000000000..1648a53ed8
--- /dev/null
+++ b/src/compiler/scala/tools/nsc/backend/jvm/opt/ClosureOptimizer.scala
@@ -0,0 +1,369 @@
+/* NSC -- new Scala compiler
+ * Copyright 2005-2015 LAMP/EPFL
+ * @author Martin Odersky
+ */
+
+package scala.tools.nsc
+package backend.jvm
+package opt
+
+import scala.annotation.switch
+import scala.reflect.internal.util.NoPosition
+import scala.tools.asm.{Handle, Type, Opcodes}
+import scala.tools.asm.tree._
+import scala.tools.nsc.backend.jvm.BTypes.InternalName
+import scala.tools.nsc.backend.jvm.analysis.ProdConsAnalyzer
+import BytecodeUtils._
+import BackendReporting._
+import Opcodes._
+import scala.tools.nsc.backend.jvm.opt.ByteCodeRepository.CompilationUnit
+import scala.collection.convert.decorateAsScala._
+
+class ClosureOptimizer[BT <: BTypes](val btypes: BT) {
+ import btypes._
+ import callGraph._
+
+ def rewriteClosureApplyInvocations(): Unit = {
+ closureInstantiations foreach {
+ case (indy, (methodNode, ownerClass)) =>
+ val warnings = rewriteClosureApplyInvocations(indy, methodNode, ownerClass)
+ warnings.foreach(w => backendReporting.inlinerWarning(w.pos, w.toString))
+ }
+ }
+
+ private val lambdaMetaFactoryInternalName: InternalName = "java/lang/invoke/LambdaMetafactory"
+
+ private val metafactoryHandle = {
+ val metafactoryMethodName: String = "metafactory"
+ val metafactoryDesc: String = "(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;"
+ new Handle(H_INVOKESTATIC, lambdaMetaFactoryInternalName, metafactoryMethodName, metafactoryDesc)
+ }
+
+ private val altMetafactoryHandle = {
+ val altMetafactoryMethodName: String = "altMetafactory"
+ val altMetafactoryDesc: String = "(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;[Ljava/lang/Object;)Ljava/lang/invoke/CallSite;"
+ new Handle(H_INVOKESTATIC, lambdaMetaFactoryInternalName, altMetafactoryMethodName, altMetafactoryDesc)
+ }
+
+ def isClosureInstantiation(indy: InvokeDynamicInsnNode): Boolean = {
+ (indy.bsm == metafactoryHandle || indy.bsm == altMetafactoryHandle) &&
+ {
+ indy.bsmArgs match {
+ case Array(samMethodType: Type, implMethod: Handle, instantiatedMethodType: Type, xs @ _*) =>
+ // LambdaMetaFactory performs a number of automatic adaptations when invoking the lambda
+ // implementation method (casting, boxing, unboxing, and primitive widening, see Javadoc).
+ //
+ // The closure optimizer supports only one of those adaptations: it will cast arguments
+ // to the correct type when re-writing a closure call to the body method. Example:
+ //
+ // val fun: String => String = l => l
+ // val l = List("")
+ // fun(l.head)
+ //
+ // The samMethodType of Function1 is `(Object)Object`, while the instantiatedMethodType
+ // is `(String)String`. The return type of `List.head` is `Object`.
+ //
+ // The implMethod has the signature `C$anonfun(String)String`.
+ //
+ // At the closure callsite, we have an `INVOKEINTERFACE Function1.apply (Object)Object`,
+ // so the object returned by `List.head` can be directly passed into the call (no cast).
+ //
+ // The closure object will cast the object to String before passing it to the implMethod.
+ //
+ // When re-writing the closure callsite to the implMethod, we have to insert a cast.
+ //
+ // The check below ensures that
+ // (1) the implMethod type has the expected singature (captured types plus argument types
+ // from instantiatedMethodType)
+ // (2) the receiver of the implMethod matches the first captured type
+ // (3) all parameters that are not the same in samMethodType and instantiatedMethodType
+ // are reference types, so that we can insert casts to perform the same adaptation
+ // that the closure object would.
+
+ val isStatic = implMethod.getTag == H_INVOKESTATIC
+ val indyParamTypes = Type.getArgumentTypes(indy.desc)
+ val instantiatedMethodArgTypes = instantiatedMethodType.getArgumentTypes
+ val expectedImplMethodType = {
+ val paramTypes = (if (isStatic) indyParamTypes else indyParamTypes.tail) ++ instantiatedMethodArgTypes
+ Type.getMethodType(instantiatedMethodType.getReturnType, paramTypes: _*)
+ }
+
+ {
+ Type.getType(implMethod.getDesc) == expectedImplMethodType // (1)
+ } && {
+ isStatic || implMethod.getOwner == indyParamTypes(0).getInternalName // (2)
+ } && {
+ def isReference(t: Type) = t.getSort == Type.OBJECT || t.getSort == Type.ARRAY
+ (samMethodType.getArgumentTypes, instantiatedMethodArgTypes).zipped forall {
+ case (samArgType, instArgType) =>
+ samArgType == instArgType || isReference(samArgType) && isReference(instArgType) // (3)
+ }
+ }
+
+ case _ =>
+ false
+ }
+ }
+ }
+
+ def isSamInvocation(invocation: MethodInsnNode, indy: InvokeDynamicInsnNode, prodCons: => ProdConsAnalyzer): Boolean = {
+ if (invocation.getOpcode == INVOKESTATIC) false
+ else {
+ def closureIsReceiver = {
+ val invocationFrame = prodCons.frameAt(invocation)
+ val receiverSlot = {
+ val numArgs = Type.getArgumentTypes(invocation.desc).length
+ invocationFrame.stackTop - numArgs
+ }
+ val receiverProducers = prodCons.initialProducersForValueAt(invocation, receiverSlot)
+ receiverProducers.size == 1 && receiverProducers.head == indy
+ }
+
+ invocation.name == indy.name && {
+ val indySamMethodDesc = indy.bsmArgs(0).asInstanceOf[Type].getDescriptor // safe, checked in isClosureInstantiation
+ indySamMethodDesc == invocation.desc
+ } &&
+ closureIsReceiver // most expensive check last
+ }
+ }
+
+ /**
+ * Stores the values captured by a closure creation into fresh local variables.
+ * Returns the list of locals holding the captured values.
+ */
+ private def storeCaptures(indy: InvokeDynamicInsnNode, methodNode: MethodNode): LocalsList = {
+ val capturedTypes = Type.getArgumentTypes(indy.desc)
+ val firstCaptureLocal = methodNode.maxLocals
+
+ // This could be optimized: in many cases the captured values are produced by LOAD instructions.
+ // If the variable is not modified within the method, we could avoid introducing yet another
+ // local. On the other hand, further optimizations (copy propagation, remove unused locals) will
+ // clean it up.
+
+ // Captured variables don't need to be cast when loaded at the callsite (castLoadTypes are None).
+ // This is checked in `isClosureInstantiation`: the types of the captured variables in the indy
+ // instruction match exactly the corresponding parameter types in the body method.
+ val localsForCaptures = LocalsList.fromTypes(firstCaptureLocal, capturedTypes, castLoadTypes = _ => None)
+ methodNode.maxLocals = firstCaptureLocal + localsForCaptures.size
+
+ insertStoreOps(indy, methodNode, localsForCaptures)
+ insertLoadOps(indy, methodNode, localsForCaptures)
+
+ localsForCaptures
+ }
+
+ /**
+ * Insert store operations in front of the `before` instruction to copy stack values into the
+ * locals denoted by `localsList`.
+ *
+ * The lowest stack value is stored in the head of the locals list, so the last local is stored first.
+ */
+ private def insertStoreOps(before: AbstractInsnNode, methodNode: MethodNode, localsList: LocalsList) =
+ insertLocalValueOps(before, methodNode, localsList, store = true)
+
+ /**
+ * Insert load operations in front of the `before` instruction to copy the local values denoted
+ * by `localsList` onto the stack.
+ *
+ * The head of the locals list will be the lowest value on the stack, so the first local is loaded first.
+ */
+ private def insertLoadOps(before: AbstractInsnNode, methodNode: MethodNode, localsList: LocalsList) =
+ insertLocalValueOps(before, methodNode, localsList, store = false)
+
+ private def insertLocalValueOps(before: AbstractInsnNode, methodNode: MethodNode, localsList: LocalsList, store: Boolean): Unit = {
+ // If `store` is true, the first instruction needs to store into the last local of the `localsList`.
+ // Load instructions on the other hand are emitted in the order of the list.
+ // To avoid reversing the list, we use `insert(previousInstr)` for stores and `insertBefore(before)` for loads.
+ lazy val previous = before.getPrevious
+ for (l <- localsList.locals) {
+ val varOp = new VarInsnNode(if (store) l.storeOpcode else l.loadOpcode, l.local)
+ if (store) methodNode.instructions.insert(previous, varOp)
+ else methodNode.instructions.insertBefore(before, varOp)
+ if (!store) for (castType <- l.castLoadedValue)
+ methodNode.instructions.insert(varOp, new TypeInsnNode(CHECKCAST, castType.getInternalName))
+ }
+ }
+
+ def rewriteClosureApplyInvocations(indy: InvokeDynamicInsnNode, methodNode: MethodNode, ownerClass: ClassBType): List[RewriteClosureApplyToClosureBodyFailed] = {
+ val lambdaBodyHandle = indy.bsmArgs(1).asInstanceOf[Handle] // safe, checked in isClosureInstantiation
+
+ // Kept as a lazy val to make sure the analysis is only computed if it's actually needed.
+ // ProdCons is used to identify closure body invocations (see isSamInvocation), but only if the
+ // callsite has the right name and signature. If the method has no invcation instruction with
+ // the right name and signature, the analysis is not executed.
+ lazy val prodCons = new ProdConsAnalyzer(methodNode, ownerClass.internalName)
+
+ // First collect all callsites without modifying the instructions list yet.
+ // Once we start modifying the instruction list, prodCons becomes unusable.
+
+ // A list of callsites and stack heights. If the invocation cannot be rewritten, a warning
+ // message is stored in the stack height value.
+ val invocationsToRewrite: List[(MethodInsnNode, Either[RewriteClosureApplyToClosureBodyFailed, Int])] = methodNode.instructions.iterator.asScala.collect({
+ case invocation: MethodInsnNode if isSamInvocation(invocation, indy, prodCons) =>
+ val bodyAccessible: Either[OptimizerWarning, Boolean] = for {
+ (bodyMethodNode, declClass) <- byteCodeRepository.methodNode(lambdaBodyHandle.getOwner, lambdaBodyHandle.getName, lambdaBodyHandle.getDesc): Either[OptimizerWarning, (MethodNode, InternalName)]
+ isAccessible <- inliner.memberIsAccessible(bodyMethodNode.access, classBTypeFromParsedClassfile(declClass), classBTypeFromParsedClassfile(lambdaBodyHandle.getOwner), ownerClass)
+ } yield {
+ isAccessible
+ }
+
+ def pos = callGraph.callsites.get(invocation).map(_.callsitePosition).getOrElse(NoPosition)
+ val stackSize: Either[RewriteClosureApplyToClosureBodyFailed, Int] = bodyAccessible match {
+ case Left(w) => Left(RewriteClosureAccessCheckFailed(pos, w))
+ case Right(false) => Left(RewriteClosureIllegalAccess(pos, ownerClass.internalName))
+ case _ => Right(prodCons.frameAt(invocation).getStackSize)
+ }
+
+ (invocation, stackSize)
+ }).toList
+
+ if (invocationsToRewrite.isEmpty) Nil
+ else {
+ // lazy val to make sure locals for captures and arguments are only allocated if there's
+ // effectively a callsite to rewrite.
+ lazy val (localsForCapturedValues, argumentLocalsList) = {
+ val captureLocals = storeCaptures(indy, methodNode)
+
+ // allocate locals for storing the arguments of the closure apply callsites.
+ // if there are multiple callsites, the same locals are re-used.
+ val argTypes = indy.bsmArgs(0).asInstanceOf[Type].getArgumentTypes // safe, checked in isClosureInstantiation
+ val firstArgLocal = methodNode.maxLocals
+
+ // The comment in `isClosureInstantiation` explains why we have to introduce casts for
+ // arguments that have different types in samMethodType and instantiatedMethodType.
+ val castLoadTypes = {
+ val instantiatedMethodType = indy.bsmArgs(2).asInstanceOf[Type]
+ (argTypes, instantiatedMethodType.getArgumentTypes).zipped map {
+ case (samArgType, instantiatedArgType) if samArgType != instantiatedArgType =>
+ // isClosureInstantiation ensures that the two types are reference types, so we don't
+ // end up casting primitive values.
+ Some(instantiatedArgType)
+ case _ =>
+ None
+ }
+ }
+ val argLocals = LocalsList.fromTypes(firstArgLocal, argTypes, castLoadTypes)
+ methodNode.maxLocals = firstArgLocal + argLocals.size
+
+ (captureLocals, argLocals)
+ }
+
+ val warnings = invocationsToRewrite flatMap {
+ case (invocation, Left(warning)) => Some(warning)
+
+ case (invocation, Right(stackHeight)) =>
+ // store arguments
+ insertStoreOps(invocation, methodNode, argumentLocalsList)
+
+ // drop the closure from the stack
+ methodNode.instructions.insertBefore(invocation, new InsnNode(POP))
+
+ // load captured values and arguments
+ insertLoadOps(invocation, methodNode, localsForCapturedValues)
+ insertLoadOps(invocation, methodNode, argumentLocalsList)
+
+ // update maxStack
+ val capturesStackSize = localsForCapturedValues.size
+ val invocationStackHeight = stackHeight + capturesStackSize - 1 // -1 because the closure is gone
+ if (invocationStackHeight > methodNode.maxStack)
+ methodNode.maxStack = invocationStackHeight
+
+ // replace the callsite with a new call to the body method
+ val bodyOpcode = (lambdaBodyHandle.getTag: @switch) match {
+ case H_INVOKEVIRTUAL => INVOKEVIRTUAL
+ case H_INVOKESTATIC => INVOKESTATIC
+ case H_INVOKESPECIAL => INVOKESPECIAL
+ case H_INVOKEINTERFACE => INVOKEINTERFACE
+ case H_NEWINVOKESPECIAL =>
+ val insns = methodNode.instructions
+ insns.insertBefore(invocation, new TypeInsnNode(NEW, lambdaBodyHandle.getOwner))
+ insns.insertBefore(invocation, new InsnNode(DUP))
+ INVOKESPECIAL
+ }
+ val isInterface = bodyOpcode == INVOKEINTERFACE
+ val bodyInvocation = new MethodInsnNode(bodyOpcode, lambdaBodyHandle.getOwner, lambdaBodyHandle.getName, lambdaBodyHandle.getDesc, isInterface)
+ methodNode.instructions.insertBefore(invocation, bodyInvocation)
+ methodNode.instructions.remove(invocation)
+
+ // update the call graph
+ val originalCallsite = callGraph.callsites.remove(invocation)
+
+ // the method node is needed for building the call graph entry
+ val bodyMethod = byteCodeRepository.methodNode(lambdaBodyHandle.getOwner, lambdaBodyHandle.getName, lambdaBodyHandle.getDesc)
+ def bodyMethodIsBeingCompiled = byteCodeRepository.classNodeAndSource(lambdaBodyHandle.getOwner).map(_._2 == CompilationUnit).getOrElse(false)
+ val bodyMethodCallsite = Callsite(
+ callsiteInstruction = bodyInvocation,
+ callsiteMethod = methodNode,
+ callsiteClass = ownerClass,
+ callee = bodyMethod.map({
+ case (bodyMethodNode, bodyMethodDeclClass) => Callee(
+ callee = bodyMethodNode,
+ calleeDeclarationClass = classBTypeFromParsedClassfile(bodyMethodDeclClass),
+ safeToInline = compilerSettings.YoptInlineGlobal || bodyMethodIsBeingCompiled,
+ safeToRewrite = false, // the lambda body method is not a trait interface method
+ annotatedInline = false,
+ annotatedNoInline = false,
+ calleeInfoWarning = None)
+ }),
+ argInfos = Nil,
+ callsiteStackHeight = invocationStackHeight,
+ receiverKnownNotNull = true, // see below (*)
+ callsitePosition = originalCallsite.map(_.callsitePosition).getOrElse(NoPosition)
+ )
+ // (*) The documentation in class LambdaMetafactory says:
+ // "if implMethod corresponds to an instance method, the first capture argument
+ // (corresponding to the receiver) must be non-null"
+ // Explanation: If the lambda body method is non-static, the receiver is a captured
+ // value. It can only be captured within some instance method, so we know it's non-null.
+ callGraph.callsites(bodyInvocation) = bodyMethodCallsite
+ None
+ }
+
+ warnings.toList
+ }
+ }
+
+ /**
+ * A list of local variables. Each local stores information about its type, see class [[Local]].
+ */
+ case class LocalsList(locals: List[Local]) {
+ val size = locals.iterator.map(_.size).sum
+ }
+
+ object LocalsList {
+ /**
+ * A list of local variables starting at `firstLocal` that can hold values of the types in the
+ * `types` parameter.
+ *
+ * For example, `fromTypes(3, Array(Int, Long, String))` returns
+ * Local(3, intOpOffset) ::
+ * Local(4, longOpOffset) :: // note that this local occupies two slots, the next is at 6
+ * Local(6, refOpOffset) ::
+ * Nil
+ */
+ def fromTypes(firstLocal: Int, types: Array[Type], castLoadTypes: Int => Option[Type]): LocalsList = {
+ var sizeTwoOffset = 0
+ val locals: List[Local] = types.indices.map(i => {
+ // The ASM method `type.getOpcode` returns the opcode for operating on a value of `type`.
+ val offset = types(i).getOpcode(ILOAD) - ILOAD
+ val local = Local(firstLocal + i + sizeTwoOffset, offset, castLoadTypes(i))
+ if (local.size == 2) sizeTwoOffset += 1
+ local
+ })(collection.breakOut)
+ LocalsList(locals)
+ }
+ }
+
+ /**
+ * Stores a local varaible index the opcode offset required for operating on that variable.
+ *
+ * The xLOAD / xSTORE opcodes are in the following sequence: I, L, F, D, A, so the offset for
+ * a local variable holding a reference (`A`) is 4. See also method `getOpcode` in [[scala.tools.asm.Type]].
+ */
+ case class Local(local: Int, opcodeOffset: Int, castLoadedValue: Option[Type]) {
+ def size = if (loadOpcode == LLOAD || loadOpcode == DLOAD) 2 else 1
+
+ def loadOpcode = ILOAD + opcodeOffset
+ def storeOpcode = ISTORE + opcodeOffset
+ }
+}
diff --git a/src/compiler/scala/tools/nsc/backend/jvm/opt/Inliner.scala b/src/compiler/scala/tools/nsc/backend/jvm/opt/Inliner.scala
index b4f091b37f..e8e848161c 100644
--- a/src/compiler/scala/tools/nsc/backend/jvm/opt/Inliner.scala
+++ b/src/compiler/scala/tools/nsc/backend/jvm/opt/Inliner.scala
@@ -26,7 +26,8 @@ class Inliner[BT <: BTypes](val btypes: BT) {
def eliminateUnreachableCodeAndUpdateCallGraph(methodNode: MethodNode, definingClass: InternalName): Unit = {
localOpt.minimalRemoveUnreachableCode(methodNode, definingClass) foreach {
- case invocation: MethodInsnNode => callGraph.callsites.remove(invocation)
+ case invocation: MethodInsnNode => callGraph.callsites.remove(invocation)
+ case indy: InvokeDynamicInsnNode => callGraph.closureInstantiations.remove(indy)
case _ =>
}
}
@@ -432,7 +433,7 @@ class Inliner[BT <: BTypes](val btypes: BT) {
callsiteMethod.localVariables.addAll(cloneLocalVariableNodes(callee, labelsMap, callee.name + "_").asJava)
callsiteMethod.tryCatchBlocks.addAll(cloneTryCatchBlockNodes(callee, labelsMap).asJava)
- // Add all invocation instructions that were inlined to the call graph
+ // Add all invocation instructions and closure instantiations that were inlined to the call graph
callee.instructions.iterator().asScala foreach {
case originalCallsiteIns: MethodInsnNode =>
callGraph.callsites.get(originalCallsiteIns) match {
@@ -452,6 +453,15 @@ class Inliner[BT <: BTypes](val btypes: BT) {
case None =>
}
+ case indy: InvokeDynamicInsnNode =>
+ callGraph.closureInstantiations.get(indy) match {
+ case Some((methodNode, ownerClass)) =>
+ val newIndy = instructionMap(indy).asInstanceOf[InvokeDynamicInsnNode]
+ callGraph.closureInstantiations(newIndy) = (callsiteMethod, callsiteClass)
+
+ case None =>
+ }
+
case _ =>
}
// Remove the elided invocation from the call graph
@@ -529,98 +539,97 @@ class Inliner[BT <: BTypes](val btypes: BT) {
}
/**
- * Returns the first instruction in the `instructions` list that would cause a
- * [[java.lang.IllegalAccessError]] when inlined into the `destinationClass`.
- *
- * If validity of some instruction could not be checked because an error occurred, the instruction
- * is returned together with a warning message that describes the problem.
+ * Check if a type is accessible to some class, as defined in JVMS 5.4.4.
+ * (A1) C is public
+ * (A2) C and D are members of the same run-time package
*/
- def findIllegalAccess(instructions: InsnList, calleeDeclarationClass: ClassBType, destinationClass: ClassBType): Option[(AbstractInsnNode, Option[OptimizerWarning])] = {
-
- /**
- * Check if a type is accessible to some class, as defined in JVMS 5.4.4.
- * (A1) C is public
- * (A2) C and D are members of the same run-time package
- */
- def classIsAccessible(accessed: BType, from: ClassBType = destinationClass): Either[OptimizerWarning, Boolean] = (accessed: @unchecked) match {
- // TODO: A2 requires "same run-time package", which seems to be package + classloader (JMVS 5.3.). is the below ok?
- case c: ClassBType => c.isPublic.map(_ || c.packageInternalName == from.packageInternalName)
- case a: ArrayBType => classIsAccessible(a.elementType, from)
- case _: PrimitiveBType => Right(true)
- }
+ def classIsAccessible(accessed: BType, from: ClassBType): Either[OptimizerWarning, Boolean] = (accessed: @unchecked) match {
+ // TODO: A2 requires "same run-time package", which seems to be package + classloader (JMVS 5.3.). is the below ok?
+ case c: ClassBType => c.isPublic.map(_ || c.packageInternalName == from.packageInternalName)
+ case a: ArrayBType => classIsAccessible(a.elementType, from)
+ case _: PrimitiveBType => Right(true)
+ }
- /**
- * Check if a member reference is accessible from the [[destinationClass]], as defined in the
- * JVMS 5.4.4. Note that the class name in a field / method reference is not necessarily the
- * class in which the member is declared:
- *
- * class A { def f = 0 }; class B extends A { f }
- *
- * The INVOKEVIRTUAL instruction uses a method reference "B.f ()I". Therefore this method has
- * two parameters:
- *
- * @param memberDeclClass The class in which the member is declared (A)
- * @param memberRefClass The class used in the member reference (B)
- *
- * (B0) JVMS 5.4.3.2 / 5.4.3.3: when resolving a member of class C in D, the class C is resolved
- * first. According to 5.4.3.1, this requires C to be accessible in D.
- *
- * JVMS 5.4.4 summary: A field or method R is accessible to a class D (destinationClass) iff
- * (B1) R is public
- * (B2) R is protected, declared in C (memberDeclClass) and D is a subclass of C.
- * If R is not static, R must contain a symbolic reference to a class T (memberRefClass),
- * such that T is either a subclass of D, a superclass of D, or D itself.
- * Also (P) needs to be satisfied.
- * (B3) R is either protected or has default access and declared by a class in the same
- * run-time package as D.
- * If R is protected, also (P) needs to be satisfied.
- * (B4) R is private and is declared in D.
- *
- * (P) When accessing a protected instance member, the target object on the stack (the receiver)
- * has to be a subtype of D (destinationClass). This is enforced by classfile verification
- * (https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-4.html#jvms-4.10.1.8).
- *
- * TODO: we cannot currently implement (P) because we don't have the necessary information
- * available. Once we have a type propagation analysis implemented, we can extract the receiver
- * type from there (https://github.com/scala-opt/scala/issues/13).
- */
- def memberIsAccessible(memberFlags: Int, memberDeclClass: ClassBType, memberRefClass: ClassBType): Either[OptimizerWarning, Boolean] = {
- // TODO: B3 requires "same run-time package", which seems to be package + classloader (JMVS 5.3.). is the below ok?
- def samePackageAsDestination = memberDeclClass.packageInternalName == destinationClass.packageInternalName
- def targetObjectConformsToDestinationClass = false // needs type propagation analysis, see above
-
- def memberIsAccessibleImpl = {
- val key = (ACC_PUBLIC | ACC_PROTECTED | ACC_PRIVATE) & memberFlags
- key match {
- case ACC_PUBLIC => // B1
- Right(true)
-
- case ACC_PROTECTED => // B2
- val isStatic = (ACC_STATIC & memberFlags) != 0
- tryEither {
- val condB2 = destinationClass.isSubtypeOf(memberDeclClass).orThrow && {
- isStatic || memberRefClass.isSubtypeOf(destinationClass).orThrow || destinationClass.isSubtypeOf(memberRefClass).orThrow
- }
- Right(
- (condB2 || samePackageAsDestination /* B3 (protected) */) &&
- (isStatic || targetObjectConformsToDestinationClass) // (P)
- )
+ /**
+ * Check if a member reference is accessible from the [[destinationClass]], as defined in the
+ * JVMS 5.4.4. Note that the class name in a field / method reference is not necessarily the
+ * class in which the member is declared:
+ *
+ * class A { def f = 0 }; class B extends A { f }
+ *
+ * The INVOKEVIRTUAL instruction uses a method reference "B.f ()I". Therefore this method has
+ * two parameters:
+ *
+ * @param memberDeclClass The class in which the member is declared (A)
+ * @param memberRefClass The class used in the member reference (B)
+ *
+ * (B0) JVMS 5.4.3.2 / 5.4.3.3: when resolving a member of class C in D, the class C is resolved
+ * first. According to 5.4.3.1, this requires C to be accessible in D.
+ *
+ * JVMS 5.4.4 summary: A field or method R is accessible to a class D (destinationClass) iff
+ * (B1) R is public
+ * (B2) R is protected, declared in C (memberDeclClass) and D is a subclass of C.
+ * If R is not static, R must contain a symbolic reference to a class T (memberRefClass),
+ * such that T is either a subclass of D, a superclass of D, or D itself.
+ * Also (P) needs to be satisfied.
+ * (B3) R is either protected or has default access and declared by a class in the same
+ * run-time package as D.
+ * If R is protected, also (P) needs to be satisfied.
+ * (B4) R is private and is declared in D.
+ *
+ * (P) When accessing a protected instance member, the target object on the stack (the receiver)
+ * has to be a subtype of D (destinationClass). This is enforced by classfile verification
+ * (https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-4.html#jvms-4.10.1.8).
+ *
+ * TODO: we cannot currently implement (P) because we don't have the necessary information
+ * available. Once we have a type propagation analysis implemented, we can extract the receiver
+ * type from there (https://github.com/scala-opt/scala/issues/13).
+ */
+ def memberIsAccessible(memberFlags: Int, memberDeclClass: ClassBType, memberRefClass: ClassBType, from: ClassBType): Either[OptimizerWarning, Boolean] = {
+ // TODO: B3 requires "same run-time package", which seems to be package + classloader (JMVS 5.3.). is the below ok?
+ def samePackageAsDestination = memberDeclClass.packageInternalName == from.packageInternalName
+ def targetObjectConformsToDestinationClass = false // needs type propagation analysis, see above
+
+ def memberIsAccessibleImpl = {
+ val key = (ACC_PUBLIC | ACC_PROTECTED | ACC_PRIVATE) & memberFlags
+ key match {
+ case ACC_PUBLIC => // B1
+ Right(true)
+
+ case ACC_PROTECTED => // B2
+ val isStatic = (ACC_STATIC & memberFlags) != 0
+ tryEither {
+ val condB2 = from.isSubtypeOf(memberDeclClass).orThrow && {
+ isStatic || memberRefClass.isSubtypeOf(from).orThrow || from.isSubtypeOf(memberRefClass).orThrow
}
+ Right(
+ (condB2 || samePackageAsDestination /* B3 (protected) */) &&
+ (isStatic || targetObjectConformsToDestinationClass) // (P)
+ )
+ }
- case 0 => // B3 (default access)
- Right(samePackageAsDestination)
+ case 0 => // B3 (default access)
+ Right(samePackageAsDestination)
- case ACC_PRIVATE => // B4
- Right(memberDeclClass == destinationClass)
- }
+ case ACC_PRIVATE => // B4
+ Right(memberDeclClass == from)
}
+ }
- classIsAccessible(memberDeclClass) match { // B0
- case Right(true) => memberIsAccessibleImpl
- case r => r
- }
+ classIsAccessible(memberDeclClass, from) match { // B0
+ case Right(true) => memberIsAccessibleImpl
+ case r => r
}
+ }
+ /**
+ * Returns the first instruction in the `instructions` list that would cause a
+ * [[java.lang.IllegalAccessError]] when inlined into the `destinationClass`.
+ *
+ * If validity of some instruction could not be checked because an error occurred, the instruction
+ * is returned together with a warning message that describes the problem.
+ */
+ def findIllegalAccess(instructions: InsnList, calleeDeclarationClass: ClassBType, destinationClass: ClassBType): Option[(AbstractInsnNode, Option[OptimizerWarning])] = {
/**
* Check if `instruction` can be transplanted to `destinationClass`.
*
@@ -637,18 +646,18 @@ class Inliner[BT <: BTypes](val btypes: BT) {
// NEW, ANEWARRAY, CHECKCAST or INSTANCEOF. For these instructions, the reference
// "must be a symbolic reference to a class, array, or interface type" (JVMS 6), so
// it can be an internal name, or a full array descriptor.
- classIsAccessible(bTypeForDescriptorOrInternalNameFromClassfile(ti.desc))
+ classIsAccessible(bTypeForDescriptorOrInternalNameFromClassfile(ti.desc), destinationClass)
case ma: MultiANewArrayInsnNode =>
// "a symbolic reference to a class, array, or interface type"
- classIsAccessible(bTypeForDescriptorOrInternalNameFromClassfile(ma.desc))
+ classIsAccessible(bTypeForDescriptorOrInternalNameFromClassfile(ma.desc), destinationClass)
case fi: FieldInsnNode =>
val fieldRefClass = classBTypeFromParsedClassfile(fi.owner)
for {
(fieldNode, fieldDeclClassNode) <- byteCodeRepository.fieldNode(fieldRefClass.internalName, fi.name, fi.desc): Either[OptimizerWarning, (FieldNode, InternalName)]
fieldDeclClass = classBTypeFromParsedClassfile(fieldDeclClassNode)
- res <- memberIsAccessible(fieldNode.access, fieldDeclClass, fieldRefClass)
+ res <- memberIsAccessible(fieldNode.access, fieldDeclClass, fieldRefClass, destinationClass)
} yield {
res
}
@@ -664,7 +673,7 @@ class Inliner[BT <: BTypes](val btypes: BT) {
Right(destinationClass == calleeDeclarationClass)
case _ => // INVOKEVIRTUAL, INVOKESTATIC, INVOKEINTERFACE and INVOKESPECIAL of constructors
- memberIsAccessible(methodFlags, methodDeclClass, methodRefClass)
+ memberIsAccessible(methodFlags, methodDeclClass, methodRefClass, destinationClass)
}
}
@@ -683,7 +692,7 @@ class Inliner[BT <: BTypes](val btypes: BT) {
Right(false)
case ci: LdcInsnNode => ci.cst match {
- case t: asm.Type => classIsAccessible(bTypeForDescriptorOrInternalNameFromClassfile(t.getInternalName))
+ case t: asm.Type => classIsAccessible(bTypeForDescriptorOrInternalNameFromClassfile(t.getInternalName), destinationClass)
case _ => Right(true)
}
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 5f51a94673..bd5bab28b5 100644
--- a/src/compiler/scala/tools/nsc/backend/jvm/opt/LocalOpt.scala
+++ b/src/compiler/scala/tools/nsc/backend/jvm/opt/LocalOpt.scala
@@ -262,7 +262,7 @@ object LocalOptImpls {
* the same index, but distinct start / end ranges are different variables, they may have not the
* same type or name.
*/
- def removeUnusedLocalVariableNodes(method: MethodNode)(fistLocalIndex: Int = parametersSize(method), renumber: Int => Int = identity): Boolean = {
+ def removeUnusedLocalVariableNodes(method: MethodNode)(firstLocalIndex: Int = parametersSize(method), renumber: Int => Int = identity): Boolean = {
def variableIsUsed(start: AbstractInsnNode, end: LabelNode, varIndex: Int): Boolean = {
start != end && (start match {
case v: VarInsnNode if v.`var` == varIndex => true
@@ -276,7 +276,7 @@ object LocalOptImpls {
val local = localsIter.next()
val index = local.index
// parameters and `this` (the lowest indices, starting at 0) are never removed or renumbered
- if (index >= fistLocalIndex) {
+ if (index >= firstLocalIndex) {
if (!variableIsUsed(local.start, local.end, index)) localsIter.remove()
else if (renumber(index) != index) local.index = renumber(index)
}
diff --git a/src/compiler/scala/tools/nsc/backend/opt/DeadCodeElimination.scala b/src/compiler/scala/tools/nsc/backend/opt/DeadCodeElimination.scala
index 1b6631e7a4..8911a3a28c 100644
--- a/src/compiler/scala/tools/nsc/backend/opt/DeadCodeElimination.scala
+++ b/src/compiler/scala/tools/nsc/backend/opt/DeadCodeElimination.scala
@@ -378,7 +378,7 @@ abstract class DeadCodeElimination extends SubComponent {
} else {
i match {
case NEW(REFERENCE(sym)) =>
- log(s"Eliminated instantation of $sym inside $m")
+ log(s"Eliminated instantiation of $sym inside $m")
case STORE_LOCAL(l) if clobbers contains ((bb, idx)) =>
// if an unused instruction was a clobber of a used store to a reference or array type
// then we'll replace it with the store of a null to make sure the reference is
diff --git a/src/compiler/scala/tools/nsc/javac/JavaParsers.scala b/src/compiler/scala/tools/nsc/javac/JavaParsers.scala
index d34c14be0f..9708cba281 100644
--- a/src/compiler/scala/tools/nsc/javac/JavaParsers.scala
+++ b/src/compiler/scala/tools/nsc/javac/JavaParsers.scala
@@ -761,9 +761,13 @@ trait JavaParsers extends ast.parser.ParsersCommon with JavaScanners {
val interfaces = interfacesOpt()
accept(LBRACE)
val buf = new ListBuffer[Tree]
+ var enumIsFinal = true
def parseEnumConsts() {
if (in.token != RBRACE && in.token != SEMI && in.token != EOF) {
- buf += enumConst(enumType)
+ val (const, hasClassBody) = enumConst(enumType)
+ buf += const
+ // if any of the enum constants has a class body, the enum class is not final (JLS 8.9.)
+ enumIsFinal &&= !hasClassBody
if (in.token == COMMA) {
in.nextToken()
parseEnumConsts()
@@ -793,15 +797,25 @@ trait JavaParsers extends ast.parser.ParsersCommon with JavaScanners {
accept(RBRACE)
val superclazz =
AppliedTypeTree(javaLangDot(tpnme.Enum), List(enumType))
+ val finalFlag = if (enumIsFinal) Flags.FINAL else 0l
+ val abstractFlag = {
+ // javac adds `ACC_ABSTRACT` to enum classes with deferred members
+ val hasAbstractMember = body exists {
+ case d: DefDef => d.mods.isDeferred
+ case _ => false
+ }
+ if (hasAbstractMember) Flags.ABSTRACT else 0l
+ }
addCompanionObject(consts ::: statics ::: predefs, atPos(pos) {
- ClassDef(mods | Flags.ENUM, name, List(),
+ ClassDef(mods | Flags.ENUM | finalFlag | abstractFlag, name, List(),
makeTemplate(superclazz :: interfaces, body))
})
}
- def enumConst(enumType: Tree) = {
+ def enumConst(enumType: Tree): (ValDef, Boolean) = {
annotations()
- atPos(in.currentPos) {
+ var hasClassBody = false
+ val res = atPos(in.currentPos) {
val name = ident()
if (in.token == LPAREN) {
// skip arguments
@@ -809,12 +823,14 @@ trait JavaParsers extends ast.parser.ParsersCommon with JavaScanners {
accept(RPAREN)
}
if (in.token == LBRACE) {
+ hasClassBody = true
// skip classbody
skipAhead()
accept(RBRACE)
}
ValDef(Modifiers(Flags.ENUM | Flags.STABLE | Flags.JAVA | Flags.STATIC), name.toTermName, enumType, blankExpr)
}
+ (res, hasClassBody)
}
def typeDecl(mods: Modifiers): List[Tree] = in.token match {
diff --git a/src/compiler/scala/tools/nsc/reporters/Reporter.scala b/src/compiler/scala/tools/nsc/reporters/Reporter.scala
index 3d688efae1..bd438f0e75 100644
--- a/src/compiler/scala/tools/nsc/reporters/Reporter.scala
+++ b/src/compiler/scala/tools/nsc/reporters/Reporter.scala
@@ -20,7 +20,7 @@ abstract class Reporter extends scala.reflect.internal.Reporter {
/** Informational messages. If `!force`, they may be suppressed. */
final def info(pos: Position, msg: String, force: Boolean): Unit = info0(pos, msg, INFO, force)
- /** For sending a message which should not be labeled as a warning/error,
+ /** For sending a message which should not be labelled as a warning/error,
* but also shouldn't require -verbose to be visible.
*/
def echo(msg: String): Unit = info(NoPosition, msg, force = true)
diff --git a/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala b/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala
index 953e43eaca..0cdece59e1 100644
--- a/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala
+++ b/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala
@@ -76,7 +76,7 @@ trait ScalaSettings extends AbsScalaSettings
val implicitConversions = Choice("implicitConversions", "Allow definition of implicit functions called views")
val higherKinds = Choice("higherKinds", "Allow higher-kinded types")
val existentials = Choice("existentials", "Existential types (besides wildcard types) can be written and inferred")
- val macros = Choice("experimental.macros", "Allow macro defintion (besides implementation and application)")
+ val macros = Choice("experimental.macros", "Allow macro definition (besides implementation and application)")
}
val language = {
val description = "Enable or disable language features"
@@ -235,6 +235,7 @@ trait ScalaSettings extends AbsScalaSettings
val emptyLabels = Choice("empty-labels", "Eliminate and collapse redundant labels in the bytecode.")
val compactLocals = Choice("compact-locals", "Eliminate empty slots in the sequence of local variables.")
val nullnessTracking = Choice("nullness-tracking", "Track nullness / non-nullness of local variables and apply optimizations.")
+ val closureElimination = Choice("closure-elimination" , "Rewrite closure invocations to the implementation method and eliminate closures.")
val inlineProject = Choice("inline-project", "Inline only methods defined in the files being compiled.")
val inlineGlobal = Choice("inline-global", "Inline methods from any source, including classfiles on the compile classpath.")
@@ -243,7 +244,7 @@ trait ScalaSettings extends AbsScalaSettings
private val defaultChoices = List(unreachableCode)
val lDefault = Choice("l:default", "Enable default optimizations: "+ defaultChoices.mkString(","), expandsTo = defaultChoices)
- private val methodChoices = List(unreachableCode, simplifyJumps, emptyLineNumbers, emptyLabels, compactLocals, nullnessTracking)
+ private val methodChoices = List(unreachableCode, simplifyJumps, emptyLineNumbers, emptyLabels, compactLocals, nullnessTracking, closureElimination)
val lMethod = Choice("l:method", "Enable intra-method optimizations: "+ methodChoices.mkString(","), expandsTo = methodChoices)
private val projectChoices = List(lMethod, inlineProject)
@@ -266,11 +267,15 @@ trait ScalaSettings extends AbsScalaSettings
def YoptEmptyLabels = Yopt.contains(YoptChoices.emptyLabels)
def YoptCompactLocals = Yopt.contains(YoptChoices.compactLocals)
def YoptNullnessTracking = Yopt.contains(YoptChoices.nullnessTracking)
+ def YoptClosureElimination = Yopt.contains(YoptChoices.closureElimination)
def YoptInlineProject = Yopt.contains(YoptChoices.inlineProject)
def YoptInlineGlobal = Yopt.contains(YoptChoices.inlineGlobal)
def YoptInlinerEnabled = YoptInlineProject || YoptInlineGlobal
+ def YoptBuildCallGraph = YoptInlinerEnabled || YoptClosureElimination
+ def YoptAddToBytecodeRepository = YoptInlinerEnabled || YoptClosureElimination
+
val YoptInlineHeuristics = ChoiceSetting(
name = "-Yopt-inline-heuristics",
helpArg = "strategy",
diff --git a/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala b/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala
index 518a402230..660028eab8 100644
--- a/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala
+++ b/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala
@@ -539,6 +539,8 @@ abstract class ClassfileParser {
devWarning(s"no linked class for java enum $sym in ${sym.owner}. A referencing class file might be missing an InnerClasses entry.")
case linked =>
if (!linked.isSealed)
+ // Marking the enum class SEALED | ABSTRACT enables exhaustiveness checking.
+ // This is a bit of a hack and requires excluding the ABSTRACT flag in the backend, see method javaClassfileFlags.
linked setFlag (SEALED | ABSTRACT)
linked addChild sym
}
diff --git a/src/compiler/scala/tools/nsc/symtab/classfile/ICodeReader.scala b/src/compiler/scala/tools/nsc/symtab/classfile/ICodeReader.scala
index ea46116976..438a71061e 100644
--- a/src/compiler/scala/tools/nsc/symtab/classfile/ICodeReader.scala
+++ b/src/compiler/scala/tools/nsc/symtab/classfile/ICodeReader.scala
@@ -599,7 +599,7 @@ abstract class ICodeReader extends ClassfileParser {
}
case JVM.invokedynamic =>
// TODO, this is just a place holder. A real implementation must parse the class constant entry
- debuglog("Found JVM invokedynamic instructionm, inserting place holder ICode INVOKE_DYNAMIC.")
+ debuglog("Found JVM invokedynamic instruction, inserting place holder ICode INVOKE_DYNAMIC.")
containsInvokeDynamic = true
val poolEntry = in.nextChar.toInt
in.skip(2)
diff --git a/src/compiler/scala/tools/nsc/transform/Delambdafy.scala b/src/compiler/scala/tools/nsc/transform/Delambdafy.scala
index 55ab73028e..5a7f6c52da 100644
--- a/src/compiler/scala/tools/nsc/transform/Delambdafy.scala
+++ b/src/compiler/scala/tools/nsc/transform/Delambdafy.scala
@@ -444,7 +444,7 @@ abstract class Delambdafy extends Transform with TypingTransformers with ast.Tre
def adaptAndPostErase(tree: Tree, pt: Type): (Boolean, Tree) = {
val (needsAdapt, adaptedTree) = adapt(tree, pt)
val trans = postErasure.newTransformer(unit)
- val postErasedTree = trans.atOwner(currentOwner)(trans.transform(adaptedTree)) // SI-8017 elimnates ErasedValueTypes
+ val postErasedTree = trans.atOwner(currentOwner)(trans.transform(adaptedTree)) // SI-8017 eliminates ErasedValueTypes
(needsAdapt, postErasedTree)
}
diff --git a/src/compiler/scala/tools/nsc/transform/patmat/Logic.scala b/src/compiler/scala/tools/nsc/transform/patmat/Logic.scala
index 227c45b3a7..49a4990722 100644
--- a/src/compiler/scala/tools/nsc/transform/patmat/Logic.scala
+++ b/src/compiler/scala/tools/nsc/transform/patmat/Logic.scala
@@ -510,7 +510,7 @@ trait ScalaLogic extends Interface with Logic with TreeAndTypeAnalysis {
def propForEqualsTo(c: Const): Prop = {observed(); symForEqualsTo.getOrElse(c, False)}
// [implementation NOTE: don't access until all potential equalities have been registered using registerEquality]p
- /** the information needed to construct the boolean proposition that encods the equality proposition (V = C)
+ /** the information needed to construct the boolean proposition that encodes the equality proposition (V = C)
*
* that models a type test pattern `_: C` or constant pattern `C`, where the type test gives rise to a TypeConst C,
* and the constant pattern yields a ValueConst C
diff --git a/src/compiler/scala/tools/nsc/transform/patmat/MatchTreeMaking.scala b/src/compiler/scala/tools/nsc/transform/patmat/MatchTreeMaking.scala
index e1fe220556..e0fcc05de2 100644
--- a/src/compiler/scala/tools/nsc/transform/patmat/MatchTreeMaking.scala
+++ b/src/compiler/scala/tools/nsc/transform/patmat/MatchTreeMaking.scala
@@ -642,7 +642,7 @@ trait MatchTreeMaking extends MatchCodeGen with Debugging {
}
// override def apply
- // debug.patmat("before fixerupper: "+ xTree)
+ // debug.patmat("before fixerUpper: "+ xTree)
// currentRun.trackerFactory.snapshot()
// debug.patmat("after fixerupper")
// currentRun.trackerFactory.snapshot()
diff --git a/src/compiler/scala/tools/nsc/transform/patmat/MatchWarnings.scala b/src/compiler/scala/tools/nsc/transform/patmat/MatchWarnings.scala
index 9e9372f709..8beb1837ad 100644
--- a/src/compiler/scala/tools/nsc/transform/patmat/MatchWarnings.scala
+++ b/src/compiler/scala/tools/nsc/transform/patmat/MatchWarnings.scala
@@ -40,7 +40,7 @@ trait MatchWarnings {
}
}
- // Issue better warnings than "unreachable code" when people mis-use
+ // Issue better warnings than "unreachable code" when people misuse
// variable patterns thinking they bind to existing identifiers.
//
// Possible TODO: more deeply nested variable patterns, like
diff --git a/src/compiler/scala/tools/nsc/typechecker/ContextErrors.scala b/src/compiler/scala/tools/nsc/typechecker/ContextErrors.scala
index c80aaea160..b0bd9977a8 100644
--- a/src/compiler/scala/tools/nsc/typechecker/ContextErrors.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/ContextErrors.scala
@@ -550,23 +550,18 @@ trait ContextErrors {
def ModuleUsingCompanionClassDefaultArgsErrror(tree: Tree) =
NormalTypeError(tree, "module extending its companion class cannot use default constructor arguments")
- def NotEnoughArgsError(tree: Tree, fun0: Tree, missing0: List[Symbol]) = {
- def notEnoughArgumentsMsg(fun: Tree, missing: List[Symbol]) = {
- val suffix = {
- if (missing.isEmpty) ""
- else {
- val keep = missing take 3 map (_.name)
- ".\nUnspecified value parameter%s %s".format(
- if (missing.tail.isEmpty) "" else "s",
- if ((missing drop 3).nonEmpty) (keep :+ "...").mkString(", ")
- else keep.mkString("", ", ", ".")
- )
- }
+ def NotEnoughArgsError(tree: Tree, fun: Tree, missing: List[Symbol]) = {
+ val notEnoughArgumentsMsg = {
+ val suffix = if (missing.isEmpty) "" else {
+ val keep = missing take 3 map (_.name)
+ val ess = if (missing.tail.isEmpty) "" else "s"
+ f".%nUnspecified value parameter$ess ${
+ keep.mkString("", ", ", if ((missing drop 3).nonEmpty) "..." else ".")
+ }"
}
-
- "not enough arguments for " + treeSymTypeMsg(fun) + suffix
+ s"not enough arguments for ${ treeSymTypeMsg(fun) }$suffix"
}
- NormalTypeError(tree, notEnoughArgumentsMsg(fun0, missing0))
+ NormalTypeError(tree, notEnoughArgumentsMsg)
}
//doTypedApply - patternMode
@@ -632,12 +627,16 @@ trait ContextErrors {
//adapt
def MissingArgsForMethodTpeError(tree: Tree, meth: Symbol) = {
+ val f = meth.name
+ val paf = s"$f(${ meth.asMethod.paramLists map (_ map (_ => "_") mkString ",") mkString ")(" })"
+ val advice = s"""
+ |Unapplied methods are only converted to functions when a function type is expected.
+ |You can make this conversion explicit by writing `$f _` or `$paf` instead of `$f`.""".stripMargin
val message =
if (meth.isMacro) MacroTooFewArgumentListsMessage
- else "missing arguments for " + meth.fullLocationString + (
- if (meth.isConstructor) ""
- else ";\nfollow this method with `_' if you want to treat it as a partially applied function"
- )
+ else s"""missing argument list for ${meth.fullLocationString}${
+ if (!meth.isConstructor) advice else ""
+ }"""
issueNormalTypeError(tree, message)
setError(tree)
}
diff --git a/src/compiler/scala/tools/nsc/typechecker/Contexts.scala b/src/compiler/scala/tools/nsc/typechecker/Contexts.scala
index 542f58795a..a7ef5d5d2f 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Contexts.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Contexts.scala
@@ -1537,7 +1537,7 @@ object ContextMode {
final val TypeConstructorAllowed: ContextMode = 1 << 16
/** TODO: The "sticky modes" are EXPRmode, PATTERNmode, TYPEmode.
- * To mimick the sticky mode behavior, when captain stickyfingers
+ * To mimic the sticky mode behavior, when captain stickyfingers
* comes around we need to propagate those modes but forget the other
* context modes which were once mode bits; those being so far the
* ones listed here.
diff --git a/src/compiler/scala/tools/nsc/typechecker/Implicits.scala b/src/compiler/scala/tools/nsc/typechecker/Implicits.scala
index 5ecca5abce..80e06eb8fa 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Implicits.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Implicits.scala
@@ -985,7 +985,7 @@ trait Implicits {
if (implicitInfoss.forall(_.isEmpty)) SearchFailure
else new ImplicitComputation(implicitInfoss, isLocalToCallsite) findBest()
- /** Produce an implicict info map, i.e. a map from the class symbols C of all parts of this type to
+ /** Produce an implicit info map, i.e. a map from the class symbols C of all parts of this type to
* the implicit infos in the companion objects of these class symbols C.
* The parts of a type is the smallest set of types that contains
* - the type itself
diff --git a/src/compiler/scala/tools/nsc/typechecker/Infer.scala b/src/compiler/scala/tools/nsc/typechecker/Infer.scala
index f9582a54ff..ea0a9bb243 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Infer.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Infer.scala
@@ -934,7 +934,7 @@ trait Infer extends Checkable {
def infer_s = map3(tparams, tvars, targs)((tparam, tvar, targ) => s"$tparam=$tvar/$targ") mkString ","
printTyping(tree, s"infer expr instance from pt=$pt, $infer_s")
- // SI-7899 infering by-name types is unsound. The correct behaviour is conditional because the hole is
+ // SI-7899 inferring by-name types is unsound. The correct behaviour is conditional because the hole is
// exploited in Scalaz (Free.scala), as seen in: run/t7899-regression.
def dropByNameIfStrict(tp: Type): Type = if (settings.inferByName) tp else dropByName(tp)
def targsStrict = if (targs eq null) null else targs mapConserve dropByNameIfStrict
diff --git a/src/compiler/scala/tools/nsc/typechecker/PatternTypers.scala b/src/compiler/scala/tools/nsc/typechecker/PatternTypers.scala
index 8a66c7d274..a702b3cdf5 100644
--- a/src/compiler/scala/tools/nsc/typechecker/PatternTypers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/PatternTypers.scala
@@ -305,7 +305,7 @@ trait PatternTypers {
// clearing the type is necessary so that ref will be stabilized; see bug 881
val fun1 = typedPos(fun.pos)(Apply(Select(fun.clearType(), unapplyMethod), unapplyArgTree :: Nil))
- def makeTypedUnApply() = {
+ def makeTypedUnapply() = {
// the union of the expected type and the inferred type of the argument to unapply
val glbType = glb(ensureFullyDefined(pt) :: unapplyArg.tpe_* :: Nil)
val wrapInTypeTest = canRemedy && !(fun1.symbol.owner isNonBottomSubClass ClassTagClass)
@@ -325,7 +325,7 @@ trait PatternTypers {
if (isBlackbox(unapplyMethod)) duplErrorTree(BlackboxExtractorExpansion(tree))
else duplErrorTree(WrongShapeExtractorExpansion(tree))
} else
- makeTypedUnApply()
+ makeTypedUnapply()
}
def wrapClassTagUnapply(uncheckedPattern: Tree, classTagExtractor: Tree, pt: Type): Tree = {
diff --git a/src/compiler/scala/tools/nsc/util/DocStrings.scala b/src/compiler/scala/tools/nsc/util/DocStrings.scala
index 352816803f..4ff7067a21 100755
--- a/src/compiler/scala/tools/nsc/util/DocStrings.scala
+++ b/src/compiler/scala/tools/nsc/util/DocStrings.scala
@@ -184,7 +184,7 @@ object DocStrings {
extractSectionTag(str, section) -> section
}
- /** Extract the section tag, treating the section tag as an indentifier */
+ /** Extract the section tag, treating the section tag as an identifier */
def extractSectionTag(str: String, section: (Int, Int)): String =
str.substring(section._1, skipTag(str, section._1))
diff --git a/src/library/scala/Predef.scala b/src/library/scala/Predef.scala
index 0f300412b7..cef62922ac 100644
--- a/src/library/scala/Predef.scala
+++ b/src/library/scala/Predef.scala
@@ -82,6 +82,11 @@ object Predef extends LowPriorityImplicits with DeprecatedPredef {
*/
def classOf[T]: Class[T] = null // This is a stub method. The actual implementation is filled in by the compiler.
+ /** The `String` type in Scala has methods that come either from the underlying
+ * Java String (see the documentation corresponding to your Java version, for
+ * example [[http://docs.oracle.com/javase/8/docs/api/java/lang/String.html]]) or
+ * are added implicitly through [[scala.collection.immutable.StringOps]].
+ */
type String = java.lang.String
type Class[T] = java.lang.Class[T]
diff --git a/src/library/scala/collection/generic/Sorted.scala b/src/library/scala/collection/generic/Sorted.scala
index a0b0e1318b..b2e63daaba 100644
--- a/src/library/scala/collection/generic/Sorted.scala
+++ b/src/library/scala/collection/generic/Sorted.scala
@@ -36,7 +36,7 @@ trait Sorted[K, +This <: Sorted[K, This]] {
/** Creates a ranged projection of this collection. Any mutations in the
* ranged projection will update this collection and vice versa.
*
- * Note: keys are not garuanteed to be consistent between this collection
+ * Note: keys are not guaranteed to be consistent between this collection
* and the projection. This is the case for buffers where indexing is
* relative to the projection.
*
diff --git a/src/library/scala/collection/immutable/Stream.scala b/src/library/scala/collection/immutable/Stream.scala
index 7edd36dc22..17cf02cce6 100644
--- a/src/library/scala/collection/immutable/Stream.scala
+++ b/src/library/scala/collection/immutable/Stream.scala
@@ -153,7 +153,7 @@ import scala.language.implicitConversions
*
* - The fact that `tail` works at all is of interest. In the definition of
* `fibs` we have an initial `(0, 1, Stream(...))` so `tail` is deterministic.
- * If we deinfed `fibs` such that only `0` were concretely known then the act
+ * If we defined `fibs` such that only `0` were concretely known then the act
* of determining `tail` would require the evaluation of `tail` which would
* cause an infinite recursion and stack overflow. If we define a definition
* where the tail is not initially computable then we're going to have an
diff --git a/src/library/scala/collection/immutable/StringOps.scala b/src/library/scala/collection/immutable/StringOps.scala
index 6737692fb1..77333badf9 100644
--- a/src/library/scala/collection/immutable/StringOps.scala
+++ b/src/library/scala/collection/immutable/StringOps.scala
@@ -12,10 +12,9 @@ package immutable
import mutable.StringBuilder
-/**
- * This class serves as a wrapper providing `String`s with all the operations
- * found in indexed sequences. Where needed, instances of `String` object
- * are implicitly converted into this class.
+/** This class serves as a wrapper providing [[scala.Predef.String]]s with all
+ * the operations found in indexed sequences. Where needed, `String`s are
+ * implicitly converted into instances of this class.
*
* The difference between this class and `WrappedString` is that calling transformer
* methods such as `filter` and `map` will yield a `String` object, whereas a
diff --git a/src/library/scala/sys/BooleanProp.scala b/src/library/scala/sys/BooleanProp.scala
index 74b0a9077b..e5e4668edb 100644
--- a/src/library/scala/sys/BooleanProp.scala
+++ b/src/library/scala/sys/BooleanProp.scala
@@ -63,12 +63,13 @@ object BooleanProp {
def valueIsTrue[T](key: String): BooleanProp = new BooleanPropImpl(key, _.toLowerCase == "true")
/** As an alternative, this method creates a BooleanProp which is true
- * if the key exists in the map. This way -Dfoo.bar is enough to be
- * considered true.
+ * if the key exists in the map and is not assigned a value other than "true",
+ * compared case-insensitively, or the empty string. This way -Dmy.property
+ * results in a true-valued property, but -Dmy.property=false does not.
*
* @return A BooleanProp with a liberal truth policy
*/
- def keyExists[T](key: String): BooleanProp = new BooleanPropImpl(key, _ => true)
+ def keyExists[T](key: String): BooleanProp = new BooleanPropImpl(key, s => s == "" || s.equalsIgnoreCase("true"))
/** A constant true or false property which ignores all method calls.
*/
diff --git a/src/partest-extras/scala/tools/partest/ASMConverters.scala b/src/partest-extras/scala/tools/partest/ASMConverters.scala
index f6e2d2a9ec..90f314428b 100644
--- a/src/partest-extras/scala/tools/partest/ASMConverters.scala
+++ b/src/partest-extras/scala/tools/partest/ASMConverters.scala
@@ -131,7 +131,7 @@ object ASMConverters {
import collection.mutable.{Map => MMap}
/**
- * Bytecode is equal modula local variable numbering and label numbering.
+ * Bytecode is equal modulo local variable numbering and label numbering.
*/
def equivalentBytecode(as: List[Instruction], bs: List[Instruction], varMap: MMap[Int, Int] = MMap(), labelMap: MMap[Int, Int] = MMap()): Boolean = {
def same(v1: Int, v2: Int, m: MMap[Int, Int]) = {
diff --git a/src/partest-extras/scala/tools/partest/ReplTest.scala b/src/partest-extras/scala/tools/partest/ReplTest.scala
index 5b65d6ab9b..1fde2370d3 100644
--- a/src/partest-extras/scala/tools/partest/ReplTest.scala
+++ b/src/partest-extras/scala/tools/partest/ReplTest.scala
@@ -75,18 +75,20 @@ abstract class SessionTest extends ReplTest {
* Retain user input: prompt lines and continuations, without the prefix; or pasted text plus ctl-D.
*/
import SessionTest._
- override final def code = input findAllMatchIn (expected mkString ("", "\n", "\n")) map {
- case input(null, null, prompted) =>
+ lazy val pasted = input(prompt)
+ override final def code = pasted findAllMatchIn (expected mkString ("", "\n", "\n")) map {
+ case pasted(null, null, prompted) =>
def continued(m: Match): Option[String] = m match {
case margin(text) => Some(text)
case _ => None
}
margin.replaceSomeIn(prompted, continued)
- case input(cmd, pasted, null) =>
+ case pasted(cmd, pasted, null) =>
cmd + pasted + "\u0004"
} mkString
- final def prompt = "scala> "
+ // Just the last line of the interactive prompt
+ def prompt = "scala> "
/** Default test is to compare expected and actual output and emit the diff on a failed comparison. */
override def show() = {
@@ -98,7 +100,7 @@ abstract class SessionTest extends ReplTest {
}
object SessionTest {
// \R for line break is Java 8, \v for vertical space might suffice
- val input = """(?m)^scala> (:pa.*\u000A)// Entering paste mode.*\u000A\u000A((?:.*\u000A)*)\u000A// Exiting paste mode.*\u000A|^scala> (.*\u000A(?:\s*\| .*\u000A)*)""".r
+ def input(prompt: String) = s"""(?m)^$prompt(:pa.*\u000A)// Entering paste mode.*\u000A\u000A((?:.*\u000A)*)\u000A// Exiting paste mode.*\u000A|^scala> (.*\u000A(?:\\s*\\| .*\u000A)*)""".r
val margin = """(?m)^\s*\| (.*)$""".r
}
diff --git a/src/reflect/scala/reflect/api/FlagSets.scala b/src/reflect/scala/reflect/api/FlagSets.scala
index bcad84a3f0..d3294dad9b 100644
--- a/src/reflect/scala/reflect/api/FlagSets.scala
+++ b/src/reflect/scala/reflect/api/FlagSets.scala
@@ -48,7 +48,7 @@ import scala.language.implicitConversions
* ''Of Note:'' This part of the Reflection API is being considered as a candidate for redesign. It is
* quite possible that in future releases of the reflection API, flag sets could be replaced with something else.
*
- * For more details about `FlagSet`s and other aspects of Scala reflection, see the
+ * For more details about `FlagSet`s and other aspects of Scala reflection, see the
* [[http://docs.scala-lang.org/overviews/reflection/overview.html Reflection Guide]]
*
* @group ReflectionAPI
diff --git a/src/reflect/scala/reflect/api/Printers.scala b/src/reflect/scala/reflect/api/Printers.scala
index 01b9759c70..c0abc5120c 100644
--- a/src/reflect/scala/reflect/api/Printers.scala
+++ b/src/reflect/scala/reflect/api/Printers.scala
@@ -130,7 +130,7 @@ import java.io.{ PrintWriter, StringWriter }
* TermName("y")#2541#GET))
* }}}
*
- * For more details about `Printer`s and other aspects of Scala reflection, see the
+ * For more details about `Printer`s and other aspects of Scala reflection, see the
* [[http://docs.scala-lang.org/overviews/reflection/overview.html Reflection Guide]]
*
* @group ReflectionAPI
diff --git a/src/reflect/scala/reflect/internal/ClassfileConstants.scala b/src/reflect/scala/reflect/internal/ClassfileConstants.scala
index e0a6757d34..53241fb15b 100644
--- a/src/reflect/scala/reflect/internal/ClassfileConstants.scala
+++ b/src/reflect/scala/reflect/internal/ClassfileConstants.scala
@@ -344,10 +344,12 @@ object ClassfileConstants {
case JAVA_ACC_STATIC => STATIC
case JAVA_ACC_ABSTRACT => if (isAnnotation) 0L else if (isClass) ABSTRACT else DEFERRED
case JAVA_ACC_INTERFACE => if (isAnnotation) 0L else TRAIT | INTERFACE | ABSTRACT
+ case JAVA_ACC_ENUM => ENUM
case _ => 0L
}
- private def translateFlags(jflags: Int, baseFlags: Long, isAnnotation: Boolean, isClass: Boolean): Long = {
- def translateFlag0(jflags: Int): Long = translateFlag(jflags, isAnnotation, isClass)
+ private def translateFlags(jflags: Int, baseFlags: Long, isClass: Boolean): Long = {
+ val isAnnot = isAnnotation(jflags)
+ def translateFlag0(jflags: Int): Long = translateFlag(jflags, isAnnot, isClass)
var res: Long = JAVA | baseFlags
/* fast, elegant, maintainable, pick any two... */
res |= translateFlag0(jflags & JAVA_ACC_PRIVATE)
@@ -357,17 +359,18 @@ object ClassfileConstants {
res |= translateFlag0(jflags & JAVA_ACC_STATIC)
res |= translateFlag0(jflags & JAVA_ACC_ABSTRACT)
res |= translateFlag0(jflags & JAVA_ACC_INTERFACE)
+ res |= translateFlag0(jflags & JAVA_ACC_ENUM)
res
}
def classFlags(jflags: Int): Long = {
- translateFlags(jflags, 0, isAnnotation(jflags), isClass = true)
+ translateFlags(jflags, 0, isClass = true)
}
def fieldFlags(jflags: Int): Long = {
- translateFlags(jflags, if ((jflags & JAVA_ACC_FINAL) == 0) MUTABLE else 0 , isAnnotation(jflags), isClass = false)
+ translateFlags(jflags, if ((jflags & JAVA_ACC_FINAL) == 0) MUTABLE else 0 , isClass = false)
}
def methodFlags(jflags: Int): Long = {
- translateFlags(jflags, if ((jflags & JAVA_ACC_BRIDGE) != 0) BRIDGE | ARTIFACT else 0, isAnnotation(jflags), isClass = false)
+ translateFlags(jflags, if ((jflags & JAVA_ACC_BRIDGE) != 0) BRIDGE | ARTIFACT else 0, isClass = false)
}
}
object FlagTranslation extends FlagTranslation { }
diff --git a/src/reflect/scala/reflect/internal/ReificationSupport.scala b/src/reflect/scala/reflect/internal/ReificationSupport.scala
index eddfec82e7..d393a841b7 100644
--- a/src/reflect/scala/reflect/internal/ReificationSupport.scala
+++ b/src/reflect/scala/reflect/internal/ReificationSupport.scala
@@ -802,7 +802,7 @@ trait ReificationSupport { self: SymbolTable =>
require(enums.nonEmpty, "enumerators can't be empty")
enums.head match {
case SyntacticValFrom(_, _) =>
- case t => throw new IllegalArgumentException(s"$t is not a valid fist enumerator of for loop")
+ case t => throw new IllegalArgumentException(s"$t is not a valid first enumerator of for loop")
}
enums.tail.foreach {
case SyntacticValEq(_, _) | SyntacticValFrom(_, _) | SyntacticFilter(_) =>
diff --git a/src/reflect/scala/reflect/internal/Types.scala b/src/reflect/scala/reflect/internal/Types.scala
index f74d976b82..c760db3864 100644
--- a/src/reflect/scala/reflect/internal/Types.scala
+++ b/src/reflect/scala/reflect/internal/Types.scala
@@ -918,7 +918,7 @@ trait Types
def prefixString = trimPrefix(toString) + "#"
/** Convert toString avoiding infinite recursions by cutting off
- * after `maxTostringRecursions` recursion levels. Uses `safeToString`
+ * after `maxToStringRecursions` recursion levels. Uses `safeToString`
* to produce a string on each level.
*/
override final def toString: String = {
@@ -1489,7 +1489,7 @@ trait Types
} finally {
if (Statistics.canEnable) Statistics.popTimer(typeOpsStack, start)
}
- // [Martin] suppressing memo-ization solves the problem with "same type after erasure" errors
+ // [Martin] suppressing memoization solves the problem with "same type after erasure" errors
// when compiling with
// scalac scala.collection.IterableViewLike.scala scala.collection.IterableLike.scala
// I have not yet figured out precisely why this is the case.
diff --git a/src/reflect/scala/reflect/internal/tpe/TypeConstraints.scala b/src/reflect/scala/reflect/internal/tpe/TypeConstraints.scala
index f79099213a..e321a07f51 100644
--- a/src/reflect/scala/reflect/internal/tpe/TypeConstraints.scala
+++ b/src/reflect/scala/reflect/internal/tpe/TypeConstraints.scala
@@ -99,7 +99,7 @@ private[internal] trait TypeConstraints {
// a lower bound despite the fact that Nothing is always a lower bound. My current
// supposition is that the side-effecting type constraint accumulation mechanism
// depends on these subtype tests being performed to make forward progress when
- // there are mutally recursive type vars.
+ // there are mutually recursive type vars.
// See pos/t6367 and pos/t6499 for the competing test cases.
val mustConsider = tp.typeSymbol match {
case NothingClass => true
diff --git a/src/reflect/scala/reflect/internal/tpe/TypeMaps.scala b/src/reflect/scala/reflect/internal/tpe/TypeMaps.scala
index c705ca7069..15a87200f1 100644
--- a/src/reflect/scala/reflect/internal/tpe/TypeMaps.scala
+++ b/src/reflect/scala/reflect/internal/tpe/TypeMaps.scala
@@ -561,7 +561,7 @@ private[internal] trait TypeMaps {
| tparams ${rhsSym.typeParams map own_s mkString ", "}
|"""
- if (argIndex < 0)
+ if (!rhsArgs.isDefinedAt(argIndex))
abort(s"Something is wrong: cannot find $lhs in applied type $rhs\n" + explain)
else {
val targ = rhsArgs(argIndex)
diff --git a/src/reflect/scala/reflect/internal/util/StripMarginInterpolator.scala b/src/reflect/scala/reflect/internal/util/StripMarginInterpolator.scala
index e622e78d57..35858cdc78 100644
--- a/src/reflect/scala/reflect/internal/util/StripMarginInterpolator.scala
+++ b/src/reflect/scala/reflect/internal/util/StripMarginInterpolator.scala
@@ -13,7 +13,7 @@ trait StripMarginInterpolator {
* The margin of each line is defined by whitespace leading up to a '|' character.
* This margin is stripped '''before''' the arguments are interpolated into to string.
*
- * String escape sequences are '''not''' processed; this interpolater is designed to
+ * String escape sequences are '''not''' processed; this interpolator is designed to
* be used with triple quoted Strings.
*
* {{{
diff --git a/src/reflect/scala/reflect/macros/FrontEnds.scala b/src/reflect/scala/reflect/macros/FrontEnds.scala
index a770f325b2..8ad41382a8 100644
--- a/src/reflect/scala/reflect/macros/FrontEnds.scala
+++ b/src/reflect/scala/reflect/macros/FrontEnds.scala
@@ -12,7 +12,7 @@ package macros
trait FrontEnds {
self: blackbox.Context =>
- /** For sending a message which should not be labeled as a warning/error,
+ /** For sending a message which should not be labelled as a warning/error,
* but also shouldn't require -verbose to be visible.
* Use `enclosingPosition` if you're in doubt what position to pass to `pos`.
*/
diff --git a/src/repl/scala/tools/nsc/interpreter/Formatting.scala b/src/repl/scala/tools/nsc/interpreter/Formatting.scala
index 43e653edfd..844997429c 100644
--- a/src/repl/scala/tools/nsc/interpreter/Formatting.scala
+++ b/src/repl/scala/tools/nsc/interpreter/Formatting.scala
@@ -8,28 +8,25 @@ package interpreter
import util.stringFromWriter
-trait Formatting {
- def prompt: String
+class Formatting(indent: Int) {
- def spaces(code: String): String = {
+ private val indentation = " " * indent
+
+ private def indenting(code: String): Boolean = {
/** Heuristic to avoid indenting and thereby corrupting """-strings and XML literals. */
val tokens = List("\"\"\"", "</", "/>")
val noIndent = (code contains "\n") && (tokens exists code.contains)
- if (noIndent) ""
- else prompt drop 1 map (_ => ' ')
+ !noIndent
}
/** Indent some code by the width of the scala> prompt.
* This way, compiler error messages read better.
*/
- def indentCode(code: String) = {
- val indent = spaces(code)
- stringFromWriter(str =>
- for (line <- code.lines) {
- str print indent
- str print (line + "\n")
- str.flush()
- }
- )
- }
+ def indentCode(code: String) = stringFromWriter(str =>
+ for (line <- code.lines) {
+ if (indenting(code)) str print indentation
+ str println line
+ str.flush()
+ }
+ )
}
diff --git a/src/repl/scala/tools/nsc/interpreter/ILoop.scala b/src/repl/scala/tools/nsc/interpreter/ILoop.scala
index a3047ccc8e..525609171e 100644
--- a/src/repl/scala/tools/nsc/interpreter/ILoop.scala
+++ b/src/repl/scala/tools/nsc/interpreter/ILoop.scala
@@ -111,11 +111,10 @@ class ILoop(in0: Option[BufferedReader], protected val out: JPrintWriter)
}
class ILoopInterpreter extends IMain(settings, out) {
- outer =>
-
- override lazy val formatting = new Formatting {
- def prompt = ILoop.this.prompt
- }
+ // the expanded prompt but without color escapes and without leading newline, for purposes of indenting
+ override lazy val formatting: Formatting = new Formatting(
+ (replProps.promptString format Properties.versionNumberString).lines.toList.last.length
+ )
override protected def parentClassLoader =
settings.explicitParentLoader.getOrElse( classOf[ILoop].getClassLoader )
}
@@ -199,10 +198,8 @@ class ILoop(in0: Option[BufferedReader], protected val out: JPrintWriter)
echo("%d %s".format(index + offset, line))
}
- private val currentPrompt = Properties.shellPromptString
-
/** Prompt to print when awaiting input */
- def prompt = currentPrompt
+ def prompt = replProps.prompt
import LoopCommand.{ cmd, nullary }
@@ -412,14 +409,8 @@ class ILoop(in0: Option[BufferedReader], protected val out: JPrintWriter)
}
private def readOneLine() = {
- import scala.io.AnsiColor.{ MAGENTA, RESET }
out.flush()
- in readLine (
- if (replProps.colorOk)
- MAGENTA + prompt + RESET
- else
- prompt
- )
+ in readLine prompt
}
/** The main read-eval-print loop for the repl. It calls
@@ -770,8 +761,13 @@ class ILoop(in0: Option[BufferedReader], protected val out: JPrintWriter)
}
private object paste extends Pasted {
+ import scala.util.matching.Regex.quote
val ContinueString = " | "
- val PromptString = "scala> "
+ val PromptString = prompt.lines.toList.last
+ val anyPrompt = s"""\\s*(?:${quote(PromptString.trim)}|${quote(AltPromptString.trim)})\\s*""".r
+
+ def isPrompted(line: String) = matchesPrompt(line)
+ def isPromptOnly(line: String) = line match { case anyPrompt() => true ; case _ => false }
def interpret(line: String): Unit = {
echo(line.trim)
@@ -781,10 +777,17 @@ class ILoop(in0: Option[BufferedReader], protected val out: JPrintWriter)
def transcript(start: String) = {
echo("\n// Detected repl transcript paste: ctrl-D to finish.\n")
- apply(Iterator(start) ++ readWhile(_.trim != PromptString.trim))
+ apply(Iterator(start) ++ readWhile(!isPromptOnly(_)))
}
+
+ def unapply(line: String): Boolean = isPrompted(line)
+ }
+
+ private object invocation {
+ def unapply(line: String): Boolean = Completion.looksLikeInvocation(line)
}
- import paste.{ ContinueString, PromptString }
+
+ private val lineComment = """\s*//.*""".r // all comment
/** Interpret expressions starting with the first line.
* Read lines until a complete compilation unit is available
@@ -796,53 +799,42 @@ class ILoop(in0: Option[BufferedReader], protected val out: JPrintWriter)
// signal completion non-completion input has been received
in.completion.resetVerbosity()
- def reallyInterpret = {
- val reallyResult = intp.interpret(code)
- (reallyResult, reallyResult match {
- case IR.Error => None
- case IR.Success => Some(code)
- case IR.Incomplete =>
- if (in.interactive && code.endsWith("\n\n")) {
- echo("You typed two blank lines. Starting a new command.")
+ def reallyInterpret = intp.interpret(code) match {
+ case IR.Error => None
+ case IR.Success => Some(code)
+ case IR.Incomplete if in.interactive && code.endsWith("\n\n") =>
+ echo("You typed two blank lines. Starting a new command.")
+ None
+ case IR.Incomplete =>
+ in.readLine(paste.ContinueString) match {
+ case null =>
+ // we know compilation is going to fail since we're at EOF and the
+ // parser thinks the input is still incomplete, but since this is
+ // a file being read non-interactively we want to fail. So we send
+ // it straight to the compiler for the nice error message.
+ intp.compileString(code)
None
- }
- else in.readLine(ContinueString) match {
- case null =>
- // we know compilation is going to fail since we're at EOF and the
- // parser thinks the input is still incomplete, but since this is
- // a file being read non-interactively we want to fail. So we send
- // it straight to the compiler for the nice error message.
- intp.compileString(code)
- None
-
- case line => interpretStartingWith(code + "\n" + line)
- }
- })
+
+ case line => interpretStartingWith(code + "\n" + line)
+ }
}
- /** Here we place ourselves between the user and the interpreter and examine
- * the input they are ostensibly submitting. We intervene in several cases:
+ /* Here we place ourselves between the user and the interpreter and examine
+ * the input they are ostensibly submitting. We intervene in several cases:
*
- * 1) If the line starts with "scala> " it is assumed to be an interpreter paste.
- * 2) If the line starts with "." (but not ".." or "./") it is treated as an invocation
- * on the previous result.
- * 3) If the Completion object's execute returns Some(_), we inject that value
- * and avoid the interpreter, as it's likely not valid scala code.
+ * 1) If the line starts with "scala> " it is assumed to be an interpreter paste.
+ * 2) If the line starts with "." (but not ".." or "./") it is treated as an invocation
+ * on the previous result.
+ * 3) If the Completion object's execute returns Some(_), we inject that value
+ * and avoid the interpreter, as it's likely not valid scala code.
*/
- if (code == "") None
- else if (!paste.running && code.trim.startsWith(PromptString)) {
- paste.transcript(code)
- None
- }
- else if (Completion.looksLikeInvocation(code) && intp.mostRecentVar != "") {
- interpretStartingWith(intp.mostRecentVar + code)
+ code match {
+ case "" => None
+ case lineComment() => None // line comment, do nothing
+ case paste() if !paste.running => paste.transcript(code) ; None
+ case invocation() if intp.mostRecentVar != "" => interpretStartingWith(intp.mostRecentVar + code)
+ case _ => reallyInterpret
}
- else if (code.trim startsWith "//") {
- // line comment, do nothing
- None
- }
- else
- reallyInterpret._2
}
// runs :load `file` on any files passed via -i
diff --git a/src/repl/scala/tools/nsc/interpreter/IMain.scala b/src/repl/scala/tools/nsc/interpreter/IMain.scala
index e355d9f864..2550a5dc57 100644
--- a/src/repl/scala/tools/nsc/interpreter/IMain.scala
+++ b/src/repl/scala/tools/nsc/interpreter/IMain.scala
@@ -112,12 +112,13 @@ class IMain(@BeanProperty val factory: ScriptEngineFactory, initialSettings: Set
def this(factory: ScriptEngineFactory) = this(factory, new Settings())
def this() = this(new Settings())
- lazy val formatting: Formatting = new Formatting {
- val prompt = Properties.shellPromptString
- }
+ // the expanded prompt but without color escapes and without leading newline, for purposes of indenting
+ lazy val formatting: Formatting = new Formatting(
+ (replProps.promptString format Properties.versionNumberString).lines.toList.last.length
+ )
lazy val reporter: ReplReporter = new ReplReporter(this)
- import formatting._
+ import formatting.indentCode
import reporter.{ printMessage, printUntruncatedMessage }
// This exists mostly because using the reporter too early leads to deadlock.
@@ -468,7 +469,7 @@ class IMain(@BeanProperty val factory: ScriptEngineFactory, initialSettings: Set
}
private def requestFromLine(line: String, synthetic: Boolean): Either[IR.Result, Request] = {
- val content = indentCode(line)
+ val content = line //indentCode(line)
val trees = parse(content) match {
case parse.Incomplete => return Left(IR.Incomplete)
case parse.Error => return Left(IR.Error)
@@ -909,10 +910,10 @@ class IMain(@BeanProperty val factory: ScriptEngineFactory, initialSettings: Set
else List("def %s = %s".format("$line", tquoted(originalLine)), "def %s = Nil".format("$trees"))
}
def preamble = s"""
- |$preambleHeader
- |%s%s%s
- """.stripMargin.format(lineRep.readName, envLines.map(" " + _ + ";\n").mkString,
- importsPreamble, indentCode(toCompute))
+ |${preambleHeader format lineRep.readName}
+ |${envLines mkString (" ", ";\n ", ";\n")}
+ |$importsPreamble
+ |${indentCode(toCompute)}""".stripMargin
val generate = (m: MemberHandler) => m extraCodeToEvaluate Request.this
diff --git a/src/repl/scala/tools/nsc/interpreter/JavapClass.scala b/src/repl/scala/tools/nsc/interpreter/JavapClass.scala
index 1ccade2172..c240ab027a 100644
--- a/src/repl/scala/tools/nsc/interpreter/JavapClass.scala
+++ b/src/repl/scala/tools/nsc/interpreter/JavapClass.scala
@@ -747,15 +747,15 @@ object JavapClass {
// 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)
- //target.member flatMap (_ => labdaMethod(x, target)) getOrElse s"${target.name}#$$anonfun"
+ case x @ closure(_, "lambda", _, _) => lambdaMethod(x, target)
+ //target.member flatMap (_ => lambdaMethod(x, target)) getOrElse s"${target.name}#$$anonfun"
case x => Some(x)
}
rev
}
// given C$lambda$$g$n for member g and n in 1..N, find the C.accessor$x
// and the C.$anonfun$x it forwards to.
- def labdaMethod(lambda: String, target: Target): Option[String] = {
+ def lambdaMethod(lambda: String, target: Target): Option[String] = {
import scala.tools.asm.ClassReader
import scala.tools.asm.Opcodes.INVOKESTATIC
import scala.tools.asm.tree.{ ClassNode, MethodInsnNode }
diff --git a/src/repl/scala/tools/nsc/interpreter/Pasted.scala b/src/repl/scala/tools/nsc/interpreter/Pasted.scala
index f5db3d9e3a..5f388eb15b 100644
--- a/src/repl/scala/tools/nsc/interpreter/Pasted.scala
+++ b/src/repl/scala/tools/nsc/interpreter/Pasted.scala
@@ -16,17 +16,21 @@ package interpreter
* the same result.
*/
abstract class Pasted {
+ def interpret(line: String): Unit
def ContinueString: String
def PromptString: String
- def interpret(line: String): Unit
+ def AltPromptString: String = "scala> "
+
+ private val testBoth = PromptString != AltPromptString
+ private val spacey = " \t".toSet
- def matchesPrompt(line: String) = matchesString(line, PromptString)
+ def matchesPrompt(line: String) = matchesString(line, PromptString) || testBoth && matchesString(line, AltPromptString)
def matchesContinue(line: String) = matchesString(line, ContinueString)
def running = isRunning
private def matchesString(line: String, target: String): Boolean = (
(line startsWith target) ||
- (line.nonEmpty && " \t".toSet(line.head) && matchesString(line.tail, target))
+ (line.nonEmpty && spacey(line.head) && matchesString(line.tail, target))
)
private def stripString(line: String, target: String) = line indexOf target match {
case -1 => line
@@ -39,7 +43,9 @@ abstract class Pasted {
private class PasteAnalyzer(val lines: List[String]) {
val referenced = lines flatMap (resReference findAllIn _.trim.stripPrefix("res")) toSet
- val cmds = lines reduceLeft append split PromptString filterNot (_.trim == "") toList
+ val ActualPromptString = lines find matchesPrompt map (s =>
+ if (matchesString(s, PromptString)) PromptString else AltPromptString) getOrElse PromptString
+ val cmds = lines reduceLeft append split ActualPromptString filterNot (_.trim == "") toList
/** If it's a prompt or continuation line, strip the formatting bits and
* assemble the code. Otherwise ship it off to be analyzed for res references
@@ -67,10 +73,10 @@ abstract class Pasted {
*/
def fixResRefs(code: String, line: String) = line match {
case resCreation(resName) if referenced(resName) =>
- code.lastIndexOf(PromptString) match {
+ code.lastIndexOf(ActualPromptString) match {
case -1 => code
case idx =>
- val (str1, str2) = code splitAt (idx + PromptString.length)
+ val (str1, str2) = code splitAt (idx + ActualPromptString.length)
str2 match {
case resAssign(`resName`) => code
case _ => "%sval %s = { %s }".format(str1, resName, str2)
@@ -79,10 +85,10 @@ abstract class Pasted {
case _ => code
}
- def run() {
+ def run(): Unit = {
println("// Replaying %d commands from transcript.\n" format cmds.size)
cmds foreach { cmd =>
- print(PromptString)
+ print(ActualPromptString)
interpret(cmd)
}
}
diff --git a/src/repl/scala/tools/nsc/interpreter/ReplProps.scala b/src/repl/scala/tools/nsc/interpreter/ReplProps.scala
index 8c4faf7278..df65e9974d 100644
--- a/src/repl/scala/tools/nsc/interpreter/ReplProps.scala
+++ b/src/repl/scala/tools/nsc/interpreter/ReplProps.scala
@@ -6,12 +6,13 @@
package scala.tools.nsc
package interpreter
+import Properties.shellPromptString
import scala.sys._
import Prop._
class ReplProps {
private def bool(name: String) = BooleanProp.keyExists(name)
- private def int(name: String) = IntProp(name)
+ private def int(name: String) = Prop[Int](name)
// This property is used in TypeDebugging. Let's recycle it.
val colorOk = bool("scala.color")
@@ -21,6 +22,14 @@ class ReplProps {
val trace = bool("scala.repl.trace")
val power = bool("scala.repl.power")
+ // Handy system prop for shell prompt, or else pick it up from compiler.properties
+ val promptString = Prop[String]("scala.repl.prompt").option getOrElse (if (info) "%nscala %s> " else shellPromptString)
+ val prompt = {
+ import scala.io.AnsiColor.{ MAGENTA, RESET }
+ val p = promptString format Properties.versionNumberString
+ if (colorOk) s"$MAGENTA$p$RESET" else p
+ }
+
/** CSV of paged,across to enable pagination or `-x` style
* columns, "across" instead of down the column. Since
* pagination turns off columnar output, these flags are
diff --git a/src/scaladoc/scala/tools/nsc/doc/html/page/diagram/DotDiagramGenerator.scala b/src/scaladoc/scala/tools/nsc/doc/html/page/diagram/DotDiagramGenerator.scala
index b541cf721b..320a8e23b2 100644
--- a/src/scaladoc/scala/tools/nsc/doc/html/page/diagram/DotDiagramGenerator.scala
+++ b/src/scaladoc/scala/tools/nsc/doc/html/page/diagram/DotDiagramGenerator.scala
@@ -383,7 +383,7 @@ class DotDiagramGenerator(settings: doc.Settings, dotRunner: DotRunner) extends
if (dotId.count(_ == '|') == 1) {
val Array(klass, id) = dotId.toString.split("\\|")
/* Sometimes dot "forgets" to add the image -- that's very annoying, but it seems pretty random, and simple
- * tests like excute 20K times and diff the output don't trigger the bug -- so it's up to us to place the image
+ * tests like execute 20K times and diff the output don't trigger the bug -- so it's up to us to place the image
* back in the node */
val kind = getKind(klass)
if (kind != "")
diff --git a/src/scaladoc/scala/tools/nsc/doc/model/ModelFactory.scala b/src/scaladoc/scala/tools/nsc/doc/model/ModelFactory.scala
index 03d71f15a3..3cbcbc433e 100644
--- a/src/scaladoc/scala/tools/nsc/doc/model/ModelFactory.scala
+++ b/src/scaladoc/scala/tools/nsc/doc/model/ModelFactory.scala
@@ -478,7 +478,7 @@ class ModelFactory(val global: Global, val settings: doc.Settings) {
override lazy val comment = {
def nonRootTemplate(sym: Symbol): Option[DocTemplateImpl] =
if (sym eq RootPackage) None else findTemplateMaybe(sym)
- /* Variable precendence order for implicitly added members: Take the variable defifinitions from ...
+ /* Variable precendence order for implicitly added members: Take the variable definitions from ...
* 1. the target of the implicit conversion
* 2. the definition template (owner)
* 3. the current template
diff --git a/test/benchmarks/src/scala/collection/parallel/benchmarks/misc/Coder.scala b/test/benchmarks/src/scala/collection/parallel/benchmarks/misc/Coder.scala
index 9cc1f4a0f6..04e37085b8 100644
--- a/test/benchmarks/src/scala/collection/parallel/benchmarks/misc/Coder.scala
+++ b/test/benchmarks/src/scala/collection/parallel/benchmarks/misc/Coder.scala
@@ -16,7 +16,7 @@ class SeqCoder(words: List[String]) {
'2' -> "ABC", '3' -> "DEF", '4' -> "GHI", '5' -> "JKL",
'6' -> "MNO", '7' -> "PQRS", '8' -> "TUV", '9' -> "WXYZ")
- /** Invert the mnemnonics map to give a map from chars 'A' ... 'Z' to '2' ... '9' */
+ /** Invert the mnemonics map to give a map from chars 'A' ... 'Z' to '2' ... '9' */
private val charCode: Map[Char, Char] =
for ((digit, letters) <- m; letter <- letters) yield letter -> digit
@@ -63,7 +63,7 @@ class ParCoder(words: List[String]) {
'2' -> "ABC", '3' -> "DEF", '4' -> "GHI", '5' -> "JKL",
'6' -> "MNO", '7' -> "PQRS", '8' -> "TUV", '9' -> "WXYZ")
- /** Invert the mnemnonics map to give a map from chars 'A' ... 'Z' to '2' ... '9' */
+ /** Invert the mnemonics map to give a map from chars 'A' ... 'Z' to '2' ... '9' */
private val charCode: Map[Char, Char] =
for ((digit, letters) <- m; letter <- letters) yield letter -> digit
diff --git a/test/benchmarks/src/scala/collection/parallel/benchmarks/parallel_array/SequentialOps.scala b/test/benchmarks/src/scala/collection/parallel/benchmarks/parallel_array/SequentialOps.scala
index ba32036002..9300851b5f 100644
--- a/test/benchmarks/src/scala/collection/parallel/benchmarks/parallel_array/SequentialOps.scala
+++ b/test/benchmarks/src/scala/collection/parallel/benchmarks/parallel_array/SequentialOps.scala
@@ -425,7 +425,7 @@ trait SequentialOps[T] {
}
def sequentialDiff(sq: Seq[T], sz: Int) = {
- val occmap = occurences(sq)
+ val occmap = occurrences(sq)
val b = new collection.mutable.ArrayBuffer[T]
var i = 0
@@ -442,7 +442,7 @@ trait SequentialOps[T] {
}
def sequentialIntersect(sq: Seq[T], sz: Int) = {
- val occmap = occurences(sq)
+ val occmap = occurrences(sq)
val b = new collection.mutable.ArrayBuffer[T]
var i = 0
@@ -461,7 +461,7 @@ trait SequentialOps[T] {
res
}
- private def occurences(sq: Seq[T]) = {
+ private def occurrences(sq: Seq[T]) = {
val occmap = new collection.mutable.HashMap[T, Int] { override def default(k: T) = 0 }
for (elem <- sq.iterator) occmap(elem) += 1
occmap
diff --git a/test/disabled/coder/Coder.scala b/test/disabled/coder/Coder.scala
index 4e29c2a6ee..62b99e0cf0 100644
--- a/test/disabled/coder/Coder.scala
+++ b/test/disabled/coder/Coder.scala
@@ -10,7 +10,7 @@ class SeqCoder(words: List[String]) {
'2' -> "ABC", '3' -> "DEF", '4' -> "GHI", '5' -> "JKL",
'6' -> "MNO", '7' -> "PQRS", '8' -> "TUV", '9' -> "WXYZ")
- /** Invert the mnemnonics map to give a map from chars 'A' ... 'Z' to '2' ... '9' */
+ /** Invert the mnemonics map to give a map from chars 'A' ... 'Z' to '2' ... '9' */
private val charCode: Map[Char, Char] =
for ((digit, letters) <- m; letter <- letters) yield letter -> digit
@@ -65,7 +65,7 @@ class ParCoder(words: List[String]) {
'2' -> "ABC", '3' -> "DEF", '4' -> "GHI", '5' -> "JKL",
'6' -> "MNO", '7' -> "PQRS", '8' -> "TUV", '9' -> "WXYZ")
- /** Invert the mnemnonics map to give a map from chars 'A' ... 'Z' to '2' ... '9' */
+ /** Invert the mnemonics map to give a map from chars 'A' ... 'Z' to '2' ... '9' */
private val charCode: Map[Char, Char] =
for ((digit, letters) <- m; letter <- letters) yield letter -> digit
diff --git a/test/disabled/run/coder2/Coder2.scala b/test/disabled/run/coder2/Coder2.scala
index 43b2e9bcb8..c1ec70b842 100644
--- a/test/disabled/run/coder2/Coder2.scala
+++ b/test/disabled/run/coder2/Coder2.scala
@@ -10,7 +10,7 @@ class SeqCoder(words: List[String]) {
'2' -> "ABC", '3' -> "DEF", '4' -> "GHI", '5' -> "JKL",
'6' -> "MNO", '7' -> "PQRS", '8' -> "TUV", '9' -> "WXYZ")
- /** Invert the mnemnonics map to give a map from chars 'A' ... 'Z' to '2' ... '9' */
+ /** Invert the mnemonics map to give a map from chars 'A' ... 'Z' to '2' ... '9' */
private val charCode: Map[Char, Char] =
for ((digit, letters) <- m; letter <- letters) yield letter -> digit
diff --git a/test/files/jvm/interpreter.check b/test/files/jvm/interpreter.check
index d03edb638c..9e875235c7 100644
--- a/test/files/jvm/interpreter.check
+++ b/test/files/jvm/interpreter.check
@@ -32,7 +32,7 @@ scala> val four: anotherint = 4
four: anotherint = 4
scala> val bogus: anotherint = "hello"
-<console>:8: error: type mismatch;
+<console>:11: error: type mismatch;
found : String("hello")
required: anotherint
(which expands to) Int
@@ -280,13 +280,13 @@ scala> // both of the following should abort immediately:
scala> def x => y => z
<console>:1: error: '=' expected but '=>' found.
- def x => y => z
- ^
+def x => y => z
+ ^
scala> [1,2,3]
<console>:1: error: illegal start of definition
- [1,2,3]
- ^
+[1,2,3]
+^
scala>
@@ -355,7 +355,7 @@ defined class Term
scala> def f(e: Exp) = e match { // non-exhaustive warning here
case _:Fact => 3
}
-<console>:18: warning: match may not be exhaustive.
+<console>:21: warning: match may not be exhaustive.
It would fail on the following inputs: Exp(), Term()
def f(e: Exp) = e match { // non-exhaustive warning here
^
@@ -365,6 +365,6 @@ scala> :quit
plusOne: (x: Int)Int
res0: Int = 6
res0: String = after reset
-<console>:8: error: not found: value plusOne
- plusOne(5) // should be undefined now
- ^
+<console>:11: error: not found: value plusOne
+ plusOne(5) // should be undefined now
+ ^
diff --git a/test/files/jvm/javaReflection/Test.scala b/test/files/jvm/javaReflection/Test.scala
index ae5a36eeb2..199399fec8 100644
--- a/test/files/jvm/javaReflection/Test.scala
+++ b/test/files/jvm/javaReflection/Test.scala
@@ -31,7 +31,7 @@ getSimpleName / getCanonicalName / isAnonymousClass / isLocalClass / isSynthetic
These should be avoided, they yield unexpected results:
- isAnonymousClass is always false. Scala-defined classes are never anonymous for Java
- reflection. Java reflection insepects the class name to decide whether a class is
+ reflection. Java reflection inspects the class name to decide whether a class is
anonymous, based on the name spec referenced above.
Also, the implementation of "isAnonymousClass" calls "getSimpleName", which may throw.
diff --git a/test/files/jvm/protectedacc.scala b/test/files/jvm/protectedacc.scala
index 89e70b90d8..43d218fa89 100644
--- a/test/files/jvm/protectedacc.scala
+++ b/test/files/jvm/protectedacc.scala
@@ -74,7 +74,7 @@ package p {
package b {
import a._;
- /** Test interraction with Scala inherited methods and currying. */
+ /** Test interaction with Scala inherited methods and currying. */
class B extends A {
class C {
def m = {
diff --git a/test/files/jvm/unreachable/Test.scala b/test/files/jvm/unreachable/Test.scala
index 3f520eb106..4c0fcb2ae8 100644
--- a/test/files/jvm/unreachable/Test.scala
+++ b/test/files/jvm/unreachable/Test.scala
@@ -6,7 +6,7 @@ import scala.collection.JavaConverters._
object Test extends BytecodeTest {
def show: Unit = {
val classNode = loadClassNode("Foo_1")
- // Foo_1 is full of unreachable code which if not elimintated
+ // Foo_1 is full of unreachable code which if not eliminated
// will result in NOPs as can be confirmed by adding -Ydisable-unreachable-prevention
// to Foo_1.flags
for (methodNode <- classNode.methods.asScala) {
diff --git a/test/files/neg/macro-invalidshape.check b/test/files/neg/macro-invalidshape.check
index aa694df6d6..5093b87598 100644
--- a/test/files/neg/macro-invalidshape.check
+++ b/test/files/neg/macro-invalidshape.check
@@ -8,8 +8,9 @@ macro [<static object>].<method name>[[<type args>]] or
macro [<macro bundle>].<method name>[[<type args>]]
def foo2(x: Any) = macro Impls.foo(null)(null)
^
-Macros_Test_2.scala:4: error: missing arguments for method foo in object Impls;
-follow this method with `_' if you want to treat it as a partially applied function
+Macros_Test_2.scala:4: error: missing argument list for method foo in object Impls
+Unapplied methods are only converted to functions when a function type is expected.
+You can make this conversion explicit by writing `foo _` or `foo(_)(_)` instead of `foo`.
def foo3(x: Any) = macro {2; Impls.foo}
^
Macros_Test_2.scala:7: error: macro implementation reference has wrong shape. required:
diff --git a/test/files/neg/missing-arg-list.check b/test/files/neg/missing-arg-list.check
new file mode 100644
index 0000000000..5a011c36f2
--- /dev/null
+++ b/test/files/neg/missing-arg-list.check
@@ -0,0 +1,21 @@
+missing-arg-list.scala:9: error: missing argument list for method id in trait T
+Unapplied methods are only converted to functions when a function type is expected.
+You can make this conversion explicit by writing `id _` or `id(_)` instead of `id`.
+ val w = id
+ ^
+missing-arg-list.scala:10: error: missing argument list for method f in trait T
+Unapplied methods are only converted to functions when a function type is expected.
+You can make this conversion explicit by writing `f _` or `f(_)(_)` instead of `f`.
+ val x = f
+ ^
+missing-arg-list.scala:11: error: missing argument list for method g in trait T
+Unapplied methods are only converted to functions when a function type is expected.
+You can make this conversion explicit by writing `g _` or `g(_,_,_)` instead of `g`.
+ val y = g
+ ^
+missing-arg-list.scala:12: error: missing argument list for method h in trait T
+Unapplied methods are only converted to functions when a function type is expected.
+You can make this conversion explicit by writing `h _` or `h(_,_,_)(_)` instead of `h`.
+ val z = h
+ ^
+four errors found
diff --git a/test/files/neg/missing-arg-list.scala b/test/files/neg/missing-arg-list.scala
new file mode 100644
index 0000000000..c422dd32fe
--- /dev/null
+++ b/test/files/neg/missing-arg-list.scala
@@ -0,0 +1,13 @@
+
+trait T {
+
+ def id(i: Int) = i
+ def f(i: Int)(j: Int) = i+j
+ def g(i: Int, j: Int, k: Int) = i+j+k
+ def h(i: Int, j: Int, k: Int)(implicit s: String) = s*(i+j+k)
+
+ val w = id
+ val x = f
+ val y = g
+ val z = h
+}
diff --git a/test/files/neg/t3995.scala b/test/files/neg/t3995.scala
index b03617ac86..c79f2a5865 100644
--- a/test/files/neg/t3995.scala
+++ b/test/files/neg/t3995.scala
@@ -27,6 +27,6 @@ object Test {
// can be accessed with unambiguous stable prefixes, the implicits infos
// which are members of these companion objects."
//
- // The skolem is stable, but it doen't seem much good to us
+ // The skolem is stable, but it does not seem much good to us
(new Lift).apply("")
}
diff --git a/test/files/neg/t5120.scala b/test/files/neg/t5120.scala
index f28b2cfb4f..0df67bc09b 100644
--- a/test/files/neg/t5120.scala
+++ b/test/files/neg/t5120.scala
@@ -12,7 +12,7 @@ object Test {
str.x1.length
}
}
-// another way demonstrating the same underlying problem, as reported by roman kalukiewicz
+// another way demonstrating the same underlying problem, as reported by Roman Kalukiewicz
class Holder[_T](_f1 : _T, _f2 : _T) {
type T = _T
diff --git a/test/files/neg/t8237-default.scala b/test/files/neg/t8237-default.scala
index f695aa523f..a4370046bd 100644
--- a/test/files/neg/t8237-default.scala
+++ b/test/files/neg/t8237-default.scala
@@ -1,4 +1,4 @@
-// This test case was extracte from `names-defaults-neg.scala`
+// This test case was extracted from `names-defaults-neg.scala`
// It pinpoints an improvement an error message that results from
// a type inference failure
object Test extends App {
diff --git a/test/files/neg/t836.scala b/test/files/neg/t836.scala
index 3633b816c6..4b86d04013 100644
--- a/test/files/neg/t836.scala
+++ b/test/files/neg/t836.scala
@@ -12,5 +12,5 @@ abstract class A {
class B extends A {
type MyObj = ObjImpl
val myString: S = "hello"
- val realString: String = myString // error: type missmatch
+ val realString: String = myString // error: type mismatch
}
diff --git a/test/files/neg/t8431.scala b/test/files/neg/t8431.scala
index 032a1f394d..bc45bb62ae 100644
--- a/test/files/neg/t8431.scala
+++ b/test/files/neg/t8431.scala
@@ -48,7 +48,7 @@ class TestExplicit {
{val c1 = convert2(s); c1.combined}
}
-// These ones work before and after; infering G=Null doesn't need to contribute an undetermined type param.
+// These ones work before and after; inferring G=Null doesn't need to contribute an undetermined type param.
class Test3 {
import C.{cbf, convert1, convert2}
val s: Invariant[Null] = ???
diff --git a/test/files/neg/t8463.scala b/test/files/neg/t8463.scala
index 7c954fd834..1337f8bece 100644
--- a/test/files/neg/t8463.scala
+++ b/test/files/neg/t8463.scala
@@ -7,7 +7,7 @@ object Test {
/* If SI-8230 is fixed, and `viewExists` is changed to no longer leak
ambiguity errors, you might expect the check file for this test to
- change as folloes:
+ change as follows:
@@ -1,18 +1,10 @@
-t8463.scala:5: error: no type parameters for method apply: (activity:
diff --git a/test/files/neg/warn-unused-privates.scala b/test/files/neg/warn-unused-privates.scala
index 2faa07e759..2eda280d40 100644
--- a/test/files/neg/warn-unused-privates.scala
+++ b/test/files/neg/warn-unused-privates.scala
@@ -21,7 +21,7 @@ class B3(msg0: String) extends A("msg")
/*** Early defs warnings disabled primarily due to SI-6595.
* The test case is here to assure we aren't issuing false positives;
- * the ones labeled "warn" don't warn.
+ * the ones labelled "warn" don't warn.
***/
class Boppy extends {
private val hmm: String = "abc" // no warn, used in early defs
diff --git a/test/files/pos/SI-4012-b.scala b/test/files/pos/SI-4012-b.scala
index 6bc8592766..f6d84963e4 100644
--- a/test/files/pos/SI-4012-b.scala
+++ b/test/files/pos/SI-4012-b.scala
@@ -6,7 +6,7 @@ object Sub extends Super[Int] {
// it is expected that super[Super].superb crashes, since
// specialization does parent class rewiring, and the super
// of Sub becomes Super$mcII$sp and not Super. But I consider
- // this normal behavior -- if you want, I can modify duplicatiors
+ // this normal behavior -- if you want, I can modify duplicators
// to make this work, but I consider it's best to keep this
// let the user know Super is not the superclass anymore.
// super[Super].superb - Vlad
diff --git a/test/files/pos/delambdafy-patterns.scala b/test/files/pos/delambdafy-patterns.scala
index 95d498629b..ca9eaa67e3 100644
--- a/test/files/pos/delambdafy-patterns.scala
+++ b/test/files/pos/delambdafy-patterns.scala
@@ -2,7 +2,7 @@ class DelambdafyPatterns {
def bar: Unit = ()
def wildcardPatternInTryCatch: Unit => Unit = (x: Unit) =>
// patterns in try..catch are preserved so we need to be
- // careful when it comes to free variable detction
+ // careful when it comes to free variable detection
// in particular a is _not_ free variable, also the
// `_` identifier has no symbol attached to it
try bar catch {
diff --git a/test/files/pos/t7200b.scala b/test/files/pos/t7200b.scala
index 9d579c6ef9..59be898fd0 100644
--- a/test/files/pos/t7200b.scala
+++ b/test/files/pos/t7200b.scala
@@ -10,7 +10,7 @@ trait Foo {
object O extends Foo {
def coflatMap[A <: T](f: A) = {
val f2 = coflatMap(f) // inferred in 2.9.2 / 2.10.0 as [Nothing]
- f2.t // so this does't type check.
+ f2.t // so this fails to type check.
f2
}
}
diff --git a/test/files/pos/t8947/Macro_1.scala b/test/files/pos/t8947/Macro_1.scala
index 4a5de3decb..ace389f339 100644
--- a/test/files/pos/t8947/Macro_1.scala
+++ b/test/files/pos/t8947/Macro_1.scala
@@ -35,7 +35,7 @@ object X {
// symtab.EmptyTree.setAttachments(symtab.NoPosition)
// }
//
- // To make this visible to the macro implementaiton, it will need to be compiled in an earlier stage,
+ // To make this visible to the macro implementation, it will need to be compiled in an earlier stage,
// e.g a separate SBT sub-project.
}
diff --git a/test/files/run/ReplacementMatching.scala b/test/files/run/ReplacementMatching.scala
index 05040d98a3..81034aa510 100644
--- a/test/files/run/ReplacementMatching.scala
+++ b/test/files/run/ReplacementMatching.scala
@@ -32,12 +32,12 @@ object Test {
def groupsMatching {
val Date = """(\d+)/(\d+)/(\d+)""".r
- for (Regex.Groups(a, b, c) <- Date findFirstMatchIn "1/1/2001 marks the start of the millenium. 31/12/2000 doesn't.") {
+ for (Regex.Groups(a, b, c) <- Date findFirstMatchIn "1/1/2001 marks the start of the millennium. 31/12/2000 doesn't.") {
assert(a == "1")
assert(b == "1")
assert(c == "2001")
}
- for (Regex.Groups(a, b, c) <- (Date findAllIn "1/1/2001 marks the start of the millenium. 31/12/2000 doesn't.").matchData) {
+ for (Regex.Groups(a, b, c) <- (Date findAllIn "1/1/2001 marks the start of the millennium. 31/12/2000 doesn't.").matchData) {
assert(a == "1" || a == "31")
assert(b == "1" || b == "12")
assert(c == "2001" || c == "2000")
diff --git a/test/files/run/blame_eye_triple_eee-double.check b/test/files/run/blame_eye_triple_eee-double.check
index 5e46d91a8f..53eac99ecd 100644
--- a/test/files/run/blame_eye_triple_eee-double.check
+++ b/test/files/run/blame_eye_triple_eee-double.check
@@ -6,4 +6,4 @@ if (x != x) is good
if (NaN != x) is good
x matching was good
NaN matching was good
-loop with NaN was goood
+loop with NaN was good
diff --git a/test/files/run/blame_eye_triple_eee-double.scala b/test/files/run/blame_eye_triple_eee-double.scala
index 1640aead40..4dcbfe7a7a 100644
--- a/test/files/run/blame_eye_triple_eee-double.scala
+++ b/test/files/run/blame_eye_triple_eee-double.scala
@@ -56,6 +56,6 @@ object Test extends App {
else z = NaN
i += 1
}
- if (z.isNaN && i == 10) println("loop with NaN was goood")
+ if (z.isNaN && i == 10) println("loop with NaN was good")
else println("loop with NaN was broken")
}
diff --git a/test/files/run/blame_eye_triple_eee-float.check b/test/files/run/blame_eye_triple_eee-float.check
index 5e46d91a8f..53eac99ecd 100644
--- a/test/files/run/blame_eye_triple_eee-float.check
+++ b/test/files/run/blame_eye_triple_eee-float.check
@@ -6,4 +6,4 @@ if (x != x) is good
if (NaN != x) is good
x matching was good
NaN matching was good
-loop with NaN was goood
+loop with NaN was good
diff --git a/test/files/run/blame_eye_triple_eee-float.scala b/test/files/run/blame_eye_triple_eee-float.scala
index 4deb9f3d60..bcc6b195d5 100644
--- a/test/files/run/blame_eye_triple_eee-float.scala
+++ b/test/files/run/blame_eye_triple_eee-float.scala
@@ -56,6 +56,6 @@ object Test extends App {
else z = NaN
i += 1
}
- if (z.isNaN && i == 10) println("loop with NaN was goood")
+ if (z.isNaN && i == 10) println("loop with NaN was good")
else println("loop with NaN was broken")
}
diff --git a/test/files/run/constrained-types.check b/test/files/run/constrained-types.check
index 89a08d5ccb..6dbf8088c9 100644
--- a/test/files/run/constrained-types.check
+++ b/test/files/run/constrained-types.check
@@ -135,16 +135,16 @@ y: String = hello
scala>
scala> val x = 3 : Int @Annot(e+f+g+h) // should have a graceful error message
-<console>:8: error: not found: value e
+<console>:11: error: not found: value e
val x = 3 : Int @Annot(e+f+g+h) // should have a graceful error message
^
-<console>:8: error: not found: value f
+<console>:11: error: not found: value f
val x = 3 : Int @Annot(e+f+g+h) // should have a graceful error message
^
-<console>:8: error: not found: value g
+<console>:11: error: not found: value g
val x = 3 : Int @Annot(e+f+g+h) // should have a graceful error message
^
-<console>:8: error: not found: value h
+<console>:11: error: not found: value h
val x = 3 : Int @Annot(e+f+g+h) // should have a graceful error message
^
diff --git a/test/files/run/deeps.scala b/test/files/run/deeps.scala
index 6049cc6024..1546112ed5 100644
--- a/test/files/run/deeps.scala
+++ b/test/files/run/deeps.scala
@@ -3,7 +3,7 @@
//############################################################################
//############################################################################
-// need to revisit array equqality
+// need to revisit array equality
object Test {
def testEquals1 {
diff --git a/test/files/run/finally.check b/test/files/run/finally.check
index 901a797426..b0f2293d11 100644
--- a/test/files/run/finally.check
+++ b/test/files/run/finally.check
@@ -29,7 +29,7 @@ body
in finally
java.lang.Exception
----------------------------------------
-Running nestedFinalies
+Running nestedFinallyBlocks
in finally 1
in finally 2
----------------------------------------
diff --git a/test/files/run/finally.scala b/test/files/run/finally.scala
index 2c01edaaef..467c9e5868 100644
--- a/test/files/run/finally.scala
+++ b/test/files/run/finally.scala
@@ -93,8 +93,8 @@ object Test extends App {
}
}
- // nested finallies with return value
- def nestedFinalies: Int =
+ // nested finally blocks with return value
+ def nestedFinallyBlocks: Int =
try {
try {
return 10
@@ -123,5 +123,5 @@ object Test extends App {
test(throwBody, "throwBody")
test(retFinally, "retFinally")
test(throwFinally, "throwFinally")
- test(nestedFinalies, "nestedFinalies")
+ test(nestedFinallyBlocks, "nestedFinallyBlocks")
}
diff --git a/test/files/run/iq.scala b/test/files/run/iq.scala
index 1eb1d40e37..0ccf67a2e9 100644
--- a/test/files/run/iq.scala
+++ b/test/files/run/iq.scala
@@ -69,7 +69,7 @@ object iq {
val (_, q7) = q6.dequeue
//val q8 = q7 + 10 + 11 //deprecated
val q8 = q7.enqueue(10).enqueue(11)
- /* Test dequeu
+ /* Test dequeue
* Expected: q8: Queue(2,3,4,5,6,7,8,9,10,11)
*/
Console.println("q8: " + q8)
diff --git a/test/files/run/kind-repl-command.check b/test/files/run/kind-repl-command.check
index 586b2710e1..1853213555 100644
--- a/test/files/run/kind-repl-command.check
+++ b/test/files/run/kind-repl-command.check
@@ -21,8 +21,8 @@ scala> :k new { def empty = false }
AnyRef{def empty: Boolean}'s kind is A
scala> :k Nonexisting
-<console>:8: error: not found: value Nonexisting
- Nonexisting
- ^
+<console>:11: error: not found: value Nonexisting
+ Nonexisting
+ ^
scala> :quit
diff --git a/test/files/run/names-defaults.scala b/test/files/run/names-defaults.scala
index b7ed490cbc..7fb4a04546 100644
--- a/test/files/run/names-defaults.scala
+++ b/test/files/run/names-defaults.scala
@@ -86,7 +86,7 @@ object Test extends App {
def f(a: Object) = "first"
val f: String => String = a => "second"
}
- println(t5.f(new Sub1())) // firsst
+ println(t5.f(new Sub1())) // first
println(t5.f("dfklj")) // second
object t6 {
@@ -239,7 +239,7 @@ object Test extends App {
// result type of default getters: parameter type, except if this one mentions any type
// parameter, in which case the result type is inferred. examples:
- // result type of default getter is "String => String". if it were infered, the compiler
+ // result type of default getter is "String => String". if it were inferred, the compiler
// would put "Nothing => Nothing", which is useless
def transform(s: String, f: String => String = identity _) = f(s)
println(transform("my text"))
diff --git a/test/files/run/nullable-lazyvals.scala b/test/files/run/nullable-lazyvals.scala
index c201e74e75..be5d82f3a7 100644
--- a/test/files/run/nullable-lazyvals.scala
+++ b/test/files/run/nullable-lazyvals.scala
@@ -24,7 +24,7 @@ object Test extends App {
// test that try-finally does not generated a liftedTry
// helper. This would already fail the first part of the test,
- // but this check will help diganose it (if the single access to a
+ // but this check will help diagnose it (if the single access to a
// private field does not happen directly in the lazy val, it won't
// be nulled).
for (f <- foo.getClass.getDeclaredMethods) {
diff --git a/test/files/run/reify-repl-fail-gracefully.check b/test/files/run/reify-repl-fail-gracefully.check
index c9e69744d6..eac4d25869 100644
--- a/test/files/run/reify-repl-fail-gracefully.check
+++ b/test/files/run/reify-repl-fail-gracefully.check
@@ -10,8 +10,8 @@ import scala.reflect.runtime.universe._
scala>
scala> reify
-<console>:12: error: too few argument lists for macro invocation
- reify
- ^
+<console>:15: error: too few argument lists for macro invocation
+ reify
+ ^
scala> :quit
diff --git a/test/files/run/reify_newimpl_22.check b/test/files/run/reify_newimpl_22.check
index 952f384a1c..24334df92c 100644
--- a/test/files/run/reify_newimpl_22.check
+++ b/test/files/run/reify_newimpl_22.check
@@ -17,9 +17,9 @@ scala> {
}
println(code.eval)
}
-<console>:15: free term: Ident(TermName("x")) defined by res0 in <console>:14:21
- val code = reify {
- ^
+<console>:18: free term: Ident(TermName("x")) defined by res0 in <console>:17:14
+ val code = reify {
+ ^
2
scala> :quit
diff --git a/test/files/run/reify_newimpl_23.check b/test/files/run/reify_newimpl_23.check
index b7e9bfdfbc..f8379958db 100644
--- a/test/files/run/reify_newimpl_23.check
+++ b/test/files/run/reify_newimpl_23.check
@@ -16,7 +16,7 @@ scala> def foo[T]{
}
println(code.eval)
}
-<console>:13: free type: Ident(TypeName("T")) defined by foo in <console>:12:16
+<console>:16: free type: Ident(TypeName("T")) defined by foo in <console>:15:16
val code = reify {
^
foo: [T]=> Unit
diff --git a/test/files/run/reify_newimpl_25.check b/test/files/run/reify_newimpl_25.check
index 4f36ba10ee..f9a5d7b578 100644
--- a/test/files/run/reify_newimpl_25.check
+++ b/test/files/run/reify_newimpl_25.check
@@ -7,9 +7,9 @@ scala> {
val tt = implicitly[TypeTag[x.type]]
println(tt)
}
-<console>:11: free term: Ident(TermName("x")) defined by res0 in <console>:10:21
- val tt = implicitly[TypeTag[x.type]]
- ^
+<console>:14: free term: Ident(TermName("x")) defined by res0 in <console>:13:14
+ val tt = implicitly[TypeTag[x.type]]
+ ^
TypeTag[x.type]
scala> :quit
diff --git a/test/files/run/reify_newimpl_26.check b/test/files/run/reify_newimpl_26.check
index 681b862795..bd77d3d707 100644
--- a/test/files/run/reify_newimpl_26.check
+++ b/test/files/run/reify_newimpl_26.check
@@ -6,7 +6,7 @@ scala> def foo[T]{
val tt = implicitly[WeakTypeTag[List[T]]]
println(tt)
}
-<console>:9: free type: Ident(TypeName("T")) defined by foo in <console>:7:16
+<console>:12: free type: Ident(TypeName("T")) defined by foo in <console>:10:16
val tt = implicitly[WeakTypeTag[List[T]]]
^
foo: [T]=> Unit
diff --git a/test/files/run/repl-bare-expr.check b/test/files/run/repl-bare-expr.check
index 07cf23412f..38ad7e818d 100644
--- a/test/files/run/repl-bare-expr.check
+++ b/test/files/run/repl-bare-expr.check
@@ -2,33 +2,33 @@ Type in expressions to have them evaluated.
Type :help for more information.
scala> 2 ; 3
-<console>:7: warning: a pure expression does nothing in statement position; you may be omitting necessary parentheses
- 2 ;;
- ^
+<console>:10: warning: a pure expression does nothing in statement position; you may be omitting necessary parentheses
+ 2 ;;
+ ^
res0: Int = 3
scala> { 2 ; 3 }
-<console>:8: warning: a pure expression does nothing in statement position; you may be omitting necessary parentheses
- { 2 ; 3 }
- ^
+<console>:11: warning: a pure expression does nothing in statement position; you may be omitting necessary parentheses
+ { 2 ; 3 }
+ ^
res1: Int = 3
scala> 5 ; 10 ; case object Cow ; 20 ; class Moo { override def toString = "Moooooo" } ; 30 ; def bippy = {
1 +
2 +
3 } ; bippy+88+11
-<console>:7: warning: a pure expression does nothing in statement position; you may be omitting necessary parentheses
- 5 ; 10 ; case object Cow ; 20 ; class Moo { override def toString = "Moooooo" } ; 30 ; def bippy = {
- ^
-<console>:7: warning: a pure expression does nothing in statement position; you may be omitting necessary parentheses
- 5 ; 10 ; case object Cow ; 20 ; class Moo { override def toString = "Moooooo" } ; 30 ; def bippy = {
- ^
-<console>:7: warning: a pure expression does nothing in statement position; you may be omitting necessary parentheses
- 5 ; 10 ; case object Cow ; 20 ; class Moo { override def toString = "Moooooo" } ; 30 ; def bippy = {
- ^
-<console>:7: warning: a pure expression does nothing in statement position; you may be omitting necessary parentheses
- 5 ; 10 ; case object Cow ; 20 ; class Moo { override def toString = "Moooooo" } ; 30 ; def bippy = {
- ^
+<console>:10: warning: a pure expression does nothing in statement position; you may be omitting necessary parentheses
+ 5 ; 10 ; case object Cow ; 20 ; class Moo { override def toString = "Moooooo" } ; 30 ; def bippy = {
+ ^
+<console>:10: warning: a pure expression does nothing in statement position; you may be omitting necessary parentheses
+ 5 ; 10 ; case object Cow ; 20 ; class Moo { override def toString = "Moooooo" } ; 30 ; def bippy = {
+ ^
+<console>:10: warning: a pure expression does nothing in statement position; you may be omitting necessary parentheses
+ 5 ; 10 ; case object Cow ; 20 ; class Moo { override def toString = "Moooooo" } ; 30 ; def bippy = {
+ ^
+<console>:10: warning: a pure expression does nothing in statement position; you may be omitting necessary parentheses
+ 5 ; 10 ; case object Cow ; 20 ; class Moo { override def toString = "Moooooo" } ; 30 ; def bippy = {
+ ^
defined object Cow
defined class Moo
bippy: Int
diff --git a/test/files/run/repl-colon-type.check b/test/files/run/repl-colon-type.check
index 9898027c1d..fa33af3beb 100644
--- a/test/files/run/repl-colon-type.check
+++ b/test/files/run/repl-colon-type.check
@@ -3,8 +3,8 @@ Type :help for more information.
scala> :type List[1, 2, 3]
<console>:1: error: identifier expected but integer literal found.
- List[1, 2, 3]
- ^
+List[1, 2, 3]
+ ^
scala> :type List(1, 2, 3)
List[Int]
diff --git a/test/files/run/repl-parens.check b/test/files/run/repl-parens.check
index 74d15ff93c..756a063b68 100644
--- a/test/files/run/repl-parens.check
+++ b/test/files/run/repl-parens.check
@@ -20,12 +20,12 @@ scala> ( (2 + 2 ) )
res5: Int = 4
scala> 5 ; ( (2 + 2 ) ) ; ((5))
-<console>:7: warning: a pure expression does nothing in statement position; you may be omitting necessary parentheses
- 5 ; ( (2 + 2 ) ) ;;
- ^
-<console>:7: warning: a pure expression does nothing in statement position; you may be omitting necessary parentheses
- 5 ; ( (2 + 2 ) ) ;;
- ^
+<console>:10: warning: a pure expression does nothing in statement position; you may be omitting necessary parentheses
+ 5 ; ( (2 + 2 ) ) ;;
+ ^
+<console>:10: warning: a pure expression does nothing in statement position; you may be omitting necessary parentheses
+ 5 ; ( (2 + 2 ) ) ;;
+ ^
res6: Int = 5
scala> (((2 + 2)), ((2 + 2)))
@@ -40,18 +40,18 @@ res9: String = 4423
scala>
scala> 55 ; ((2 + 2)) ; (1, 2, 3)
-<console>:7: warning: a pure expression does nothing in statement position; you may be omitting necessary parentheses
- 55 ; ((2 + 2)) ;;
- ^
-<console>:7: warning: a pure expression does nothing in statement position; you may be omitting necessary parentheses
- 55 ; ((2 + 2)) ;;
- ^
+<console>:10: warning: a pure expression does nothing in statement position; you may be omitting necessary parentheses
+ 55 ; ((2 + 2)) ;;
+ ^
+<console>:10: warning: a pure expression does nothing in statement position; you may be omitting necessary parentheses
+ 55 ; ((2 + 2)) ;;
+ ^
res10: (Int, Int, Int) = (1,2,3)
scala> 55 ; (x: Int) => x + 1 ; () => ((5))
-<console>:7: warning: a pure expression does nothing in statement position; you may be omitting necessary parentheses
- 55 ; (x: Int) => x + 1 ;;
- ^
+<console>:10: warning: a pure expression does nothing in statement position; you may be omitting necessary parentheses
+ 55 ; (x: Int) => x + 1 ;;
+ ^
res11: () => Int = <function0>
scala>
@@ -60,9 +60,9 @@ scala> () => 5
res12: () => Int = <function0>
scala> 55 ; () => 5
-<console>:7: warning: a pure expression does nothing in statement position; you may be omitting necessary parentheses
- 55 ;;
- ^
+<console>:10: warning: a pure expression does nothing in statement position; you may be omitting necessary parentheses
+ 55 ;;
+ ^
res13: () => Int = <function0>
scala> () => { class X ; new X }
diff --git a/test/files/run/repl-paste-2.check b/test/files/run/repl-paste-2.check
index 6ea8e2f419..bc80615107 100644
--- a/test/files/run/repl-paste-2.check
+++ b/test/files/run/repl-paste-2.check
@@ -44,7 +44,7 @@ scala> res5 + res6
res1: Int = 690
scala> val x = dingus
-<console>:7: error: not found: value dingus
+<console>:10: error: not found: value dingus
val x = dingus
^
diff --git a/test/files/run/repl-reset.check b/test/files/run/repl-reset.check
index cd7893bbc3..a2d88fd445 100644
--- a/test/files/run/repl-reset.check
+++ b/test/files/run/repl-reset.check
@@ -30,23 +30,23 @@ Forgetting all expression results and named terms: $intp, BippyBungus, x1, x2, x
Forgetting defined types: BippyBungus
scala> x1 + x2 + x3
-<console>:8: error: not found: value x1
- x1 + x2 + x3
- ^
-<console>:8: error: not found: value x2
- x1 + x2 + x3
- ^
-<console>:8: error: not found: value x3
- x1 + x2 + x3
- ^
+<console>:11: error: not found: value x1
+ x1 + x2 + x3
+ ^
+<console>:11: error: not found: value x2
+ x1 + x2 + x3
+ ^
+<console>:11: error: not found: value x3
+ x1 + x2 + x3
+ ^
scala> val x1 = 4
x1: Int = 4
scala> new BippyBungus
-<console>:8: error: not found: type BippyBungus
- new BippyBungus
- ^
+<console>:11: error: not found: type BippyBungus
+ new BippyBungus
+ ^
scala> class BippyBungus() { def f = 5 }
defined class BippyBungus
diff --git a/test/files/run/repl-trim-stack-trace.scala b/test/files/run/repl-trim-stack-trace.scala
index a53ce3b3e4..b8c1668691 100644
--- a/test/files/run/repl-trim-stack-trace.scala
+++ b/test/files/run/repl-trim-stack-trace.scala
@@ -13,7 +13,7 @@ f: Nothing
scala> f
java.lang.Exception: Uh-oh
- at .f(<console>:7)
+ at .f(<console>:10)
... 69 elided
scala> def f = throw new Exception("")
@@ -21,7 +21,7 @@ f: Nothing
scala> f
java.lang.Exception:
- at .f(<console>:7)
+ at .f(<console>:10)
... 69 elided
scala> def f = throw new Exception
@@ -29,7 +29,7 @@ f: Nothing
scala> f
java.lang.Exception
- at .f(<console>:7)
+ at .f(<console>:10)
... 69 elided
scala> :quit"""
diff --git a/test/files/run/sbt-icode-interface.scala b/test/files/run/sbt-icode-interface.scala
new file mode 100644
index 0000000000..84d38cc65a
--- /dev/null
+++ b/test/files/run/sbt-icode-interface.scala
@@ -0,0 +1,42 @@
+import scala.tools.partest._
+import scala.tools.nsc._
+
+object Test extends DirectTest {
+
+ def code = """
+ class C { class D }
+ object O
+ """.trim
+
+ def show() {
+ for (b <- List("GenASM", "GenBCode")) {
+ val global = newCompiler("-usejavacp", s"-Ybackend:$b")
+ import global._
+ val r = new Run
+ r.compileSources(newSourceFile(code) :: Nil)
+
+ val results = collection.mutable.Buffer[(Boolean, String)]()
+
+ // Nailing down defacto compiler API from SBT's usage
+ // https://github.com/sbt/sbt/blob/adb41611cf73260938274915d8462d924df200c8/compile/interface/src/main/scala/xsbt/Analyzer.scala#L29-L41
+ def isTopLevelModule(sym: Symbol) = sym.isTopLevel && sym.isModule
+ for (unit <- currentRun.units if !unit.isJava) {
+ val sourceFile = unit.source.file.file
+ for (iclass <- unit.icode) {
+ val sym = iclass.symbol
+ def addGenerated(separatorRequired: Boolean) {
+ results += (separatorRequired -> sym.fullName)
+ }
+ if (sym.isModuleClass && !sym.isImplClass) {
+ if (isTopLevelModule(sym) && sym.companionClass == NoSymbol)
+ addGenerated(false)
+ addGenerated(true)
+ } else
+ addGenerated(false)
+ }
+ }
+ val expected = List((false, "C"), (true, "O"), (false, "C$D"))
+ assert(results.toList == expected, b + ": " + results.toList)
+ }
+ }
+}
diff --git a/test/files/run/t0631.scala b/test/files/run/t0631.scala
index c401ed31cb..8d672574ec 100644
--- a/test/files/run/t0631.scala
+++ b/test/files/run/t0631.scala
@@ -11,6 +11,6 @@ object Test extends App {
case class Bar(x: Foo)
val b = new Bar(new Foo)
- // this should not call Foo.equals, but simply compare object identiy of b
+ // this should not call Foo.equals, but simply compare object identity of b
println(b == b)
}
diff --git a/test/files/run/t2526.scala b/test/files/run/t2526.scala
index 53f3059135..9f3c48ec61 100644
--- a/test/files/run/t2526.scala
+++ b/test/files/run/t2526.scala
@@ -38,7 +38,7 @@ object Test {
/*
* Checks foreach of `actual` goes over all the elements in `expected`
- * We duplicate the method above because there is no common inteface between Traversable and
+ * We duplicate the method above because there is no common interface between Traversable and
* Iterator and we want to avoid converting between collections to ensure that we test what
* we mean to test.
*/
diff --git a/test/files/run/t4542.check b/test/files/run/t4542.check
index f7716dc2f0..f7aad3deb2 100644
--- a/test/files/run/t4542.check
+++ b/test/files/run/t4542.check
@@ -7,7 +7,7 @@ scala> @deprecated("foooo", "ReplTest version 1.0-FINAL") class Foo() {
defined class Foo
scala> val f = new Foo
-<console>:8: warning: class Foo is deprecated: foooo
+<console>:11: warning: class Foo is deprecated: foooo
val f = new Foo
^
f: Foo = Bippy
diff --git a/test/files/run/t4594-repl-settings.scala b/test/files/run/t4594-repl-settings.scala
index db5dc19866..1b883983cf 100644
--- a/test/files/run/t4594-repl-settings.scala
+++ b/test/files/run/t4594-repl-settings.scala
@@ -17,7 +17,7 @@ object Test extends SessionTest {
|scala> :settings -deprecation
|
|scala> def b = depp
- |<console>:8: warning: method depp is deprecated: Please don't do that.
+ |<console>:11: warning: method depp is deprecated: Please don't do that.
| def b = depp
| ^
|b: String
diff --git a/test/files/run/t5655.check b/test/files/run/t5655.check
index 4bbc54b641..e8375c3e90 100644
--- a/test/files/run/t5655.check
+++ b/test/files/run/t5655.check
@@ -8,19 +8,19 @@ scala> import x._
import x._
scala> x
-<console>:12: error: reference to x is ambiguous;
+<console>:15: error: reference to x is ambiguous;
it is imported twice in the same scope by
import x._
and import x
- x
- ^
+ x
+ ^
scala> x
-<console>:12: error: reference to x is ambiguous;
+<console>:15: error: reference to x is ambiguous;
it is imported twice in the same scope by
import x._
and import x
- x
- ^
+ x
+ ^
scala> :quit
diff --git a/test/files/run/t6240-universe-code-gen.scala b/test/files/run/t6240-universe-code-gen.scala
index 9f7061ee1b..60e1f76b54 100644
--- a/test/files/run/t6240-universe-code-gen.scala
+++ b/test/files/run/t6240-universe-code-gen.scala
@@ -13,8 +13,8 @@ object Test extends App {
(sym.isMethod && sym.asMethod.isLazy)
|| sym.isModule
)
- val forcables = tp.members.sorted.filter(isLazyAccessorOrObject)
- forcables.map {
+ val forceables = tp.members.sorted.filter(isLazyAccessorOrObject)
+ forceables.map {
sym =>
val path = s"$prefix.${sym.name}"
" " + (
diff --git a/test/files/run/t6440b.scala b/test/files/run/t6440b.scala
index 974aca2844..7ab9529ccb 100644
--- a/test/files/run/t6440b.scala
+++ b/test/files/run/t6440b.scala
@@ -35,7 +35,7 @@ object Test extends StoreReporterDirectTest {
def app2 = """
package pack3
object Test {
- pack2.V.u.t // we have to fail if T.class is misisng
+ pack2.V.u.t // we have to fail if T.class is missing
}
"""
diff --git a/test/files/run/t7319.check b/test/files/run/t7319.check
index e35cfc90c0..885136b432 100644
--- a/test/files/run/t7319.check
+++ b/test/files/run/t7319.check
@@ -17,25 +17,25 @@ warning: there was one feature warning; re-run with -feature for details
convert: [F[X <: F[X]]](builder: F[_ <: F[_]])Int
scala> convert(Some[Int](0))
-<console>:12: error: no type parameters for method convert: (builder: F[_ <: F[_]])Int exist so that it can be applied to arguments (Some[Int])
+<console>:15: error: no type parameters for method convert: (builder: F[_ <: F[_]])Int exist so that it can be applied to arguments (Some[Int])
--- because ---
argument expression's type is not compatible with formal parameter type;
found : Some[Int]
required: ?F[_$1] forSome { type _$1 <: ?F[_$2] forSome { type _$2 } }
- convert(Some[Int](0))
- ^
-<console>:12: error: type mismatch;
+ convert(Some[Int](0))
+ ^
+<console>:15: error: type mismatch;
found : Some[Int]
required: F[_ <: F[_]]
- convert(Some[Int](0))
- ^
+ convert(Some[Int](0))
+ ^
scala> Range(1,2).toArray: Seq[_]
-<console>:11: error: polymorphic expression cannot be instantiated to expected type;
+<console>:14: error: polymorphic expression cannot be instantiated to expected type;
found : [B >: Int]Array[B]
required: Seq[_]
- Range(1,2).toArray: Seq[_]
- ^
+ Range(1,2).toArray: Seq[_]
+ ^
scala> 0
res2: Int = 0
diff --git a/test/files/run/t7582.check b/test/files/run/t7582.check
index 2a11210000..0cfbf08886 100644
--- a/test/files/run/t7582.check
+++ b/test/files/run/t7582.check
@@ -1,6 +1 @@
-#partest !-Ybackend:GenBCode
-warning: there was one inliner warning; re-run with -Yinline-warnings for details
-#partest -Ybackend:GenBCode
-warning: there was one inliner warning; re-run with -Yopt-warnings for details
-#partest
2
diff --git a/test/files/run/t7582/InlineHolder.scala b/test/files/run/t7582/InlineHolder.scala
index a18b9effaa..3cbf233ce1 100644
--- a/test/files/run/t7582/InlineHolder.scala
+++ b/test/files/run/t7582/InlineHolder.scala
@@ -1,3 +1,6 @@
+/*
+ * filter: inliner warning; re-run with
+ */
package p1 {
object InlineHolder {
@inline def inlinable = p1.PackageProtectedJava.protectedMethod() + 1
diff --git a/test/files/run/t7582b.check b/test/files/run/t7582b.check
index 2a11210000..0cfbf08886 100644
--- a/test/files/run/t7582b.check
+++ b/test/files/run/t7582b.check
@@ -1,6 +1 @@
-#partest !-Ybackend:GenBCode
-warning: there was one inliner warning; re-run with -Yinline-warnings for details
-#partest -Ybackend:GenBCode
-warning: there was one inliner warning; re-run with -Yopt-warnings for details
-#partest
2
diff --git a/test/files/run/t7582b/InlineHolder.scala b/test/files/run/t7582b/InlineHolder.scala
index a18b9effaa..3cbf233ce1 100644
--- a/test/files/run/t7582b/InlineHolder.scala
+++ b/test/files/run/t7582b/InlineHolder.scala
@@ -1,3 +1,6 @@
+/*
+ * filter: inliner warning; re-run with
+ */
package p1 {
object InlineHolder {
@inline def inlinable = p1.PackageProtectedJava.protectedMethod() + 1
diff --git a/test/files/run/t7747-repl.check b/test/files/run/t7747-repl.check
index 5f436ba6b1..98e3d3b821 100644
--- a/test/files/run/t7747-repl.check
+++ b/test/files/run/t7747-repl.check
@@ -17,33 +17,33 @@ scala> val z = x * y
z: Int = 156
scala> 2 ; 3
-<console>:7: warning: a pure expression does nothing in statement position; you may be omitting necessary parentheses
- 2 ;;
- ^
+<console>:10: warning: a pure expression does nothing in statement position; you may be omitting necessary parentheses
+ 2 ;;
+ ^
res0: Int = 3
scala> { 2 ; 3 }
-<console>:8: warning: a pure expression does nothing in statement position; you may be omitting necessary parentheses
- { 2 ; 3 }
- ^
+<console>:11: warning: a pure expression does nothing in statement position; you may be omitting necessary parentheses
+ { 2 ; 3 }
+ ^
res1: Int = 3
scala> 5 ; 10 ; case object Cow ; 20 ; class Moo { override def toString = "Moooooo" } ; 30 ; def bippy = {
1 +
2 +
3 } ; bippy+88+11
-<console>:7: warning: a pure expression does nothing in statement position; you may be omitting necessary parentheses
- 5 ; 10 ; case object Cow ; 20 ; class Moo { override def toString = "Moooooo" } ; 30 ; def bippy = {
- ^
-<console>:7: warning: a pure expression does nothing in statement position; you may be omitting necessary parentheses
- 5 ; 10 ; case object Cow ; 20 ; class Moo { override def toString = "Moooooo" } ; 30 ; def bippy = {
- ^
-<console>:7: warning: a pure expression does nothing in statement position; you may be omitting necessary parentheses
- 5 ; 10 ; case object Cow ; 20 ; class Moo { override def toString = "Moooooo" } ; 30 ; def bippy = {
- ^
-<console>:7: warning: a pure expression does nothing in statement position; you may be omitting necessary parentheses
- 5 ; 10 ; case object Cow ; 20 ; class Moo { override def toString = "Moooooo" } ; 30 ; def bippy = {
- ^
+<console>:10: warning: a pure expression does nothing in statement position; you may be omitting necessary parentheses
+ 5 ; 10 ; case object Cow ; 20 ; class Moo { override def toString = "Moooooo" } ; 30 ; def bippy = {
+ ^
+<console>:10: warning: a pure expression does nothing in statement position; you may be omitting necessary parentheses
+ 5 ; 10 ; case object Cow ; 20 ; class Moo { override def toString = "Moooooo" } ; 30 ; def bippy = {
+ ^
+<console>:10: warning: a pure expression does nothing in statement position; you may be omitting necessary parentheses
+ 5 ; 10 ; case object Cow ; 20 ; class Moo { override def toString = "Moooooo" } ; 30 ; def bippy = {
+ ^
+<console>:10: warning: a pure expression does nothing in statement position; you may be omitting necessary parentheses
+ 5 ; 10 ; case object Cow ; 20 ; class Moo { override def toString = "Moooooo" } ; 30 ; def bippy = {
+ ^
defined object Cow
defined class Moo
bippy: Int
@@ -83,12 +83,12 @@ scala> ( (2 + 2 ) )
res10: Int = 4
scala> 5 ; ( (2 + 2 ) ) ; ((5))
-<console>:7: warning: a pure expression does nothing in statement position; you may be omitting necessary parentheses
- 5 ; ( (2 + 2 ) ) ;;
- ^
-<console>:7: warning: a pure expression does nothing in statement position; you may be omitting necessary parentheses
- 5 ; ( (2 + 2 ) ) ;;
- ^
+<console>:10: warning: a pure expression does nothing in statement position; you may be omitting necessary parentheses
+ 5 ; ( (2 + 2 ) ) ;;
+ ^
+<console>:10: warning: a pure expression does nothing in statement position; you may be omitting necessary parentheses
+ 5 ; ( (2 + 2 ) ) ;;
+ ^
res11: Int = 5
scala> (((2 + 2)), ((2 + 2)))
@@ -103,18 +103,18 @@ res14: String = 4423
scala>
scala> 55 ; ((2 + 2)) ; (1, 2, 3)
-<console>:7: warning: a pure expression does nothing in statement position; you may be omitting necessary parentheses
- 55 ; ((2 + 2)) ;;
- ^
-<console>:7: warning: a pure expression does nothing in statement position; you may be omitting necessary parentheses
- 55 ; ((2 + 2)) ;;
- ^
+<console>:10: warning: a pure expression does nothing in statement position; you may be omitting necessary parentheses
+ 55 ; ((2 + 2)) ;;
+ ^
+<console>:10: warning: a pure expression does nothing in statement position; you may be omitting necessary parentheses
+ 55 ; ((2 + 2)) ;;
+ ^
res15: (Int, Int, Int) = (1,2,3)
scala> 55 ; (x: Int) => x + 1 ; () => ((5))
-<console>:9: warning: a pure expression does nothing in statement position; you may be omitting necessary parentheses
- 55 ; (x: Int) => x + 1 ;;
- ^
+<console>:12: warning: a pure expression does nothing in statement position; you may be omitting necessary parentheses
+ 55 ; (x: Int) => x + 1 ;;
+ ^
res16: () => Int = <function0>
scala>
@@ -123,9 +123,9 @@ scala> () => 5
res17: () => Int = <function0>
scala> 55 ; () => 5
-<console>:7: warning: a pure expression does nothing in statement position; you may be omitting necessary parentheses
- 55 ;;
- ^
+<console>:10: warning: a pure expression does nothing in statement position; you may be omitting necessary parentheses
+ 55 ;;
+ ^
res18: () => Int = <function0>
scala> () => { class X ; new X }
@@ -211,23 +211,23 @@ Forgetting all expression results and named terms: $intp, BippyBungus, Bovine, C
Forgetting defined types: BippyBungus, Moo, Ruminant
scala> x1 + x2 + x3
-<console>:8: error: not found: value x1
- x1 + x2 + x3
- ^
-<console>:8: error: not found: value x2
- x1 + x2 + x3
- ^
-<console>:8: error: not found: value x3
- x1 + x2 + x3
- ^
+<console>:11: error: not found: value x1
+ x1 + x2 + x3
+ ^
+<console>:11: error: not found: value x2
+ x1 + x2 + x3
+ ^
+<console>:11: error: not found: value x3
+ x1 + x2 + x3
+ ^
scala> val x1 = 4
x1: Int = 4
scala> new BippyBungus
-<console>:8: error: not found: type BippyBungus
- new BippyBungus
- ^
+<console>:11: error: not found: type BippyBungus
+ new BippyBungus
+ ^
scala> class BippyBungus() { def f = 5 }
defined class BippyBungus
diff --git a/test/files/run/t7817-tree-gen.scala b/test/files/run/t7817-tree-gen.scala
index a8317fda6e..094c0d6289 100644
--- a/test/files/run/t7817-tree-gen.scala
+++ b/test/files/run/t7817-tree-gen.scala
@@ -1,6 +1,6 @@
import scala.tools.partest._
-// Testing that `mkAttributedRef` doesn't incude the package object test.`package`,
+// Testing that `mkAttributedRef` doesn't include the package object test.`package`,
// under joint and separate compilation.
package testSep { class C { object O } }
diff --git a/test/files/run/t8601-closure-elim.scala b/test/files/run/t8601-closure-elim.scala
index 2c5b03af77..ebeb16e0c7 100644
--- a/test/files/run/t8601-closure-elim.scala
+++ b/test/files/run/t8601-closure-elim.scala
@@ -11,7 +11,7 @@ object Test extends BytecodeTest {
val classNode = loadClassNode("Foo")
val methodNode = getMethod(classNode, "b")
val ops = methodNode.instructions.iterator.asScala.map(_.getOpcode).toList
- assert(!ops.contains(asm.Opcodes.NEW), ops)// should be allocation free if the closure is eliminiated
+ assert(!ops.contains(asm.Opcodes.NEW), ops)// should be allocation free if the closure is eliminated
}
test("b")
}
diff --git a/test/files/run/t8708_b/Test_2.scala b/test/files/run/t8708_b/Test_2.scala
index c978490609..fae3c677ec 100644
--- a/test/files/run/t8708_b/Test_2.scala
+++ b/test/files/run/t8708_b/Test_2.scala
@@ -13,7 +13,7 @@ object Test extends DirectTest {
val c = g.rootMirror.getRequiredClass("p.C")
println(c.info.decls)
val t = c.info.member(g.newTypeName("T"))
- // this test ensrues that the <local child> dummy class symbol is not entered in the
+ // this test ensures that the <local child> dummy class symbol is not entered in the
// scope of trait T during unpickling.
println(t.info.decls)
})
diff --git a/test/files/run/t9170.scala b/test/files/run/t9170.scala
index 25a0e84581..67a58d6803 100644
--- a/test/files/run/t9170.scala
+++ b/test/files/run/t9170.scala
@@ -10,17 +10,17 @@ object Test extends SessionTest {
Type :help for more information.
scala> object Y { def f[A](a: => A) = 1 ; def f[A](a: => Either[Exception, A]) = 2 }
-<console>:7: error: double definition:
-def f[A](a: => A): Int at line 7 and
-def f[A](a: => Either[Exception,A]): Int at line 7
+<console>:10: error: double definition:
+def f[A](a: => A): Int at line 10 and
+def f[A](a: => Either[Exception,A]): Int at line 10
have same type after erasure: (a: Function0)Int
object Y { def f[A](a: => A) = 1 ; def f[A](a: => Either[Exception, A]) = 2 }
^
scala> object Y { def f[A](a: => A) = 1 ; def f[A](a: => Either[Exception, A]) = 2 }
-<console>:7: error: double definition:
-def f[A](a: => A): Int at line 7 and
-def f[A](a: => Either[Exception,A]): Int at line 7
+<console>:10: error: double definition:
+def f[A](a: => A): Int at line 10 and
+def f[A](a: => Either[Exception,A]): Int at line 10
have same type after erasure: (a: Function0)Int
object Y { def f[A](a: => A) = 1 ; def f[A](a: => Either[Exception, A]) = 2 }
^
@@ -29,9 +29,9 @@ scala> object Y {
| def f[A](a: => A) = 1
| def f[A](a: => Either[Exception, A]) = 2
| }
-<console>:9: error: double definition:
-def f[A](a: => A): Int at line 8 and
-def f[A](a: => Either[Exception,A]): Int at line 9
+<console>:12: error: double definition:
+def f[A](a: => A): Int at line 11 and
+def f[A](a: => Either[Exception,A]): Int at line 12
have same type after erasure: (a: Function0)Int
def f[A](a: => Either[Exception, A]) = 2
^
@@ -46,9 +46,9 @@ object Y {
// Exiting paste mode, now interpreting.
-<console>:9: error: double definition:
-def f[A](a: => A): Int at line 8 and
-def f[A](a: => Either[Exception,A]): Int at line 9
+<console>:12: error: double definition:
+def f[A](a: => A): Int at line 11 and
+def f[A](a: => Either[Exception,A]): Int at line 12
have same type after erasure: (a: Function0)Int
def f[A](a: => Either[Exception, A]) = 2
^
diff --git a/test/files/run/t9206.scala b/test/files/run/t9206.scala
new file mode 100644
index 0000000000..2942d0f73e
--- /dev/null
+++ b/test/files/run/t9206.scala
@@ -0,0 +1,39 @@
+
+import scala.tools.partest.SessionTest
+
+object Test extends SessionTest {
+ //override def prompt = "XXX> "
+//Welcome to Scala version 2.11.6 (Java HotSpot(TM) 64-Bit Server VM, Java 1.8.0_40).
+ def session =
+ s"""|Type in expressions to have them evaluated.
+ |Type :help for more information.
+ |
+ |scala> val i: Int = "foo"
+ |<console>:10: error: type mismatch;
+ | found : String("foo")
+ | required: Int
+ | val i: Int = "foo"
+ | ^
+ |
+ |scala> { val j = 42 ; val i: Int = "foo" + j }
+ |<console>:11: error: type mismatch;
+ | found : String
+ | required: Int
+ | { val j = 42 ; val i: Int = "foo" + j }
+ | ^
+ |
+ |scala> :quit"""
+ /*
+ |XXX> XXX> def f = 42
+ |
+ |// Detected repl transcript paste: ctrl-D to finish.
+ |
+ |// Replaying 1 commands from transcript.
+ |
+ |XXX> def f = 42
+ |f: Int
+ |
+ |XXX> :quit"""
+ */
+
+}
diff --git a/test/files/run/t9359.check b/test/files/run/t9359.check
new file mode 100644
index 0000000000..8dcfe4f60a
--- /dev/null
+++ b/test/files/run/t9359.check
@@ -0,0 +1,18 @@
+ // access flags 0x4009
+ public static enum INNERCLASS A_1$A1N A_1 A1N
+
+ // access flags 0x4409
+ public static abstract enum INNERCLASS A_1$A1N_ABSTRACT A_1 A1N_ABSTRACT
+
+ // access flags 0x4019
+ public final static enum INNERCLASS A_1$A1N_FINAL A_1 A1N_FINAL
+
+ // access flags 0x4009
+ public static enum INNERCLASS B_2$A1N B_2 A1N
+
+ // access flags 0x4409
+ public static abstract enum INNERCLASS B_2$A1N_ABSTRACT B_2 A1N_ABSTRACT
+
+ // access flags 0x4019
+ public final static enum INNERCLASS B_2$A1N_FINAL B_2 A1N_FINAL
+
diff --git a/test/files/run/t9359/A_1.java b/test/files/run/t9359/A_1.java
new file mode 100644
index 0000000000..3ac82ed55f
--- /dev/null
+++ b/test/files/run/t9359/A_1.java
@@ -0,0 +1,19 @@
+public class A_1 {
+ // nested final
+ public static enum A1N_FINAL {
+ A1N_FINAL_VAL
+ }
+
+ // nested, non-final
+ public enum A1N {
+ A1N_VAL { } // value has a body, so a class extending A1N is generated
+ }
+
+ // nested, non-final, abstract
+ public enum A1N_ABSTRACT {
+ A1N_ABSTRACT_VAL {
+ void foo() { return; }
+ };
+ abstract void foo(); // abstract member makes the enum class abstract
+ }
+}
diff --git a/test/files/run/t9359/B_2.java b/test/files/run/t9359/B_2.java
new file mode 100644
index 0000000000..d824facda9
--- /dev/null
+++ b/test/files/run/t9359/B_2.java
@@ -0,0 +1,19 @@
+public class B_2 {
+ // nested final
+ public enum A1N_FINAL {
+ A1N_FINAL_VAL
+ }
+
+ // nested, non-final
+ public enum A1N {
+ A1N_VAL { } // value has a body, so a class extending A1N is generated
+ }
+
+ // nested, non-final, abstract
+ public enum A1N_ABSTRACT {
+ A1N_ABSTRACT_VAL {
+ void foo() { return; }
+ };
+ abstract void foo(); // abstract member makes the enum class abstract
+ }
+}
diff --git a/test/files/run/t9359/Test_2.scala b/test/files/run/t9359/Test_2.scala
new file mode 100644
index 0000000000..869c51b619
--- /dev/null
+++ b/test/files/run/t9359/Test_2.scala
@@ -0,0 +1,28 @@
+import scala.tools.partest.BytecodeTest
+import scala.tools.asm
+import asm.tree.{ClassNode, InnerClassNode}
+import asm.{Opcodes => Flags}
+import scala.collection.JavaConverters._
+
+class C {
+ def f1: A_1.A1N_FINAL = A_1.A1N_FINAL.A1N_FINAL_VAL
+ def f2: A_1.A1N = A_1.A1N.A1N_VAL
+ def f3: A_1.A1N_ABSTRACT = A_1.A1N_ABSTRACT.A1N_ABSTRACT_VAL
+
+ def f4: B_2.A1N_FINAL = B_2.A1N_FINAL.A1N_FINAL_VAL
+ def f5: B_2.A1N = B_2.A1N.A1N_VAL
+ def f6: B_2.A1N_ABSTRACT = B_2.A1N_ABSTRACT.A1N_ABSTRACT_VAL
+}
+
+object Test extends BytecodeTest {
+ def tost(n: InnerClassNode) = {
+ val t = new asm.util.Textifier
+ t.visitInnerClass(n.name, n.outerName, n.innerName, n.access)
+ t.getText.get(0);
+ }
+ def show(): Unit = {
+ for (n <- loadClassNode("C").innerClasses.asScala.toList.sortBy(_.name)) {
+ println(tost(n))
+ }
+ }
+}
diff --git a/test/files/run/xMigration.check b/test/files/run/xMigration.check
index 378f7bb6c3..304132a848 100644
--- a/test/files/run/xMigration.check
+++ b/test/files/run/xMigration.check
@@ -12,10 +12,10 @@ res1: Iterable[String] = MapLike(eis)
scala> :setting -Xmigration:any
scala> Map(1 -> "eis").values // warn
-<console>:8: warning: method values in trait MapLike has changed semantics in version 2.8.0:
+<console>:11: warning: method values in trait MapLike has changed semantics in version 2.8.0:
`values` returns `Iterable[B]` rather than `Iterator[B]`.
- Map(1 -> "eis").values // warn
- ^
+ Map(1 -> "eis").values // warn
+ ^
res2: Iterable[String] = MapLike(eis)
scala> :setting -Xmigration:2.8
@@ -26,10 +26,10 @@ res3: Iterable[String] = MapLike(eis)
scala> :setting -Xmigration:2.7
scala> Map(1 -> "eis").values // warn
-<console>:8: warning: method values in trait MapLike has changed semantics in version 2.8.0:
+<console>:11: warning: method values in trait MapLike has changed semantics in version 2.8.0:
`values` returns `Iterable[B]` rather than `Iterator[B]`.
- Map(1 -> "eis").values // warn
- ^
+ Map(1 -> "eis").values // warn
+ ^
res4: Iterable[String] = MapLike(eis)
scala> :setting -Xmigration:2.11
@@ -40,10 +40,10 @@ res5: Iterable[String] = MapLike(eis)
scala> :setting -Xmigration // same as :any
scala> Map(1 -> "eis").values // warn
-<console>:8: warning: method values in trait MapLike has changed semantics in version 2.8.0:
+<console>:11: warning: method values in trait MapLike has changed semantics in version 2.8.0:
`values` returns `Iterable[B]` rather than `Iterator[B]`.
- Map(1 -> "eis").values // warn
- ^
+ Map(1 -> "eis").values // warn
+ ^
res6: Iterable[String] = MapLike(eis)
scala> :quit
diff --git a/test/files/scalacheck/quasiquotes/RuntimeErrorProps.scala b/test/files/scalacheck/quasiquotes/RuntimeErrorProps.scala
index a3b6137f68..40fb42d63c 100644
--- a/test/files/scalacheck/quasiquotes/RuntimeErrorProps.scala
+++ b/test/files/scalacheck/quasiquotes/RuntimeErrorProps.scala
@@ -68,7 +68,7 @@ object RuntimeErrorProps extends QuasiquoteProperties("errors") {
q"for(..$enums) 0"
}
- property("for inlalid enum") = testFails {
+ property("for invalid enum") = testFails {
val enums = q"foo" :: Nil
q"for(..$enums) 0"
}
diff --git a/test/files/specialized/constant_lambda.scala b/test/files/specialized/constant_lambda.scala
index bb9a97403e..7c5358ce10 100644
--- a/test/files/specialized/constant_lambda.scala
+++ b/test/files/specialized/constant_lambda.scala
@@ -1,4 +1,4 @@
-// during development of late delmabdafying there was a problem where
+// during development of late delambdafying there was a problem where
// specialization would undo some of the work done in uncurry if the body of the
// lambda had a constant type. That would result in a compiler crash as
// when the delambdafy phase got a tree shape it didn't understand
diff --git a/test/junit/scala/tools/nsc/backend/jvm/CodeGenTools.scala b/test/junit/scala/tools/nsc/backend/jvm/CodeGenTools.scala
index d0ffd06b01..ee9580c1c3 100644
--- a/test/junit/scala/tools/nsc/backend/jvm/CodeGenTools.scala
+++ b/test/junit/scala/tools/nsc/backend/jvm/CodeGenTools.scala
@@ -6,7 +6,7 @@ import scala.collection.mutable.ListBuffer
import scala.reflect.internal.util.BatchSourceFile
import scala.reflect.io.VirtualDirectory
import scala.tools.asm.Opcodes
-import scala.tools.asm.tree.{ClassNode, MethodNode}
+import scala.tools.asm.tree.{AbstractInsnNode, ClassNode, MethodNode}
import scala.tools.cmd.CommandLineParser
import scala.tools.nsc.io.AbstractFile
import scala.tools.nsc.reporters.StoreReporter
@@ -15,6 +15,7 @@ import scala.tools.nsc.{Settings, Global}
import scala.tools.partest.ASMConverters
import scala.collection.JavaConverters._
import scala.tools.testing.TempDir
+import AsmUtils._
object CodeGenTools {
import ASMConverters._
@@ -151,6 +152,17 @@ object CodeGenTools {
def getSingleMethod(classNode: ClassNode, name: String): Method =
convertMethod(classNode.methods.asScala.toList.find(_.name == name).get)
+ /**
+ * Instructions that match `query` when textified.
+ * If `query` starts with a `+`, the next instruction is returned.
+ */
+ def findInstr(method: MethodNode, query: String): List[AbstractInsnNode] = {
+ val useNext = query(0) == '+'
+ val instrPart = if (useNext) query.drop(1) else query
+ val insns = method.instructions.iterator.asScala.find(i => textify(i) contains instrPart).toList
+ if (useNext) insns.map(_.getNext) else insns
+ }
+
def assertHandlerLabelPostions(h: ExceptionHandler, instructions: List[Instruction], startIndex: Int, endIndex: Int, handlerIndex: Int): Unit = {
val insVec = instructions.toVector
assertTrue(h.start == insVec(startIndex) && h.end == insVec(endIndex) && h.handler == insVec(handlerIndex))
diff --git a/test/junit/scala/tools/nsc/backend/jvm/DirectCompileTest.scala b/test/junit/scala/tools/nsc/backend/jvm/DirectCompileTest.scala
index 4086f7dd7b..240d3523f1 100644
--- a/test/junit/scala/tools/nsc/backend/jvm/DirectCompileTest.scala
+++ b/test/junit/scala/tools/nsc/backend/jvm/DirectCompileTest.scala
@@ -28,7 +28,7 @@ class DirectCompileTest extends ClearAfterClass {
|}
""".stripMargin)
def s(i: Int, n: Int) = (bytes(i) & 0xff) << n
- assertTrue((s(0, 24) | s(1, 16) | s(2, 8) | s(3, 0)) == 0xcafebabe) // mocha java latte machiatto surpreme dark roasted espresso
+ assertTrue((s(0, 24) | s(1, 16) | s(2, 8) | s(3, 0)) == 0xcafebabe) // mocha java latte macchiato surpreme dark roasted espresso
}
@Test
diff --git a/test/junit/scala/tools/nsc/backend/jvm/analysis/NullnessAnalyzerTest.scala b/test/junit/scala/tools/nsc/backend/jvm/analysis/NullnessAnalyzerTest.scala
index 3a85f03da2..94e776aadb 100644
--- a/test/junit/scala/tools/nsc/backend/jvm/analysis/NullnessAnalyzerTest.scala
+++ b/test/junit/scala/tools/nsc/backend/jvm/analysis/NullnessAnalyzerTest.scala
@@ -38,17 +38,6 @@ class NullnessAnalyzerTest extends ClearAfterClass {
nullnessAnalyzer
}
- /**
- * Instructions that match `query` when textified.
- * If `query` starts with a `+`, the next instruction is returned.
- */
- def findInstr(method: MethodNode, query: String): List[AbstractInsnNode] = {
- val useNext = query(0) == '+'
- val instrPart = if (useNext) query.drop(1) else query
- val insns = method.instructions.iterator.asScala.find(i => textify(i) contains instrPart).toList
- if (useNext) insns.map(_.getNext) else insns
- }
-
def testNullness(analyzer: NullnessAnalyzer, method: MethodNode, query: String, index: Int, nullness: Nullness): Unit = {
for (i <- findInstr(method, query)) {
val r = analyzer.frameAt(i, method).getValue(index).nullness
diff --git a/test/junit/scala/tools/nsc/backend/jvm/analysis/ProdConsAnalyzerTest.scala b/test/junit/scala/tools/nsc/backend/jvm/analysis/ProdConsAnalyzerTest.scala
new file mode 100644
index 0000000000..9af9ef54fc
--- /dev/null
+++ b/test/junit/scala/tools/nsc/backend/jvm/analysis/ProdConsAnalyzerTest.scala
@@ -0,0 +1,249 @@
+package scala.tools.nsc
+package backend.jvm
+package analysis
+
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.JUnit4
+import org.junit.Assert._
+
+import scala.tools.asm.Opcodes
+import scala.tools.asm.tree.AbstractInsnNode
+import scala.tools.partest.ASMConverters._
+import scala.tools.testing.ClearAfterClass
+import CodeGenTools._
+import AsmUtils._
+
+object ProdConsAnalyzerTest extends ClearAfterClass.Clearable {
+ var noOptCompiler = newCompiler(extraArgs = "-Ybackend:GenBCode -Yopt:l:none")
+
+ def clear(): Unit = {
+ noOptCompiler = null
+ }
+}
+
+@RunWith(classOf[JUnit4])
+class ProdConsAnalyzerTest extends ClearAfterClass {
+ ClearAfterClass.stateToClear = ProdConsAnalyzerTest
+ val noOptCompiler = ProdConsAnalyzerTest.noOptCompiler
+
+ def prodToString(producer: AbstractInsnNode) = producer match {
+ case p: InitialProducer => p.toString
+ case p => textify(p)
+ }
+
+ def testSingleInsn(singletonInsns: Traversable[AbstractInsnNode], expected: String): Unit = {
+ testInsn(single(singletonInsns), expected)
+ }
+
+ def testMultiInsns(insns: Traversable[AbstractInsnNode], expected: Traversable[String]): Unit = {
+ assertTrue(s"Sizes don't match: ${insns.size} vs ${expected.size}", insns.size == expected.size)
+ for (insn <- insns) {
+ val txt = prodToString(insn)
+ assertTrue(s"Instruction $txt not found in ${expected mkString ", "}", expected.exists(txt.contains))
+ }
+ }
+
+ def testInsn(insn: AbstractInsnNode, expected: String): Unit = {
+ val txt = prodToString(insn)
+ assertTrue(s"Expected $expected, found $txt", txt contains expected)
+ }
+
+ def single[T](c: Traversable[T]): T = {
+ assertTrue(s"Expected singleton collection, got $c", c.size == 1)
+ c.head
+ }
+
+ @Test
+ def parameters(): Unit = {
+ val List(m) = compileMethods(noOptCompiler)("def f = this.toString")
+ val a = new ProdConsAnalyzer(m, "C")
+ val call = findInstr(m, "INVOKEVIRTUAL").head
+
+ testSingleInsn(a.producersForValueAt(call, 1), "ALOAD 0") // producer of stack value
+ testSingleInsn(a.producersForInputsOf(call), "ALOAD 0")
+
+ testSingleInsn(a.consumersOfValueAt(call.getNext, 1), "ARETURN") // consumer of `toString` result
+ testSingleInsn(a.consumersOfOutputsFrom(call), "ARETURN")
+
+ testSingleInsn(a.ultimateConsumersOfValueAt(call.getNext, 1), "ARETURN")
+
+ testSingleInsn(a.initialProducersForValueAt(call, 1), "ParameterProducer")
+ testSingleInsn(a.producersForValueAt(call, 0), "ParameterProducer")
+ }
+
+ @Test
+ def parametersInitialProducer(): Unit = {
+ // mutates a parameter local (not possible in scala, but in bytecode)
+ import Opcodes._
+ val m = genMethod(descriptor = "(I)I")(
+ Label(0),
+ VarOp(ILOAD, 1),
+ Jump(IFNE, Label(1)),
+ Op(ICONST_1),
+ VarOp(ISTORE, 1),
+ Label(1),
+ VarOp(ILOAD, 1),
+ Op(IRETURN),
+ Label(2)
+ )
+ m.maxLocals = 2
+ m.maxStack = 1
+ val a = new ProdConsAnalyzer(m, "C")
+
+ val ifne = findInstr(m, "IFNE").head
+ testSingleInsn(a.producersForValueAt(ifne, 1), "ParameterProducer")
+
+ val ret = findInstr(m, "IRETURN").head
+ testMultiInsns(a.producersForValueAt(ret, 1), List("ParameterProducer", "ISTORE 1"))
+ }
+
+ @Test
+ def branching(): Unit = {
+ val List(m) = compileMethods(noOptCompiler)("def f(x: Int) = { var a = x; if (a == 0) a = 12; a }")
+ val a = new ProdConsAnalyzer(m, "C")
+
+ val List(ret) = findInstr(m, "IRETURN")
+ testMultiInsns(a.producersForValueAt(ret, 2), List("ISTORE 2", "ISTORE 2"))
+ testMultiInsns(a.initialProducersForValueAt(ret, 2), List("BIPUSH 12", "ParameterProducer"))
+
+ val List(bipush) = findInstr(m, "BIPUSH 12")
+ testSingleInsn(a.consumersOfOutputsFrom(bipush), "ISTORE 2")
+ testSingleInsn(a.ultimateConsumersOfValueAt(bipush.getNext, 3), "IRETURN")
+ }
+
+ @Test
+ def checkCast(): Unit = {
+ val List(m) = compileMethods(noOptCompiler)("def f(o: Object) = o.asInstanceOf[String]")
+ val a = new ProdConsAnalyzer(m, "C")
+ assert(findInstr(m, "CHECKCAST java/lang/String").length == 1)
+
+ val List(ret) = findInstr(m, "ARETURN")
+ testSingleInsn(a.initialProducersForInputsOf(ret), "ParameterProducer(1)")
+ }
+
+ @Test
+ def instanceOf(): Unit = {
+ val List(m) = compileMethods(noOptCompiler)("def f(o: Object) = o.isInstanceOf[String]")
+ val a = new ProdConsAnalyzer(m, "C")
+ assert(findInstr(m, "INSTANCEOF java/lang/String").length == 1)
+
+ val List(ret) = findInstr(m, "IRETURN")
+ testSingleInsn(a.initialProducersForInputsOf(ret), "INSTANCEOF")
+ }
+
+ @Test
+ def unInitLocal(): Unit = {
+ val List(m) = compileMethods(noOptCompiler)("def f(b: Boolean) = { if (b) { var a = 0; println(a) }; 1 }")
+ val a = new ProdConsAnalyzer(m, "C")
+
+ val List(store) = findInstr(m, "ISTORE")
+ val List(call) = findInstr(m, "INVOKEVIRTUAL")
+ val List(ret) = findInstr(m, "IRETURN")
+
+ testSingleInsn(a.producersForValueAt(store, 2), "UninitializedLocalProducer(2)")
+ testSingleInsn(a.producersForValueAt(call, 2), "ISTORE")
+ testMultiInsns(a.producersForValueAt(ret, 2), List("UninitializedLocalProducer", "ISTORE"))
+ }
+
+ @Test
+ def dupCopying(): Unit = {
+ val List(m) = compileMethods(noOptCompiler)("def f = new Object")
+ val a = new ProdConsAnalyzer(m, "C")
+
+ val List(newO) = findInstr(m, "NEW")
+ val List(constr) = findInstr(m, "INVOKESPECIAL")
+
+ testSingleInsn(a.producersForInputsOf(constr), "DUP")
+ testSingleInsn(a.initialProducersForInputsOf(constr), "NEW")
+
+ testSingleInsn(a.consumersOfOutputsFrom(newO), "DUP")
+ testMultiInsns(a.ultimateConsumersOfOutputsFrom(newO), List("INVOKESPECIAL", "ARETURN"))
+ }
+
+ @Test
+ def multiProducer(): Unit = {
+ import Opcodes._
+ val m = genMethod(descriptor = "(I)I")(
+ VarOp(ILOAD, 1),
+ VarOp(ILOAD, 1),
+ Op(DUP2),
+ Op(IADD),
+ Op(SWAP),
+ VarOp(ISTORE, 1),
+ Op(IRETURN)
+ )
+ m.maxLocals = 2
+ m.maxStack = 4
+ val a = new ProdConsAnalyzer(m, "C")
+
+ val List(dup2) = findInstr(m, "DUP2")
+ val List(add) = findInstr(m, "IADD")
+ val List(swap) = findInstr(m, "SWAP")
+ val List(store) = findInstr(m, "ISTORE")
+ val List(ret) = findInstr(m, "IRETURN")
+
+ testMultiInsns(a.producersForInputsOf(dup2), List("ILOAD", "ILOAD"))
+ testSingleInsn(a.consumersOfValueAt(dup2.getNext, 4), "IADD")
+ testSingleInsn(a.consumersOfValueAt(dup2.getNext, 5), "IADD")
+ testMultiInsns(a.consumersOfOutputsFrom(dup2), List("IADD", "SWAP"))
+
+ testSingleInsn(a.ultimateConsumersOfOutputsFrom(dup2), "IADD") // the 'store' is not here: it's a copying instr, so not an ultimate consumer.
+ testMultiInsns(a.consumersOfOutputsFrom(swap), List("IRETURN", "ISTORE"))
+ testSingleInsn(a.ultimateConsumersOfOutputsFrom(swap), "IRETURN") // again, no store
+ testSingleInsn(a.initialProducersForInputsOf(add), "ParameterProducer(1)")
+
+ testMultiInsns(a.producersForInputsOf(swap), List("IADD", "DUP2"))
+ testSingleInsn(a.consumersOfValueAt(swap.getNext, 4), "ISTORE")
+ testSingleInsn(a.consumersOfValueAt(swap.getNext, 3), "IRETURN")
+ testSingleInsn(a.initialProducersForInputsOf(store), "ParameterProducer(1)")
+ testSingleInsn(a.initialProducersForInputsOf(ret), "IADD")
+ }
+
+ @Test
+ def iincProdCons(): Unit = {
+ import Opcodes._
+ val m = genMethod(descriptor = "(I)I")(
+ Incr(IINC, 1, 1), // producer and cosumer of local variable 1
+ VarOp(ILOAD, 1),
+ Op(IRETURN)
+ )
+ m.maxLocals = 2
+ m.maxStack = 1
+ val a = new ProdConsAnalyzer(m, "C")
+
+ val List(inc) = findInstr(m, "IINC")
+ val List(load) = findInstr(m, "ILOAD")
+ val List(ret) = findInstr(m, "IRETURN")
+
+ testSingleInsn(a.producersForInputsOf(inc), "ParameterProducer(1)")
+ testSingleInsn(a.consumersOfOutputsFrom(inc), "ILOAD")
+ testSingleInsn(a.ultimateConsumersOfOutputsFrom(inc), "IRETURN")
+ testSingleInsn(a.consumersOfValueAt(inc, 1), "IINC") // parameter value has a single consumer, the IINC
+ testSingleInsn(a.ultimateConsumersOfValueAt(inc, 1), "IINC")
+
+ testSingleInsn(a.producersForInputsOf(load), "IINC")
+ testSingleInsn(a.producersForValueAt(load, 1), "IINC")
+
+ testSingleInsn(a.initialProducersForInputsOf(ret), "IINC")
+ }
+
+ @Test
+ def copyingInsns(): Unit = {
+ val List(m) = compileMethods(noOptCompiler)("def f = 0l.asInstanceOf[Int]")
+ val a = new ProdConsAnalyzer(m, "C")
+
+ val List(cnst) = findInstr(m, "LCONST_0")
+ val List(l2i) = findInstr(m, "L2I") // l2i is not a copying instruction
+ val List(ret) = findInstr(m, "IRETURN")
+
+ testSingleInsn(a.consumersOfOutputsFrom(cnst), "L2I")
+ testSingleInsn(a.ultimateConsumersOfOutputsFrom(cnst), "L2I")
+
+ testSingleInsn(a.producersForInputsOf(l2i), "LCONST_0")
+ testSingleInsn(a.initialProducersForInputsOf(l2i), "LCONST_0")
+
+ testSingleInsn(a.consumersOfOutputsFrom(l2i), "IRETURN")
+ testSingleInsn(a.producersForInputsOf(ret), "L2I")
+ }
+}
diff --git a/test/junit/scala/tools/nsc/backend/jvm/opt/InlinerTest.scala b/test/junit/scala/tools/nsc/backend/jvm/opt/InlinerTest.scala
index b8c5f85c49..0309bb97cc 100644
--- a/test/junit/scala/tools/nsc/backend/jvm/opt/InlinerTest.scala
+++ b/test/junit/scala/tools/nsc/backend/jvm/opt/InlinerTest.scala
@@ -503,7 +503,7 @@ class InlinerTest extends ClearAfterClass {
|class C extends T
""".stripMargin
val List(c, t, tClass) = compile(code)
- // the static implementaiton method is inlined into the mixin, so there's no invocation in the mixin
+ // the static implementation method is inlined into the mixin, so there's no invocation in the mixin
assertNoInvoke(getSingleMethod(c, "f"))
}
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 1ce1b88ff2..5ef2458c0a 100644
--- a/test/junit/scala/tools/nsc/backend/jvm/opt/MethodLevelOpts.scala
+++ b/test/junit/scala/tools/nsc/backend/jvm/opt/MethodLevelOpts.scala
@@ -56,7 +56,7 @@ class MethodLevelOpts extends ClearAfterClass {
}
@Test
- def inlineReturnInCachtNotTry(): Unit = {
+ def inlineReturnInCatchNotTry(): Unit = {
val code = "def f: Int = return { try 1 catch { case _: Throwable => 2 } }"
// cannot inline the IRETURN into the try block (because RETURN may throw IllegalMonitorState)
val m = singleMethod(methodOptCompiler)(code)
diff --git a/test/junit/scala/tools/nsc/classpath/FlatClassPathResolverTest.scala b/test/junit/scala/tools/nsc/classpath/FlatClassPathResolverTest.scala
index a37ba31b31..5dee488285 100644
--- a/test/junit/scala/tools/nsc/classpath/FlatClassPathResolverTest.scala
+++ b/test/junit/scala/tools/nsc/classpath/FlatClassPathResolverTest.scala
@@ -42,7 +42,7 @@ class FlatClassPathResolverTest {
// In Java TemporaryFolder in JUnit is managed automatically using @Rule.
// It would work also in Scala after adding and extending a class like
// TestWithTempFolder.java containing it. But in this case it doesn't work when running tests
- // from the command line - java class is not compiled due to some, misterious reasons.
+ // from the command line - java class is not compiled due to some, mysterious reasons.
// That's why such dirs are here created and deleted manually.
tempDir.create()
tempDir.newFile("TestSourceInRootPackage.scala")
diff --git a/test/scaladoc/run/groups.scala b/test/scaladoc/run/groups.scala
index c9e4a8679b..ad5cca89b8 100644
--- a/test/scaladoc/run/groups.scala
+++ b/test/scaladoc/run/groups.scala
@@ -38,7 +38,7 @@ object Test extends ScaladocModelTest {
* @groupdesc C Group C is introduced by B
*/
trait B {
- /** baz descriptopn
+ /** baz description
* @group C */
def baz = 3
}
diff --git a/versions.properties b/versions.properties
index a7ec8caedc..529365c9f9 100644
--- a/versions.properties
+++ b/versions.properties
@@ -8,7 +8,7 @@
# The scala version used for boostrapping. This has no impact on the final classfiles:
# there are two stages (locker and quick), so compiler and library are always built
# with themselves. Stability is ensured by building a third stage (strap).
-starr.version=2.11.6
+starr.version=2.11.7
# These are the versions of the modules that go with this release.
# These properties are used during PR validation and in dbuild builds.
@@ -22,7 +22,7 @@ starr.version=2.11.6
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.6
+scala.full.version=2.11.7
# external modules shipped with distribution, as specified by scala-library-all's pom
scala-xml.version.number=1.0.4
@@ -33,7 +33,7 @@ scala-swing.version.number=1.0.2
akka-actor.version.number=2.3.10
actors-migration.version.number=1.1.0
jline.version=2.12.1
-scala-asm.version=5.0.4-scala-1
+scala-asm.version=5.0.4-scala-2
# external modules, used internally (not shipped)
partest.version.number=1.0.7