summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore6
-rw-r--r--.travis.yml2
-rw-r--r--Gemfile2
-rw-r--r--README.md9
-rw-r--r--build.sbt443
-rwxr-xr-xbuild.xml8
-rw-r--r--compare-build-dirs-ignore-patterns8
-rwxr-xr-xcompare-build-dirs.sh5
-rw-r--r--project/ScalaTool.scala44
-rw-r--r--project/build.properties1
-rw-r--r--project/plugins.sbt1
-rwxr-xr-xscripts/jobs/integrate/bootstrap32
-rw-r--r--scripts/repositories-scala-release7
-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/Reporting.scala2
-rwxr-xr-xsrc/compiler/scala/tools/nsc/ast/parser/MarkupParsers.scala129
-rw-r--r--src/compiler/scala/tools/nsc/ast/parser/Parsers.scala2
-rwxr-xr-xsrc/compiler/scala/tools/nsc/ast/parser/SymbolicXMLBuilder.scala24
-rw-r--r--src/compiler/scala/tools/nsc/backend/icode/GenICode.scala7
-rw-r--r--src/compiler/scala/tools/nsc/backend/icode/ICodeCheckers.scala8
-rw-r--r--src/compiler/scala/tools/nsc/backend/icode/analysis/TypeFlowAnalysis.scala2
-rw-r--r--src/compiler/scala/tools/nsc/backend/jvm/BCodeAsmCommon.scala6
-rw-r--r--src/compiler/scala/tools/nsc/backend/jvm/BTypes.scala30
-rw-r--r--src/compiler/scala/tools/nsc/backend/jvm/BTypesFromSymbols.scala23
-rw-r--r--src/compiler/scala/tools/nsc/backend/jvm/BackendReporting.scala56
-rw-r--r--src/compiler/scala/tools/nsc/backend/jvm/GenBCode.scala8
-rw-r--r--src/compiler/scala/tools/nsc/backend/jvm/opt/BytecodeUtils.scala28
-rw-r--r--src/compiler/scala/tools/nsc/backend/jvm/opt/CallGraph.scala14
-rw-r--r--src/compiler/scala/tools/nsc/backend/jvm/opt/Inliner.scala63
-rw-r--r--src/compiler/scala/tools/nsc/backend/jvm/opt/LocalOpt.scala72
-rw-r--r--src/compiler/scala/tools/nsc/backend/opt/DeadCodeElimination.scala4
-rw-r--r--src/compiler/scala/tools/nsc/plugins/Plugin.scala6
-rw-r--r--src/compiler/scala/tools/nsc/settings/ScalaSettings.scala37
-rw-r--r--src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala32
-rw-r--r--src/compiler/scala/tools/nsc/transform/AddInterfaces.scala2
-rw-r--r--src/compiler/scala/tools/nsc/transform/Constructors.scala2
-rw-r--r--src/compiler/scala/tools/nsc/transform/Delambdafy.scala115
-rw-r--r--src/compiler/scala/tools/nsc/transform/Erasure.scala10
-rw-r--r--src/compiler/scala/tools/nsc/transform/LambdaLift.scala14
-rw-r--r--src/compiler/scala/tools/nsc/transform/LazyVals.scala2
-rw-r--r--src/compiler/scala/tools/nsc/transform/Mixin.scala4
-rw-r--r--src/compiler/scala/tools/nsc/transform/SampleTransform.scala2
-rw-r--r--src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala4
-rw-r--r--src/compiler/scala/tools/nsc/transform/UnCurry.scala18
-rw-r--r--src/compiler/scala/tools/nsc/transform/patmat/Logic.scala65
-rw-r--r--src/compiler/scala/tools/nsc/transform/patmat/MatchAnalysis.scala195
-rw-r--r--src/compiler/scala/tools/nsc/transform/patmat/MatchTreeMaking.scala2
-rw-r--r--src/compiler/scala/tools/nsc/transform/patmat/Solving.scala153
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/AnalyzerPlugins.scala2
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Contexts.scala8
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Infer.scala7
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Namers.scala2
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/RefChecks.scala2
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala2
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Typers.scala11
-rw-r--r--src/interactive/scala/tools/nsc/interactive/CompilerControl.scala2
-rw-r--r--src/interactive/scala/tools/nsc/interactive/Global.scala2
-rw-r--r--src/interactive/scala/tools/nsc/interactive/Lexer.scala2
-rw-r--r--src/library/scala/Mutable.scala2
-rw-r--r--src/library/scala/Predef.scala4
-rw-r--r--src/library/scala/annotation/switch.scala3
-rw-r--r--src/library/scala/collection/GenTraversableOnce.scala4
-rw-r--r--src/library/scala/collection/SeqLike.scala2
-rw-r--r--src/library/scala/collection/TraversableLike.scala2
-rw-r--r--src/library/scala/collection/TraversableOnce.scala17
-rw-r--r--src/library/scala/collection/concurrent/Map.scala2
-rw-r--r--src/library/scala/collection/immutable/Stream.scala2
-rw-r--r--src/library/scala/collection/mutable/AVLTree.scala4
-rw-r--r--src/library/scala/collection/mutable/HashTable.scala2
-rw-r--r--src/library/scala/collection/mutable/UnrolledBuffer.scala2
-rw-r--r--src/library/scala/collection/mutable/WrappedArray.scala2
-rw-r--r--src/library/scala/concurrent/JavaConversions.scala2
-rw-r--r--src/library/scala/concurrent/duration/Duration.scala5
-rw-r--r--src/library/scala/math/BigDecimal.scala2
-rw-r--r--src/library/scala/sys/process/BasicIO.scala2
-rw-r--r--src/library/scala/sys/process/ProcessLogger.scala2
-rw-r--r--src/library/scala/util/control/Exception.scala2
-rw-r--r--src/library/scala/util/hashing/MurmurHash3.scala2
-rw-r--r--src/library/scala/util/matching/Regex.scala2
-rw-r--r--src/partest-extras/scala/tools/partest/ASMConverters.scala2
-rw-r--r--src/partest-extras/scala/tools/partest/ParserTest.scala21
-rw-r--r--src/reflect/scala/reflect/api/Quasiquotes.scala2
-rw-r--r--src/reflect/scala/reflect/internal/Definitions.scala2
-rw-r--r--src/reflect/scala/reflect/internal/ReificationSupport.scala2
-rw-r--r--src/reflect/scala/reflect/internal/Symbols.scala3
-rw-r--r--src/reflect/scala/reflect/internal/TreeGen.scala2
-rw-r--r--src/reflect/scala/reflect/internal/Types.scala4
-rw-r--r--src/reflect/scala/reflect/internal/tpe/FindMembers.scala2
-rw-r--r--src/reflect/scala/reflect/runtime/JavaMirrors.scala6
-rw-r--r--src/repl/scala/tools/nsc/interpreter/ConsoleReaderHelper.scala15
-rw-r--r--src/repl/scala/tools/nsc/interpreter/JavapClass.scala34
-rw-r--r--src/scaladoc/scala/tools/nsc/doc/Index.scala2
-rwxr-xr-xsrc/scaladoc/scala/tools/nsc/doc/base/CommentFactoryBase.scala33
-rw-r--r--src/scaladoc/scala/tools/nsc/doc/html/HtmlFactory.scala2
-rw-r--r--src/scaladoc/scala/tools/nsc/doc/html/HtmlPage.scala47
-rwxr-xr-xsrc/scaladoc/scala/tools/nsc/doc/html/page/DeprecatedIndex.scala58
-rw-r--r--src/scaladoc/scala/tools/nsc/doc/html/page/Index.scala7
-rw-r--r--src/scaladoc/scala/tools/nsc/doc/html/page/Template.scala6
-rw-r--r--src/scaladoc/scala/tools/nsc/doc/html/resource/lib/template.css2
-rw-r--r--src/scaladoc/scala/tools/nsc/doc/html/resource/lib/template.js2
-rwxr-xr-xsrc/scaladoc/scala/tools/nsc/doc/model/IndexModelFactory.scala8
-rw-r--r--test/files/jvm/inner.scala2
-rw-r--r--test/files/jvm/javaReflection/Test.scala4
-rw-r--r--test/files/jvm/t8689.scala9
-rw-r--r--test/files/neg/case-collision2.flags2
-rw-r--r--test/files/neg/inlineMaxSize.check9
-rw-r--r--test/files/neg/inlineMaxSize.flags1
-rw-r--r--test/files/neg/inlineMaxSize.scala8
-rw-r--r--test/files/neg/patmatexhaust-huge.check7
-rw-r--r--test/files/neg/patmatexhaust-huge.flags1
-rw-r--r--test/files/neg/patmatexhaust-huge.scala806
-rw-r--r--test/files/neg/t0899.check6
-rw-r--r--test/files/neg/t562.check2
-rw-r--r--test/files/neg/t8731.check5
-rw-r--r--test/files/neg/t9273.check10
-rw-r--r--test/files/neg/t9273.scala9
-rw-r--r--test/files/pos/t3368.flags1
-rw-r--r--test/files/pos/t3368.scala5
-rw-r--r--test/files/pos/t6942.flags2
-rw-r--r--test/files/pos/t7815.scala2
-rw-r--r--test/files/pos/t8359-closelim-crash.flags1
-rw-r--r--test/files/pos/t8359-closelim-crash.scala23
-rw-r--r--test/files/pos/t8861.flags1
-rw-r--r--test/files/pos/t8861.scala11
-rw-r--r--test/files/pos/t9181.flags1
-rw-r--r--test/files/pos/t9181.scala806
-rw-r--r--test/files/pos/t9239/Declaration.scala3
-rw-r--r--test/files/pos/t9239/Usage.java15
-rw-r--r--test/files/run/classfile-format-51.scala2
-rw-r--r--test/files/run/classfile-format-52.scala2
-rw-r--r--test/files/run/delambdafy-specialized.check1
-rw-r--r--test/files/run/delambdafy-specialized.flags1
-rw-r--r--test/files/run/delambdafy-specialized.scala6
-rw-r--r--test/files/run/delambdafy_t6028.check51
-rw-r--r--test/files/run/delambdafy_t6028.scala10
-rw-r--r--test/files/run/delambdafy_t6555.check8
-rw-r--r--test/files/run/delambdafy_t6555.scala2
-rw-r--r--test/files/run/delambdafy_uncurry_byname_method.check6
-rw-r--r--test/files/run/delambdafy_uncurry_byname_method.scala4
-rw-r--r--test/files/run/repl-javap-lambdas.scala6
-rw-r--r--test/files/run/t3368-b.check89
-rw-r--r--test/files/run/t3368-b.scala26
-rw-r--r--test/files/run/t3368-c.check85
-rw-r--r--test/files/run/t3368-c.scala26
-rw-r--r--test/files/run/t3368-d.check89
-rw-r--r--test/files/run/t3368-d.scala26
-rw-r--r--test/files/run/t3368.check85
-rw-r--r--test/files/run/t3368.scala26
-rwxr-xr-xtest/files/run/t5699.scala14
-rw-r--r--test/files/run/t7407.flags2
-rw-r--r--test/files/run/t7407b.flags2
-rw-r--r--test/files/run/t7741a/GroovyInterface$1Dump.java222
-rw-r--r--test/files/run/t7741a/GroovyInterfaceDump.java51
-rw-r--r--test/files/run/t7741a/Test.scala47
-rw-r--r--test/files/run/t7741b.check3
-rw-r--r--test/files/run/t7741b/HasInner.java3
-rw-r--r--test/files/run/t7741b/Test.scala29
-rw-r--r--test/files/run/t8845.flags2
-rw-r--r--test/files/run/t8925.flags2
-rw-r--r--test/files/run/t9097.scala2
-rw-r--r--test/files/run/t9252.check1
-rw-r--r--test/files/run/t9252.scala5
-rw-r--r--test/files/run/t9268.check5
-rw-r--r--test/files/run/t9268/Java.java12
-rw-r--r--test/files/run/t9268/Test.scala40
-rw-r--r--test/files/run/valueClassSelfType.scala52
-rw-r--r--test/junit/scala/collection/mutable/VectorTest.scala1
-rw-r--r--test/junit/scala/concurrent/duration/SerializationTest.scala24
-rw-r--r--test/junit/scala/tools/nsc/backend/jvm/CodeGenTools.scala7
-rw-r--r--test/junit/scala/tools/nsc/backend/jvm/opt/EmptyExceptionHandlersTest.scala4
-rw-r--r--test/junit/scala/tools/nsc/backend/jvm/opt/EmptyLabelsAndLineNumbersTest.scala6
-rw-r--r--test/junit/scala/tools/nsc/backend/jvm/opt/InlineWarningTest.scala48
-rw-r--r--test/junit/scala/tools/nsc/backend/jvm/opt/InlinerTest.scala29
-rw-r--r--test/junit/scala/tools/nsc/backend/jvm/opt/SimplifyJumpsTest.scala24
-rw-r--r--test/junit/scala/tools/nsc/backend/jvm/opt/UnreachableCodeTest.scala2
-rw-r--r--test/junit/scala/tools/nsc/interpreter/TabulatorTest.scala20
-rw-r--r--test/junit/scala/tools/nsc/transform/patmat/SolvingTest.scala61
-rw-r--r--test/pending/jvm/javasigs.scala2
-rw-r--r--test/pending/run/delambdafy-lambdametafactory.scala50
-rw-r--r--test/scaladoc/resources/SI-4476.scala9
-rw-r--r--test/scaladoc/resources/Trac4420.scala2
-rw-r--r--test/scaladoc/run/t5795.check4
-rw-r--r--test/scaladoc/run/t5795.scala63
-rw-r--r--test/scaladoc/scalacheck/CommentFactoryTest.scala20
-rw-r--r--test/scaladoc/scalacheck/DeprecatedIndexTest.scala50
-rw-r--r--test/scaladoc/scalacheck/HtmlFactoryTest.scala4
-rw-r--r--test/scaladoc/scalacheck/IndexTest.scala8
-rwxr-xr-xtools/scaladoc-compare2
-rw-r--r--versions.properties2
190 files changed, 4662 insertions, 659 deletions
diff --git a/.gitignore b/.gitignore
index 20d700dd12..d6571a377f 100644
--- a/.gitignore
+++ b/.gitignore
@@ -48,3 +48,9 @@
# Standard symbolic link to build/quick/bin
/qbin
+
+# Sbt's target directories
+/target/
+/project/target/
+/project/project/target
+/build-sbt/
diff --git a/.travis.yml b/.travis.yml
index e90fc35267..6a7ac45e3d 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -2,7 +2,7 @@
# based on http://www.paperplanes.de/2013/8/13/deploying-your-jekyll-blog-to-s3-with-travis-ci.html
language: ruby
rvm:
- - 1.9.3
+ - 2.2
script: bundle exec jekyll build -s spec/ -d build/spec
install: bundle install
diff --git a/Gemfile b/Gemfile
index 53924a4381..6921f792c3 100644
--- a/Gemfile
+++ b/Gemfile
@@ -1,7 +1,7 @@
# To build the spec on Travis CI
source "https://rubygems.org"
-gem "jekyll", "2.0.0.alpha.2"
+gem "jekyll", "2.5.3"
gem "rouge"
# gem 's3_website'
# gem 'redcarpet'
diff --git a/README.md b/README.md
index 830dfa8d6c..1651333188 100644
--- a/README.md
+++ b/README.md
@@ -138,6 +138,15 @@ The Scala build system is based on Apache Ant. Most required pre-compiled
libraries are part of the repository (in 'lib/'). The following however is
assumed to be installed on the build machine:
+## Building with Sbt (EXPERIMENTAL)
+
+The experimental sbt-based build definition has arrived! Run `sbt package`
+to build the compiler. You can run `sbt test` to run unit (JUnit) tests.
+Use `sbt test/it:test` to run integration (partest) tests.
+
+We would like to migrate to sbt build as quickly as possible. If you would
+like to help please contact scala-internals@ mailing list to discuss your
+ideas and coordinate your effort with others.
### Tips and tricks
diff --git a/build.sbt b/build.sbt
new file mode 100644
index 0000000000..0df2e6a800
--- /dev/null
+++ b/build.sbt
@@ -0,0 +1,443 @@
+/*
+ * The new, sbt-based build definition for Scala.
+ *
+ * What you see below is very much work-in-progress. Basics like compiling and packaging jars
+ * (into right location) work. Everything else is missing:
+ * building docs, placing shell scripts in right locations (so you can run compiler easily),
+ * running partest test, compiling and running JUnit test, and many, many other things.
+ *
+ * You'll notice that this build definition is much more complicated than your typical sbt build.
+ * The main reason is that we are not benefiting from sbt's conventions when it comes project
+ * layout. For that reason we have to configure a lot more explicitly. I've tried explain in
+ * comments the less obvious settings.
+ *
+ * This nicely leads me to explaining goal and non-goals of this build definition. Goals are:
+ *
+ * - to be easy to tweak it in case a bug or small inconsistency is found
+ * - to mimic Ant's behavior as closely as possible
+ * - to be super explicit about any departure from standard sbt settings
+ * - to achieve functional parity with Ant build as quickly as possible
+ * - to be readable and not necessarily succinct
+ * - to provide the nicest development experience for people hacking on Scala
+ *
+ * Non-goals are:
+ *
+ * - to have the shortest sbt build definition possible; we'll beat Ant definition
+ * easily and that will thrill us already
+ * - to remove irregularities from our build process right away
+ * - to modularize the Scala compiler or library further
+ *
+ * It boils down to simple rules:
+ *
+ * - project layout is set in stone for now
+ * - if you need to work on convincing sbt to follow non-standard layout then
+ * explain everything you did in comments
+ * - constantly check where Ant build produces class files, artifacts, what kind of other
+ * files generates and port all of that to here
+ *
+ * Note on bootstrapping:
+ *
+ * Let's start with reminder what bootstrapping means in our context. It's an answer
+ * to this question: which version of Scala are using to compile Scala? The fact that
+ * the question sounds circular suggests trickiness. Indeed, bootstrapping Scala
+ * compiler is a tricky process.
+ *
+ * Ant build used to have involved system of bootstrapping Scala. It would consist of
+ * three layers: starr, locker and quick. The sbt build for Scala ditches layering
+ * and strives to be as standard sbt project as possible. This means that we are simply
+ * building Scala with latest stable release of Scala.
+ * See this discussion for more details behind this decision:
+ * https://groups.google.com/d/topic/scala-internals/gp5JsM1E0Fo/discussion
+ */
+
+val bootstrapScalaVersion = "2.11.5"
+
+def withoutScalaLang(moduleId: ModuleID): ModuleID = moduleId exclude("org.scala-lang", "*")
+
+// exclusion of the scala-library transitive dependency avoids eviction warnings during `update`.
+val scalaParserCombinatorsDep = withoutScalaLang("org.scala-lang.modules" %% "scala-parser-combinators" % versionNumber("scala-parser-combinators"))
+val scalaXmlDep = withoutScalaLang("org.scala-lang.modules" %% "scala-xml" % versionNumber("scala-xml"))
+val partestDep = withoutScalaLang("org.scala-lang.modules" %% "scala-partest" % versionNumber("partest"))
+val partestInterfaceDep = withoutScalaLang("org.scala-lang.modules" %% "scala-partest-interface" % "0.5.0")
+val junitDep = "junit" % "junit" % "4.11"
+val junitIntefaceDep = "com.novocode" % "junit-interface" % "0.11" % "test"
+val jlineDep = "jline" % "jline" % versionProps("jline.version")
+val antDep = "org.apache.ant" % "ant" % "1.9.4"
+val scalacheckDep = withoutScalaLang("org.scalacheck" %% "scalacheck" % "1.11.4")
+
+lazy val commonSettings = clearSourceAndResourceDirectories ++ Seq[Setting[_]](
+ organization := "org.scala-lang",
+ version := "2.11.6-SNAPSHOT",
+ scalaVersion := bootstrapScalaVersion,
+ // we don't cross build Scala itself
+ crossPaths := false,
+ // do not add Scala library jar as a dependency automatically
+ autoScalaLibrary := false,
+ // we also do not add scala instance automatically because it introduces
+ // a circular instance, see: https://github.com/sbt/sbt/issues/1872
+ managedScalaInstance := false,
+ // this is a way to workaround issue described in https://github.com/sbt/sbt/issues/1872
+ // check it out for more details
+ scalaInstance := ScalaInstance(scalaVersion.value, appConfiguration.value.provider.scalaProvider.launcher getScala scalaVersion.value),
+ // we always assume that Java classes are standalone and do not have any dependency
+ // on Scala classes
+ compileOrder := CompileOrder.JavaThenScala,
+ javacOptions in Compile ++= Seq("-g", "-source", "1.5", "-target", "1.6"),
+ // we don't want any unmanaged jars; as a reminder: unmanaged jar is a jar stored
+ // directly on the file system and it's not resolved through Ivy
+ // Ant's build stored unmanaged jars in `lib/` directory
+ unmanagedJars in Compile := Seq.empty,
+ sourceDirectory in Compile := baseDirectory.value,
+ unmanagedSourceDirectories in Compile := List(baseDirectory.value),
+ scalaSource in Compile := (sourceDirectory in Compile).value,
+ javaSource in Compile := (sourceDirectory in Compile).value,
+ // resources are stored along source files in our current layout
+ resourceDirectory in Compile := (sourceDirectory in Compile).value,
+ // each subproject has to ask specifically for files they want to include
+ includeFilter in unmanagedResources in Compile := NothingFilter,
+ target := (baseDirectory in ThisBuild).value / "target" / thisProject.value.id,
+ target in Compile in doc := buildDirectory.value / "scaladoc" / thisProject.value.id,
+ classDirectory in Compile := buildDirectory.value / "quick/classes" / thisProject.value.id,
+ // given that classDirectory is overriden to be _outside_ of target directory, we have
+ // to make sure its being cleaned properly
+ cleanFiles += (classDirectory in Compile).value,
+ fork in run := true
+)
+
+// disable various tasks that are not needed for projects that are used
+// only for compiling code and not publishing it as a standalone artifact
+// we disable those tasks by overriding them and returning bogus files when
+// needed. This is a bit sketchy but I haven't found any better way.
+val disableDocsAndPublishingTasks = Seq[Setting[_]](
+ doc := file("!!! NO DOCS !!!"),
+ publishLocal := {},
+ publish := {},
+ packageBin in Compile := file("!!! NO PACKAGING !!!")
+)
+
+lazy val setJarLocation: Setting[_] =
+ artifactPath in packageBin in Compile := {
+ // two lines below are copied over from sbt's sources:
+ // https://github.com/sbt/sbt/blob/0.13/main/src/main/scala/sbt/Defaults.scala#L628
+ //val resolvedScalaVersion = ScalaVersion((scalaVersion in artifactName).value, (scalaBinaryVersion in artifactName).value)
+ //val resolvedArtifactName = artifactName.value(resolvedScalaVersion, projectID.value, artifact.value)
+ // if you would like to get a jar with version number embedded in it (as normally sbt does)
+ // uncomment the other definition of the `resolvedArtifactName`
+ val resolvedArtifact = artifact.value
+ val resolvedArtifactName = s"${resolvedArtifact.name}.${resolvedArtifact.extension}"
+ buildDirectory.value / "pack/lib" / resolvedArtifactName
+ }
+lazy val scalaSubprojectSettings: Seq[Setting[_]] = commonSettings :+ setJarLocation
+
+lazy val generatePropertiesFileSettings = Seq[Setting[_]](
+ copyrightString := "Copyright 2002-2013, LAMP/EPFL",
+ resourceGenerators in Compile += generateVersionPropertiesFile.map(file => Seq(file)).taskValue,
+ generateVersionPropertiesFile := generateVersionPropertiesFileImpl.value
+)
+
+val libIncludes: FileFilter = "*.tmpl" | "*.xml" | "*.js" | "*.css" | "rootdoc.txt"
+
+lazy val library = configureAsSubproject(project)
+ .settings(generatePropertiesFileSettings: _*)
+ .settings(
+ name := "scala-library",
+ scalacOptions in Compile ++= Seq[String]("-sourcepath", (scalaSource in Compile).value.toString),
+ // Workaround for a bug in `scaladoc` that it seems to not respect the `-sourcepath` option
+ // as a result of this bug, the compiler cannot even initialize Definitions without
+ // binaries of the library on the classpath. Specifically, we get this error:
+ // (library/compile:doc) scala.reflect.internal.FatalError: package class scala does not have a member Int
+ // Ant build does the same thing always: it puts binaries for documented classes on the classpath
+ // sbt never does this by default (which seems like a good default)
+ dependencyClasspath in Compile in doc += (classDirectory in Compile).value,
+ scalacOptions in Compile in doc ++= {
+ val libraryAuxDir = (baseDirectory in ThisBuild).value / "src/library-aux"
+ Seq("-doc-no-compile", libraryAuxDir.toString)
+ },
+ includeFilter in unmanagedResources in Compile := libIncludes)
+ .dependsOn (forkjoin)
+
+lazy val reflect = configureAsSubproject(project)
+ .settings(generatePropertiesFileSettings: _*)
+ .settings(name := "scala-reflect")
+ .dependsOn(library)
+
+val compilerIncludes: FileFilter =
+ "*.tmpl" | "*.xml" | "*.js" | "*.css" | "*.html" | "*.properties" | "*.swf" |
+ "*.png" | "*.gif" | "*.gif" | "*.txt"
+
+lazy val compiler = configureAsSubproject(project)
+ .settings(generatePropertiesFileSettings: _*)
+ .settings(
+ name := "scala-compiler",
+ libraryDependencies += antDep,
+ // this a way to make sure that classes from interactive and scaladoc projects
+ // end up in compiler jar (that's what Ant build does)
+ // we need to use LocalProject references (with strings) to deal with mutual recursion
+ mappings in Compile in packageBin :=
+ (mappings in Compile in packageBin).value ++
+ (mappings in Compile in packageBin in LocalProject("interactive")).value ++
+ (mappings in Compile in packageBin in LocalProject("scaladoc")).value ++
+ (mappings in Compile in packageBin in LocalProject("repl")).value,
+ includeFilter in unmanagedResources in Compile := compilerIncludes)
+ .dependsOn(library, reflect, asm)
+
+lazy val interactive = configureAsSubproject(project)
+ .settings(disableDocsAndPublishingTasks: _*)
+ .dependsOn(compiler)
+
+lazy val repl = configureAsSubproject(project)
+ .settings(libraryDependencies += jlineDep)
+ .settings(disableDocsAndPublishingTasks: _*)
+ .dependsOn(compiler)
+
+lazy val scaladoc = configureAsSubproject(project)
+ .settings(
+ libraryDependencies ++= Seq(scalaXmlDep, scalaParserCombinatorsDep, partestDep)
+ )
+ .settings(disableDocsAndPublishingTasks: _*)
+ .dependsOn(compiler)
+
+lazy val scalap = configureAsSubproject(project).
+ dependsOn(compiler)
+
+// deprecated Scala Actors project
+// TODO: it packages into actors.jar but it should be scala-actors.jar
+lazy val actors = configureAsSubproject(project)
+ .settings(generatePropertiesFileSettings: _*)
+ .settings(name := "scala-actors")
+ .dependsOn(library)
+
+lazy val forkjoin = configureAsForkOfJavaProject(project)
+
+lazy val asm = configureAsForkOfJavaProject(project)
+
+lazy val partestExtras = configureAsSubproject(Project("partest-extras", file(".") / "src" / "partest-extras"))
+ .dependsOn(repl)
+ .settings(clearSourceAndResourceDirectories: _*)
+ .settings(
+ libraryDependencies += partestDep,
+ unmanagedSourceDirectories in Compile := List(baseDirectory.value)
+ )
+
+lazy val junit = project.in(file("test") / "junit")
+ .dependsOn(library, reflect, compiler, partestExtras, scaladoc)
+ .settings(clearSourceAndResourceDirectories: _*)
+ .settings(commonSettings: _*)
+ .settings(
+ fork in Test := true,
+ libraryDependencies ++= Seq(junitDep, junitIntefaceDep),
+ testOptions += Tests.Argument(TestFrameworks.JUnit, "-a", "-v"),
+ unmanagedSourceDirectories in Test := List(baseDirectory.value)
+ )
+
+lazy val partestJavaAgent = (project in file(".") / "src" / "partest-javaagent").
+ dependsOn(asm).
+ settings(commonSettings: _*).
+ settings(
+ doc := file("!!! NO DOCS !!!"),
+ publishLocal := {},
+ publish := {},
+ // Setting name to "scala-partest-javaagent" so that the jar file gets that name, which the Runner relies on
+ name := "scala-partest-javaagent",
+ // writing jar file to $buildDirectory/pack/lib because that's where it's expected to be found
+ setJarLocation,
+ // add required manifest entry - previously included from file
+ packageOptions in (Compile, packageBin) +=
+ Package.ManifestAttributes( "Premain-Class" -> "scala.tools.partest.javaagent.ProfilingAgent" ),
+ // we need to build this to a JAR
+ exportJars := true
+ )
+
+lazy val test = project.
+ dependsOn(compiler, interactive, actors, repl, scalap, partestExtras, partestJavaAgent, asm, scaladoc).
+ configs(IntegrationTest).
+ settings(disableDocsAndPublishingTasks: _*).
+ settings(commonSettings: _*).
+ settings(Defaults.itSettings: _*).
+ settings(
+ libraryDependencies ++= Seq(partestDep, scalaXmlDep, partestInterfaceDep, scalacheckDep),
+ unmanagedBase in Test := baseDirectory.value / "files" / "lib",
+ unmanagedJars in Test <+= (unmanagedBase) (j => Attributed.blank(j)) map(identity),
+ // no main sources
+ sources in Compile := Seq.empty,
+ // test sources are compiled in partest run, not here
+ sources in IntegrationTest := Seq.empty,
+ fork in IntegrationTest := true,
+ javaOptions in IntegrationTest += "-Xmx1G",
+ testFrameworks += new TestFramework("scala.tools.partest.Framework"),
+ testOptions in IntegrationTest += Tests.Setup( () => root.base.getAbsolutePath + "/pull-binary-libs.sh" ! ),
+ definedTests in IntegrationTest += (
+ new sbt.TestDefinition(
+ "partest",
+ // marker fingerprint since there are no test classes
+ // to be discovered by sbt:
+ new sbt.testing.AnnotatedFingerprint {
+ def isModule = true
+ def annotationName = "partest"
+ }, true, Array())
+ )
+ )
+
+lazy val root = (project in file(".")).
+ aggregate(library, forkjoin, reflect, compiler, asm, interactive, repl,
+ scaladoc, scalap, actors, partestExtras, junit).settings(
+ sources in Compile := Seq.empty,
+ onLoadMessage := """|*** Welcome to the sbt build definition for Scala! ***
+ |This build definition has an EXPERIMENTAL status. If you are not
+ |interested in testing or working on the build itself, please use
+ |the Ant build definition for now. Check README.md for more information.""".stripMargin
+ )
+
+lazy val dist = (project in file("dist")).settings(
+ mkBin := mkBinImpl.value
+)
+
+/**
+ * Configures passed project as a subproject (e.g. compiler or repl)
+ * with common settings attached to it.
+ *
+ * Typical usage is:
+ *
+ * lazy val mySubproject = configureAsSubproject(project)
+ *
+ * We pass `project` as an argument which is in fact a macro call. This macro determines
+ * project.id based on the name of the lazy val on the left-hand side.
+ */
+def configureAsSubproject(project: Project): Project = {
+ val base = file(".") / "src" / project.id
+ (project in base).settings(scalaSubprojectSettings: _*)
+}
+
+/**
+ * Configuration for subprojects that are forks of some Java projects
+ * we depend on. At the moment there are just two: asm and forkjoin.
+ *
+ * We do not publish artifacts for those projects but we package their
+ * binaries in a jar of other project (compiler or library).
+ *
+ * For that reason we disable docs generation, packaging and publishing.
+ */
+def configureAsForkOfJavaProject(project: Project): Project = {
+ val base = file(".") / "src" / project.id
+ (project in base).
+ settings(commonSettings: _*).
+ settings(disableDocsAndPublishingTasks: _*).
+ settings(
+ sourceDirectory in Compile := baseDirectory.value,
+ javaSource in Compile := (sourceDirectory in Compile).value,
+ sources in Compile in doc := Seq.empty,
+ classDirectory in Compile := buildDirectory.value / "libs/classes" / thisProject.value.id
+ )
+}
+
+lazy val buildDirectory = settingKey[File]("The directory where all build products go. By default ./build")
+lazy val copyrightString = settingKey[String]("Copyright string.")
+lazy val generateVersionPropertiesFile = taskKey[File]("Generating version properties file.")
+lazy val mkBin = taskKey[Seq[File]]("Generate shell script (bash or Windows batch).")
+
+lazy val generateVersionPropertiesFileImpl: Def.Initialize[Task[File]] = Def.task {
+ val propFile = (resourceManaged in Compile).value / s"${thisProject.value.id}.properties"
+ val props = new java.util.Properties
+
+ /**
+ * Regexp that splits version number split into two parts: version and suffix.
+ * Examples of how the split is performed:
+ *
+ * "2.11.5": ("2.11.5", null)
+ * "2.11.5-acda7a": ("2.11.5", "-acda7a")
+ * "2.11.5-SNAPSHOT": ("2.11.5", "-SNAPSHOT")
+ *
+ */
+ val versionSplitted = """([\w+\.]+)(-[\w+\.]+)??""".r
+
+ val versionSplitted(ver, suffixOrNull) = version.value
+ val osgiSuffix = suffixOrNull match {
+ case null => "-VFINAL"
+ case "-SNAPSHOT" => ""
+ case suffixStr => suffixStr
+ }
+
+ def executeTool(tool: String) = {
+ val cmd =
+ if (System.getProperty("os.name").toLowerCase.contains("windows"))
+ s"cmd.exe /c tools\\$tool.bat -p"
+ else s"tools/$tool"
+ Process(cmd).lines.head
+ }
+
+ val commitDate = executeTool("get-scala-commit-date")
+ val commitSha = executeTool("get-scala-commit-sha")
+
+ props.put("version.number", s"${version.value}-$commitDate-$commitSha")
+ props.put("maven.version.number", s"${version.value}")
+ props.put("osgi.version.number", s"$ver.v$commitDate$osgiSuffix-$commitSha")
+ props.put("copyright.string", copyrightString.value)
+
+ // unfortunately, this will write properties in arbitrary order
+ // this makes it harder to test for stability of generated artifacts
+ // consider using https://github.com/etiennestuder/java-ordered-properties
+ // instead of java.util.Properties
+ IO.write(props, null, propFile)
+
+ propFile
+}
+
+// Defining these settings is somewhat redundant as we also redefine settings that depend on them.
+// However, IntelliJ's project import works better when these are set correctly.
+def clearSourceAndResourceDirectories = Seq(Compile, Test).flatMap(config => inConfig(config)(Seq(
+ unmanagedSourceDirectories := Nil,
+ managedSourceDirectories := Nil,
+ unmanagedResourceDirectories := Nil,
+ managedResourceDirectories := Nil
+)))
+
+lazy val mkBinImpl: Def.Initialize[Task[Seq[File]]] = Def.task {
+ def mkScalaTool(mainCls: String, classpath: Seq[Attributed[File]]): ScalaTool =
+ ScalaTool(mainClass = mainCls,
+ classpath = classpath.toList.map(_.data.getAbsolutePath),
+ properties = Map.empty,
+ javaOpts = "-Xmx256M -Xms32M",
+ toolFlags = "")
+ val rootDir = (classDirectory in Compile in compiler).value
+ def writeScripts(scalaTool: ScalaTool, file: String, outDir: File): Seq[File] =
+ Seq(
+ scalaTool.writeScript(file, "unix", rootDir, outDir),
+ scalaTool.writeScript(file, "windows", rootDir, outDir)
+ )
+ def mkQuickBin(file: String, mainCls: String, classpath: Seq[Attributed[File]]): Seq[File] = {
+ val scalaTool = mkScalaTool(mainCls, classpath)
+ val outDir = buildDirectory.value / "quick/bin"
+ writeScripts(scalaTool, file, outDir)
+ }
+
+ def mkPackBin(file: String, mainCls: String): Seq[File] = {
+ val scalaTool = mkScalaTool(mainCls, classpath = Nil)
+ val outDir = buildDirectory.value / "pack/bin"
+ writeScripts(scalaTool, file, outDir)
+ }
+
+ def mkBin(file: String, mainCls: String, classpath: Seq[Attributed[File]]): Seq[File] =
+ mkQuickBin(file, mainCls, classpath) ++ mkPackBin(file, mainCls)
+
+ mkBin("scala" , "scala.tools.nsc.MainGenericRunner", (fullClasspath in Compile in repl).value) ++
+ mkBin("scalac" , "scala.tools.nsc.Main", (fullClasspath in Compile in compiler).value) ++
+ mkBin("fsc" , "scala.tools.nsc.CompileClient", (fullClasspath in Compile in compiler).value) ++
+ mkBin("scaladoc" , "scala.tools.nsc.ScalaDoc", (fullClasspath in Compile in scaladoc).value) ++
+ mkBin("scalap" , "scala.tools.scalap.Main", (fullClasspath in Compile in scalap).value)
+}
+
+buildDirectory in ThisBuild := (baseDirectory in ThisBuild).value / "build-sbt"
+
+lazy val versionProps: Map[String, String] = {
+ import java.io.FileInputStream
+ import java.util.Properties
+ val props = new Properties()
+ val in = new FileInputStream(file("versions.properties"))
+ try props.load(in)
+ finally in.close()
+ import scala.collection.JavaConverters._
+ props.asScala.toMap
+}
+
+def versionNumber(name: String): String =
+ versionProps(s"$name.version.number")
diff --git a/build.xml b/build.xml
index 4b79b68a02..0a67f8a563 100755
--- a/build.xml
+++ b/build.xml
@@ -165,7 +165,7 @@ TODO:
<property name="build.dir" value="${basedir}/build"/>
<property name="build-deps.dir" value="${build.dir}/deps"/>
<property name="build-libs.dir" value="${build.dir}/libs"/>
- <property name="build-asm.dir" value="${build.dir}/asm"/>
+ <property name="build-asm.dir" value="${build-libs.dir}"/>
<property name="build-forkjoin.dir" value="${build-libs.dir}"/>
<property name="build-locker.dir" value="${build.dir}/locker"/>
<property name="build-quick.dir" value="${build.dir}/quick"/>
@@ -588,8 +588,8 @@ TODO:
</propertyfile>
</then></if>
- <path id="forkjoin.classpath" path="${build-libs.dir}/classes/forkjoin"/>
- <path id="asm.classpath" path="${build-asm.dir}/classes"/>
+ <path id="forkjoin.classpath" path="${build-forkjoin.dir}/classes/forkjoin"/>
+ <path id="asm.classpath" path="${build-asm.dir}/classes/asm"/>
<property name="forkjoin-classes" refid="forkjoin.classpath"/>
<property name="asm-classes" refid="asm.classpath"/>
@@ -1061,7 +1061,7 @@ TODO:
============================================================================ -->
<target name="asm.done" depends="init"> <simple-javac project="asm" jar="no"/> </target>
- <target name="forkjoin.done" depends="init"> <simple-javac project="forkjoin" args="-XDignore.symbol.file"/></target>
+ <target name="forkjoin.done" depends="init"> <simple-javac project="forkjoin" args="-XDignore.symbol.file" jar="no"/></target>
<!-- For local development only. We only allow released versions of Scala for STARR.
This builds quick (core only) and publishes it with a generated version number,
diff --git a/compare-build-dirs-ignore-patterns b/compare-build-dirs-ignore-patterns
new file mode 100644
index 0000000000..8c8160ba15
--- /dev/null
+++ b/compare-build-dirs-ignore-patterns
@@ -0,0 +1,8 @@
+.DS_Store
+*.complete
+locker
+deps
+scala-continuations-*.jar
+scala-parser-combinators*.jar
+scala-swing*.jar
+scala-xml*.jar
diff --git a/compare-build-dirs.sh b/compare-build-dirs.sh
new file mode 100755
index 0000000000..f6806dd422
--- /dev/null
+++ b/compare-build-dirs.sh
@@ -0,0 +1,5 @@
+# Compares build directories generated by Ant and sbt build definitions
+# This let's us to see how far are we from achieving perfect parity
+# between the builds
+
+diff -X compare-build-dirs-ignore-patterns -qr build/ build-sbt/
diff --git a/project/ScalaTool.scala b/project/ScalaTool.scala
new file mode 100644
index 0000000000..559b215c18
--- /dev/null
+++ b/project/ScalaTool.scala
@@ -0,0 +1,44 @@
+import sbt._
+import org.apache.commons.lang3.StringUtils.replaceEach
+
+/**
+ * A class that generates a shell or batch script to execute a Scala program.
+ *
+ * This is a simplified copy of Ant task (see scala.tools.ant.ScalaTool).
+ */
+case class ScalaTool(mainClass: String,
+ classpath: List[String],
+ properties: Map[String, String],
+ javaOpts: String,
+ toolFlags: String) {
+ // For classpath, the platform specific
+ // demarcation of any script variables (e.g. `${SCALA_HOME}` or
+ // `%SCALA_HOME%`) can be specified in a platform independent way (e.g.
+ // `@SCALA_HOME@`) and automatically translated for you.
+ def patchedToolScript(template: String, platform: String) = {
+ val varRegex = """@(\w+)@""" // the group should be able to capture each of the keys of the map below
+
+ val variables = Map(
+ ("@@" -> "@"), // for backwards compatibility
+ ("@class@" -> mainClass),
+ ("@properties@" -> (properties map { case (k, v) => s"""-D$k="$v""""} mkString " ")),
+ ("@javaflags@" -> javaOpts),
+ ("@toolflags@" -> toolFlags),
+ ("@classpath@" -> (platform match {
+ case "unix" => classpath.mkString(":").replace('\\', '/').replaceAll(varRegex, """\${$1}""")
+ case "windows" => classpath.mkString(";").replace('/', '\\').replaceAll(varRegex, "%$1%")
+ }))
+ )
+
+ val (from, to) = variables.unzip
+ replaceEach(template, from.toArray, to.toArray)
+ }
+
+ def writeScript(file: String, platform: String, rootDir: File, outDir: File): File = {
+ val templatePath = s"scala/tools/ant/templates/tool-$platform.tmpl"
+ val suffix = platform match { case "windows" => ".bat" case _ => "" }
+ val scriptFile = outDir / s"$file$suffix"
+ IO.write(scriptFile, patchedToolScript(IO.read(rootDir / templatePath), platform))
+ scriptFile
+ }
+}
diff --git a/project/build.properties b/project/build.properties
new file mode 100644
index 0000000000..748703f770
--- /dev/null
+++ b/project/build.properties
@@ -0,0 +1 @@
+sbt.version=0.13.7
diff --git a/project/plugins.sbt b/project/plugins.sbt
new file mode 100644
index 0000000000..dc266a8db1
--- /dev/null
+++ b/project/plugins.sbt
@@ -0,0 +1 @@
+libraryDependencies += "org.apache.commons" % "commons-lang3" % "3.3.2" \ No newline at end of file
diff --git a/scripts/jobs/integrate/bootstrap b/scripts/jobs/integrate/bootstrap
index d0a5b452a8..7944ab3fd3 100755
--- a/scripts/jobs/integrate/bootstrap
+++ b/scripts/jobs/integrate/bootstrap
@@ -108,8 +108,22 @@ rm -rf $baseDir/resolutionScratch_
mkdir -p $baseDir/resolutionScratch_
# repo used to publish "locker" scala to (to start the bootstrap)
-privateCred="private-repo"
-privateRepo="http://private-repo.typesafe.com/typesafe/scala-release-temp/"
+releaseTempRepoCred="private-repo"
+releaseTempRepoUrl=${releaseTempRepoUrl-"http://private-repo.typesafe.com/typesafe/scala-release-temp/"}
+
+# Used below in sbtArgs since we use a dedicated repository to share artifcacts between jobs,
+# so we need to configure SBT to use these rather than its default, Maven Central.
+# See http://www.scala-sbt.org/0.13/docs/Proxy-Repositories.html
+sbtRepositoryConfig="$scriptsDir/repositories-scala-release"
+cat > "$sbtRepositoryConfig" << EOF
+[repositories]
+ plugins: http://dl.bintray.com/sbt/sbt-plugin-releases/, [organisation]/[module]/(scala_[scalaVersion]/)(sbt_[sbtVersion]/)[revision]/[type]s/[artifact](-[classifier]).[ext]
+ private-repo: $releaseTempRepoUrl
+ typesafe-ivy-releases: http://repo.typesafe.com/typesafe/ivy-releases/, [organization]/[module]/[revision]/[type]s/[artifact](-[classifier]).[ext], bootOnly
+ sbt-plugin-releases: http://scalasbt.artifactoryonline.com/scalasbt/sbt-plugin-releases, [organization]/[module]/(scala_[scalaVersion]/)(sbt_[sbtVersion]/)[revision]/[type]s/[artifact](-[classifier]).[ext]
+ maven-central
+ local
+EOF
##### git
gfxd() {
@@ -158,7 +172,7 @@ function st_stagingRepoClose() {
# the old version (on jenkins, and I don't want to upgrade for risk of breaking other builds) honors -sbt-dir
# the new version of sbt-extras ignores sbt-dir, so we pass it in as -Dsbt.global.base
# need to set sbt-dir to one that has the gpg.sbt plugin config
-sbtArgs="-no-colors -ivy $baseDir/ivy2 -Dsbt.override.build.repos=true -Dsbt.repository.config=$scriptsDir/repositories-scala-release -Dsbt.global.base=$HOME/.sbt/0.13 -sbt-dir $HOME/.sbt/0.13"
+sbtArgs="-no-colors -ivy $baseDir/ivy2 -Dsbt.override.build.repos=true -Dsbt.repository.config=$sbtRepositoryConfig -Dsbt.global.base=$HOME/.sbt/0.13 -sbt-dir $HOME/.sbt/0.13"
sbtBuild() {
echo "### sbtBuild: "$sbtCmd $sbtArgs "${scalaVersionTasks[@]}" "${publishTasks[@]}" "$@"
@@ -457,8 +471,8 @@ bootstrap() {
# in sabbus lingo, the resulting Scala build will be used as starr to build the released Scala compiler
ant -Dmaven.version.number=$SCALA_VER\
-Dremote.snapshot.repository=NOPE\
- -Dremote.release.repository=$privateRepo\
- -Drepository.credentials.id=$privateCred\
+ -Dremote.release.repository=$releaseTempRepoUrl\
+ -Drepository.credentials.id=$releaseTempRepoCred\
-Dscalac.args.optimise=-optimise\
-Ddocs.skip=1\
-Dlocker.skip=1\
@@ -471,7 +485,7 @@ bootstrap() {
# publish to our internal repo (so we can resolve the modules in the scala build below)
# we only need to build the modules necessary to build Scala itself
# since the version of locker and quick are the same
- publishTasks=('set credentials += Credentials(Path.userHome / ".credentials-private-repo")' "set every publishTo := Some(\"private-repo\" at \"$privateRepo\")")
+ publishTasks=('set credentials += Credentials(Path.userHome / ".credentials-private-repo")' "set every publishTo := Some(\"private-repo\" at \"$releaseTempRepoUrl\")")
buildTasks=($publishPrivateTask)
buildModules
@@ -496,14 +510,14 @@ bootstrap() {
# which is fully cross-versioned (for $SCALA_VER, the version we're releasing)
ant -Dstarr.version=$SCALA_VER\
-Dscala.full.version=$SCALA_VER\
- -Dextra.repo.url=$privateRepo\
+ -Dextra.repo.url=$releaseTempRepoUrl\
-Dmaven.version.suffix=$SCALA_VER_SUFFIX\
${updatedModuleVersions[@]} \
-Dupdate.versions=1\
-Dscaladoc.git.commit=$SCALADOC_SOURCE_LINKS_VER\
-Dremote.snapshot.repository=NOPE\
- -Dremote.release.repository=$privateRepo\
- -Drepository.credentials.id=$privateCred\
+ -Dremote.release.repository=$releaseTempRepoUrl\
+ -Drepository.credentials.id=$releaseTempRepoCred\
-Dscalac.args.optimise=-optimise\
$antBuildTask $publishPrivateTask
diff --git a/scripts/repositories-scala-release b/scripts/repositories-scala-release
deleted file mode 100644
index 00538a08ff..0000000000
--- a/scripts/repositories-scala-release
+++ /dev/null
@@ -1,7 +0,0 @@
-[repositories]
- plugins: http://dl.bintray.com/sbt/sbt-plugin-releases/, [organisation]/[module]/(scala_[scalaVersion]/)(sbt_[sbtVersion]/)[revision]/[type]s/[artifact](-[classifier]).[ext]
- private-repo: http://private-repo.typesafe.com/typesafe/scala-release-temp/
- typesafe-ivy-releases: http://repo.typesafe.com/typesafe/ivy-releases/, [organization]/[module]/[revision]/[type]s/[artifact](-[classifier]).[ext], bootOnly
- sbt-plugin-releases: http://scalasbt.artifactoryonline.com/scalasbt/sbt-plugin-releases, [organization]/[module]/(scala_[scalaVersion]/)(sbt_[sbtVersion]/)[revision]/[type]s/[artifact](-[classifier]).[ext]
- maven-central
- local \ No newline at end of file
diff --git a/src/compiler/scala/reflect/quasiquotes/Reifiers.scala b/src/compiler/scala/reflect/quasiquotes/Reifiers.scala
index 7c0e7dfbb8..e753c9787a 100644
--- a/src/compiler/scala/reflect/quasiquotes/Reifiers.scala
+++ b/src/compiler/scala/reflect/quasiquotes/Reifiers.scala
@@ -317,7 +317,7 @@ trait Reifiers { self: Quasiquotes =>
* Reification of non-trivial list is done in two steps:
*
* 1. split the list into groups where every placeholder is always
- * put in a group of it's own and all subsquent non-holeMap are
+ * put in a group of its own and all subsquent non-holeMap are
* grouped together; element is considered to be a placeholder if it's
* in the domain of the fill function;
*
diff --git a/src/compiler/scala/tools/nsc/PhaseAssembly.scala b/src/compiler/scala/tools/nsc/PhaseAssembly.scala
index e1cfa63960..4b32aab5ee 100644
--- a/src/compiler/scala/tools/nsc/PhaseAssembly.scala
+++ b/src/compiler/scala/tools/nsc/PhaseAssembly.scala
@@ -127,7 +127,7 @@ trait PhaseAssembly {
}
/* Find all edges in the given graph that are hard links. For each hard link we
- * need to check that its the only dependency. If not, then we will promote the
+ * need to check that it's the only dependency. If not, then we will promote the
* other dependencies down
*/
def validateAndEnforceHardlinks() {
diff --git a/src/compiler/scala/tools/nsc/Reporting.scala b/src/compiler/scala/tools/nsc/Reporting.scala
index 72a4b69536..4e7a527a5a 100644
--- a/src/compiler/scala/tools/nsc/Reporting.scala
+++ b/src/compiler/scala/tools/nsc/Reporting.scala
@@ -46,7 +46,7 @@ trait Reporting extends scala.reflect.internal.Reporting { self: ast.Positions w
private val _deprecationWarnings = new ConditionalWarning("deprecation", settings.deprecation)()
private val _uncheckedWarnings = new ConditionalWarning("unchecked", settings.unchecked)()
private val _featureWarnings = new ConditionalWarning("feature", settings.feature)()
- private val _inlinerWarnings = new ConditionalWarning("inliner", settings.YinlinerWarnings)(if (settings.isBCodeAskedFor) settings.YoptWarnings.name else settings.YinlinerWarnings.name)
+ private val _inlinerWarnings = new ConditionalWarning("inliner", settings.YinlinerWarnings)(if (settings.isBCodeActive) settings.YoptWarnings.name else settings.YinlinerWarnings.name)
private val _allConditionalWarnings = List(_deprecationWarnings, _uncheckedWarnings, _featureWarnings, _inlinerWarnings)
// TODO: remove in favor of the overload that takes a Symbol, give that argument a default (NoSymbol)
diff --git a/src/compiler/scala/tools/nsc/ast/parser/MarkupParsers.scala b/src/compiler/scala/tools/nsc/ast/parser/MarkupParsers.scala
index 96939e616c..52b8a51a79 100755
--- a/src/compiler/scala/tools/nsc/ast/parser/MarkupParsers.scala
+++ b/src/compiler/scala/tools/nsc/ast/parser/MarkupParsers.scala
@@ -6,6 +6,7 @@
package scala.tools.nsc
package ast.parser
+import scala.annotation.tailrec
import scala.collection.mutable
import mutable.{ Buffer, ArrayBuffer, ListBuffer }
import scala.util.control.ControlThrowable
@@ -172,20 +173,19 @@ trait MarkupParsers {
}
def appendText(pos: Position, ts: Buffer[Tree], txt: String): Unit = {
- def append(t: String) = ts append handle.text(pos, t)
-
- if (preserveWS) append(txt)
- else {
+ def append(text: String): Unit = {
+ val tree = handle.text(pos, text)
+ ts append tree
+ }
+ val clean = if (preserveWS) txt else {
val sb = new StringBuilder()
-
txt foreach { c =>
if (!isSpace(c)) sb append c
else if (sb.isEmpty || !isSpace(sb.last)) sb append ' '
}
-
- val trimmed = sb.toString.trim
- if (!trimmed.isEmpty) append(trimmed)
+ sb.toString.trim
}
+ if (!clean.isEmpty) append(clean)
}
/** adds entity/character to ts as side-effect
@@ -216,44 +216,75 @@ trait MarkupParsers {
if (xCheckEmbeddedBlock) ts append xEmbeddedExpr
else appendText(p, ts, xText)
- /** Returns true if it encounters an end tag (without consuming it),
- * appends trees to ts as side-effect.
+ /** At an open angle-bracket, detects an end tag
+ * or consumes CDATA, comment, PI or element.
+ * Trees are appended to `ts` as a side-effect.
+ * @return true if an end tag (without consuming it)
*/
- private def content_LT(ts: ArrayBuffer[Tree]): Boolean = {
- if (ch == '/')
- return true // end tag
-
- val toAppend = ch match {
- case '!' => nextch() ; if (ch =='[') xCharData else xComment // CDATA or Comment
- case '?' => nextch() ; xProcInstr // PI
- case _ => element // child node
+ private def content_LT(ts: ArrayBuffer[Tree]): Boolean =
+ (ch == '/') || {
+ val toAppend = ch match {
+ case '!' => nextch() ; if (ch =='[') xCharData else xComment // CDATA or Comment
+ case '?' => nextch() ; xProcInstr // PI
+ case _ => element // child node
+ }
+ ts append toAppend
+ false
}
- ts append toAppend
- false
- }
-
def content: Buffer[Tree] = {
val ts = new ArrayBuffer[Tree]
- while (true) {
- if (xEmbeddedBlock)
+ val coalescing = settings.XxmlSettings.isCoalescing
+ @tailrec def loopContent(): Unit =
+ if (xEmbeddedBlock) {
ts append xEmbeddedExpr
- else {
+ loopContent()
+ } else {
tmppos = o2p(curOffset)
ch match {
- // end tag, cdata, comment, pi or child node
- case '<' => nextch() ; if (content_LT(ts)) return ts
- // either the character '{' or an embedded scala block }
- case '{' => content_BRACE(tmppos, ts) // }
- // EntityRef or CharRef
- case '&' => content_AMP(ts)
- case SU => return ts
- // text content - here xEmbeddedBlock might be true
- case _ => appendText(tmppos, ts, xText)
+ case '<' => // end tag, cdata, comment, pi or child node
+ nextch()
+ if (!content_LT(ts)) loopContent()
+ case '{' => // } literal brace or embedded Scala block
+ content_BRACE(tmppos, ts)
+ loopContent()
+ case '&' => // EntityRef or CharRef
+ content_AMP(ts)
+ loopContent()
+ case SU => ()
+ case _ => // text content - here xEmbeddedBlock might be true
+ appendText(tmppos, ts, xText)
+ loopContent()
}
}
+ // merge text sections and strip attachments
+ def coalesce(): ArrayBuffer[Tree] = {
+ def copy() = {
+ val buf = new ArrayBuffer[Tree]
+ var acc = new StringBuilder
+ var pos: Position = NoPosition
+ def emit() = if (acc.nonEmpty) {
+ appendText(pos, buf, acc.toString)
+ acc.clear()
+ }
+ for (t <- ts)
+ t.attachments.get[handle.TextAttache] match {
+ case Some(ta) =>
+ if (acc.isEmpty) pos = ta.pos
+ acc append ta.text
+ case _ =>
+ emit()
+ buf += t
+ }
+ emit()
+ buf
+ }
+ val res = if (ts.count(_.hasAttachment[handle.TextAttache]) > 1) copy() else ts
+ for (t <- res) t.removeAttachment[handle.TextAttache]
+ res
}
- unreachable
+ loopContent()
+ if (coalescing) coalesce() else ts
}
/** '<' element ::= xmlTag1 '>' { xmlExpr | '{' simpleExpr '}' } ETag
@@ -289,20 +320,16 @@ trait MarkupParsers {
private def xText: String = {
assert(!xEmbeddedBlock, "internal error: encountered embedded block")
val buf = new StringBuilder
- def done = buf.toString
-
- while (ch != SU) {
- if (ch == '}') {
- if (charComingAfter(nextch()) == '}') nextch()
- else errorBraces()
- }
-
- buf append ch
- nextch()
- if (xCheckEmbeddedBlock || ch == '<' || ch == '&')
- return done
- }
- done
+ if (ch != SU)
+ do {
+ if (ch == '}') {
+ if (charComingAfter(nextch()) == '}') nextch()
+ else errorBraces()
+ }
+ buf append ch
+ nextch()
+ } while (!(ch == SU || xCheckEmbeddedBlock || ch == '<' || ch == '&'))
+ buf.toString
}
/** Some try/catch/finally logic used by xLiteral and xLiteralPattern. */
@@ -344,12 +371,12 @@ trait MarkupParsers {
tmppos = o2p(curOffset) // Iuli: added this line, as it seems content_LT uses tmppos when creating trees
content_LT(ts)
- // parse more XML ?
+ // parse more XML?
if (charComingAfter(xSpaceOpt()) == '<') {
do {
xSpaceOpt()
nextch()
- ts append element
+ content_LT(ts)
} while (charComingAfter(xSpaceOpt()) == '<')
handle.makeXMLseq(r2p(start, start, curOffset), ts)
}
diff --git a/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala b/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala
index 67e91ae857..4f195c2985 100644
--- a/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala
+++ b/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala
@@ -1259,7 +1259,7 @@ self =>
atPos(start) { Apply(t3, exprsBuf.toList) }
}
if (inPattern) stringCheese
- else withPlaceholders(stringCheese, isAny = true) // strinterpolator params are Any* by definition
+ else withPlaceholders(stringCheese, isAny = true) // string interpolator params are Any* by definition
}
/* ------------- NEW LINES ------------------------------------------------- */
diff --git a/src/compiler/scala/tools/nsc/ast/parser/SymbolicXMLBuilder.scala b/src/compiler/scala/tools/nsc/ast/parser/SymbolicXMLBuilder.scala
index d2a999cdec..67241ef639 100755
--- a/src/compiler/scala/tools/nsc/ast/parser/SymbolicXMLBuilder.scala
+++ b/src/compiler/scala/tools/nsc/ast/parser/SymbolicXMLBuilder.scala
@@ -36,6 +36,7 @@ abstract class SymbolicXMLBuilder(p: Parsers#Parser, preserveWS: Boolean) {
val _MetaData: NameType = "MetaData"
val _NamespaceBinding: NameType = "NamespaceBinding"
val _NodeBuffer: NameType = "NodeBuffer"
+ val _PCData: NameType = "PCData"
val _PrefixedAttribute: NameType = "PrefixedAttribute"
val _ProcInstr: NameType = "ProcInstr"
val _Text: NameType = "Text"
@@ -46,6 +47,7 @@ abstract class SymbolicXMLBuilder(p: Parsers#Parser, preserveWS: Boolean) {
private object xmlterms extends TermNames {
val _Null: NameType = "Null"
val __Elem: NameType = "Elem"
+ val _PCData: NameType = "PCData"
val __Text: NameType = "Text"
val _buf: NameType = "$buf"
val _md: NameType = "$md"
@@ -55,10 +57,15 @@ abstract class SymbolicXMLBuilder(p: Parsers#Parser, preserveWS: Boolean) {
val _xml: NameType = "xml"
}
- import xmltypes.{_Comment, _Elem, _EntityRef, _Group, _MetaData, _NamespaceBinding, _NodeBuffer,
- _PrefixedAttribute, _ProcInstr, _Text, _Unparsed, _UnprefixedAttribute}
+ import xmltypes.{
+ _Comment, _Elem, _EntityRef, _Group, _MetaData, _NamespaceBinding, _NodeBuffer,
+ _PCData, _PrefixedAttribute, _ProcInstr, _Text, _Unparsed, _UnprefixedAttribute
+ }
+
+ import xmlterms.{ _Null, __Elem, __Text, _buf, _md, _plus, _scope, _tmpscope, _xml }
- import xmlterms.{_Null, __Elem, __Text, _buf, _md, _plus, _scope, _tmpscope, _xml}
+ /** Attachment for trees deriving from text nodes (Text, CData, entities). Used for coalescing. */
+ case class TextAttache(pos: Position, text: String)
// convenience methods
private def LL[A](x: A*): List[List[A]] = List(List(x:_*))
@@ -108,16 +115,21 @@ abstract class SymbolicXMLBuilder(p: Parsers#Parser, preserveWS: Boolean) {
final def entityRef(pos: Position, n: String) =
atPos(pos)( New(_scala_xml_EntityRef, LL(const(n))) )
+ private def coalescing = settings.XxmlSettings.isCoalescing
+
// create scala.xml.Text here <: scala.xml.Node
final def text(pos: Position, txt: String): Tree = atPos(pos) {
- if (isPattern) makeTextPat(const(txt))
- else makeText1(const(txt))
+ val t = if (isPattern) makeTextPat(const(txt)) else makeText1(const(txt))
+ if (coalescing) t updateAttachment TextAttache(pos, txt) else t
}
def makeTextPat(txt: Tree) = Apply(_scala_xml__Text, List(txt))
def makeText1(txt: Tree) = New(_scala_xml_Text, LL(txt))
def comment(pos: Position, text: String) = atPos(pos)( Comment(const(text)) )
- def charData(pos: Position, txt: String) = atPos(pos)( makeText1(const(txt)) )
+ def charData(pos: Position, txt: String) = if (coalescing) text(pos, txt) else atPos(pos) {
+ if (isPattern) Apply(_scala_xml(xmlterms._PCData), List(const(txt)))
+ else New(_scala_xml(_PCData), LL(const(txt)))
+ }
def procInstr(pos: Position, target: String, txt: String) =
atPos(pos)( ProcInstr(const(target), const(txt)) )
diff --git a/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala b/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala
index 185fd93501..137954b52d 100644
--- a/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala
+++ b/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala
@@ -883,7 +883,12 @@ abstract class GenICode extends SubComponent {
case None =>
val saved = settings.uniqid
settings.uniqid.value = true
- try abort(s"symbol $sym does not exist in ${ctx.method}, which contains locals ${ctx.method.locals.mkString(",")}")
+ try {
+ val methodCode = unit.body.collect { case dd: DefDef
+ if dd.symbol == ctx.method.symbol => showCode(dd);
+ }.headOption.getOrElse("<unknown>")
+ abort(s"symbol $sym does not exist in ${ctx.method}, which contains locals ${ctx.method.locals.mkString(",")}. \nMethod code: $methodCode")
+ }
finally settings.uniqid.value = saved
}
}
diff --git a/src/compiler/scala/tools/nsc/backend/icode/ICodeCheckers.scala b/src/compiler/scala/tools/nsc/backend/icode/ICodeCheckers.scala
index 0cdf629ce1..843648282b 100644
--- a/src/compiler/scala/tools/nsc/backend/icode/ICodeCheckers.scala
+++ b/src/compiler/scala/tools/nsc/backend/icode/ICodeCheckers.scala
@@ -109,7 +109,7 @@ abstract class ICodeCheckers {
/** Only called when m1 < m2, so already known that (m1 ne m2).
*/
- private def isConfict(m1: IMember, m2: IMember, canOverload: Boolean) = (
+ private def isConflict(m1: IMember, m2: IMember, canOverload: Boolean) = (
(m1.symbol.name == m2.symbol.name) &&
(!canOverload || (m1.symbol.tpe =:= m2.symbol.tpe))
)
@@ -119,11 +119,11 @@ abstract class ICodeCheckers {
clasz = cls
for (f1 <- cls.fields ; f2 <- cls.fields ; if f1 < f2)
- if (isConfict(f1, f2, canOverload = false))
+ if (isConflict(f1, f2, canOverload = false))
icodeError("Repetitive field name: " + f1.symbol.fullName)
for (m1 <- cls.methods ; m2 <- cls.methods ; if m1 < m2)
- if (isConfict(m1, m2, canOverload = true))
+ if (isConflict(m1, m2, canOverload = true))
icodeError("Repetitive method: " + m1.symbol.fullName)
clasz.methods foreach check
@@ -471,7 +471,7 @@ abstract class ICodeCheckers {
pushStack(local.kind)
case LOAD_FIELD(field, isStatic) =>
- // the symbol's owner should contain it's field, but
+ // the symbol's owner should contain its field, but
// this is already checked by the type checker, no need
// to redo that here
if (isStatic) ()
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 b0ad5bdaf9..058b6a161d 100644
--- a/src/compiler/scala/tools/nsc/backend/icode/analysis/TypeFlowAnalysis.scala
+++ b/src/compiler/scala/tools/nsc/backend/icode/analysis/TypeFlowAnalysis.scala
@@ -572,7 +572,7 @@ abstract class TypeFlowAnalysis {
- `inlined` : These blocks were spliced into the method's CFG as part of inlining. Being new blocks, they haven't been visited yet by the typeflow analysis.
- - `staleIn` : These blocks are what `doInline()` calls `afterBlock`s, ie the new home for instructions that previously appearead
+ - `staleIn` : These blocks are what `doInline()` calls `afterBlock`s, ie the new home for instructions that previously appeared
after a callsite in a `staleOut` block.
Based on the above information, we have to bring up-to-date the caches that `forwardAnalysis` and `blockTransfer` use to skip blocks and instructions.
diff --git a/src/compiler/scala/tools/nsc/backend/jvm/BCodeAsmCommon.scala b/src/compiler/scala/tools/nsc/backend/jvm/BCodeAsmCommon.scala
index 162da4236a..eadc404bee 100644
--- a/src/compiler/scala/tools/nsc/backend/jvm/BCodeAsmCommon.scala
+++ b/src/compiler/scala/tools/nsc/backend/jvm/BCodeAsmCommon.scala
@@ -329,10 +329,12 @@ final class BCodeAsmCommon[G <: Global](val global: G) {
* Build the [[InlineInfo]] for a class symbol.
*/
def buildInlineInfoFromClassSymbol(classSym: Symbol, classSymToInternalName: Symbol => InternalName, methodSymToDescriptor: Symbol => String): InlineInfo = {
- val selfType = {
+ val traitSelfType = if (classSym.isTrait && !classSym.isImplClass) {
// The mixin phase uses typeOfThis for the self parameter in implementation class methods.
val selfSym = classSym.typeOfThis.typeSymbol
if (selfSym != classSym) Some(classSymToInternalName(selfSym)) else None
+ } else {
+ None
}
val isEffectivelyFinal = classSym.isEffectivelyFinal
@@ -394,6 +396,6 @@ final class BCodeAsmCommon[G <: Global](val global: G) {
}
}).toMap
- InlineInfo(selfType, isEffectivelyFinal, methodInlineInfos, warning)
+ InlineInfo(traitSelfType, isEffectivelyFinal, methodInlineInfos, warning)
}
}
diff --git a/src/compiler/scala/tools/nsc/backend/jvm/BTypes.scala b/src/compiler/scala/tools/nsc/backend/jvm/BTypes.scala
index d8a17e975e..e61190bf3a 100644
--- a/src/compiler/scala/tools/nsc/backend/jvm/BTypes.scala
+++ b/src/compiler/scala/tools/nsc/backend/jvm/BTypes.scala
@@ -11,11 +11,12 @@ import scala.collection.concurrent.TrieMap
import scala.reflect.internal.util.Position
import scala.tools.asm
import asm.Opcodes
-import scala.tools.asm.tree.{MethodInsnNode, InnerClassNode, ClassNode}
+import scala.tools.asm.tree.{MethodNode, MethodInsnNode, InnerClassNode, ClassNode}
import scala.tools.nsc.backend.jvm.BTypes.{InlineInfo, MethodInlineInfo}
import scala.tools.nsc.backend.jvm.BackendReporting._
import scala.tools.nsc.backend.jvm.opt._
import scala.collection.convert.decorateAsScala._
+import scala.tools.nsc.settings.ScalaSettings
/**
* The BTypes component defines The BType class hierarchy. A BType stores all type information
@@ -39,6 +40,8 @@ abstract class BTypes {
*/
val byteCodeRepository: ByteCodeRepository
+ val localOpt: LocalOpt[this.type]
+
val inliner: Inliner[this.type]
val callGraph: CallGraph[this.type]
@@ -48,14 +51,9 @@ abstract class BTypes {
// Allows to define per-run caches here and in the CallGraph component, which don't have a global
def recordPerRunCache[T <: collection.generic.Clearable](cache: T): T
- // When building the call graph, we need to know if global inlining is allowed (the component doesn't have a global)
- def inlineGlobalEnabled: Boolean
-
- // When the inliner is not enabled, there's no point in adding InlineInfos to all ClassBTypes
- def inlinerEnabled: Boolean
+ // Allows access to the compiler settings for backend components that don't have a global in scope
+ def compilerSettings: ScalaSettings
- // Settings that define what kind of optimizer warnings are emitted.
- def warnSettings: WarnSettings
/**
* A map from internal names to ClassBTypes. Every ClassBType is added to this map on its
@@ -83,6 +81,18 @@ abstract class BTypes {
val javaDefinedClasses: collection.mutable.Set[InternalName] = recordPerRunCache(collection.mutable.Set.empty)
/**
+ * Cache, contains methods whose unreachable instructions are eliminated.
+ *
+ * The ASM Analyzer class does not compute any frame information for unreachable instructions.
+ * Transformations that use an analyzer (including inlining) therefore require unreachable code
+ * to be eliminated.
+ *
+ * This cache allows running dead code elimination whenever an analyzer is used. If the method
+ * is already optimized, DCE can return early.
+ */
+ val unreachableCodeEliminated: collection.mutable.Set[MethodNode] = recordPerRunCache(collection.mutable.Set.empty)
+
+ /**
* Obtain the BType for a type descriptor or internal name. For class descriptors, the ClassBType
* is constructed by parsing the corresponding classfile.
*
@@ -229,7 +239,7 @@ abstract class BTypes {
// The InlineInfo is built from the classfile (not from the symbol) for all classes that are NOT
// being compiled. For those classes, the info is only needed if the inliner is enabled, othewise
// we can save the memory.
- if (!inlinerEnabled) BTypes.EmptyInlineInfo
+ if (!compilerSettings.YoptInlinerEnabled) BTypes.EmptyInlineInfo
else fromClassfileAttribute getOrElse fromClassfileWithoutAttribute
}
@@ -305,7 +315,7 @@ abstract class BTypes {
case ArrayBType(component) =>
if (other == ObjectReference || other == jlCloneableReference || other == jioSerializableReference) true
else other match {
- case ArrayBType(otherComponoent) => component.conformsTo(otherComponoent).orThrow
+ case ArrayBType(otherComponent) => component.conformsTo(otherComponent).orThrow
case _ => false
}
diff --git a/src/compiler/scala/tools/nsc/backend/jvm/BTypesFromSymbols.scala b/src/compiler/scala/tools/nsc/backend/jvm/BTypesFromSymbols.scala
index eeb6ed24a2..1b9fd5e298 100644
--- a/src/compiler/scala/tools/nsc/backend/jvm/BTypesFromSymbols.scala
+++ b/src/compiler/scala/tools/nsc/backend/jvm/BTypesFromSymbols.scala
@@ -7,9 +7,10 @@ package scala.tools.nsc
package backend.jvm
import scala.tools.asm
-import scala.tools.nsc.backend.jvm.opt.{CallGraph, Inliner, ByteCodeRepository}
+import scala.tools.nsc.backend.jvm.opt.{LocalOpt, CallGraph, Inliner, ByteCodeRepository}
import scala.tools.nsc.backend.jvm.BTypes.{InlineInfo, MethodInlineInfo, InternalName}
import BackendReporting._
+import scala.tools.nsc.settings.ScalaSettings
/**
* This class mainly contains the method classBTypeFromSymbol, which extracts the necessary
@@ -37,6 +38,8 @@ class BTypesFromSymbols[G <: Global](val global: G) extends BTypes {
val byteCodeRepository = new ByteCodeRepository(global.classPath, javaDefinedClasses, recordPerRunCache(collection.concurrent.TrieMap.empty))
+ val localOpt: LocalOpt[this.type] = new LocalOpt(this)
+
val inliner: Inliner[this.type] = new Inliner(this)
val callGraph: CallGraph[this.type] = new CallGraph(this)
@@ -49,19 +52,7 @@ class BTypesFromSymbols[G <: Global](val global: G) extends BTypes {
def recordPerRunCache[T <: collection.generic.Clearable](cache: T): T = perRunCaches.recordCache(cache)
- def inlineGlobalEnabled: Boolean = settings.YoptInlineGlobal
-
- def inlinerEnabled: Boolean = settings.YoptInlinerEnabled
-
- def warnSettings: WarnSettings = {
- val c = settings.YoptWarningsChoices
- // cannot extract settings.YoptWarnings into a local val due to some dependent typing issue.
- WarnSettings(
- !settings.YoptWarnings.isSetByUser || settings.YoptWarnings.contains(c.atInlineFailedSummary.name) || settings.YoptWarnings.contains(c.atInlineFailed.name),
- settings.YoptWarnings.contains(c.noInlineMixed.name),
- settings.YoptWarnings.contains(c.noInlineMissingBytecode.name),
- settings.YoptWarnings.contains(c.noInlineMissingScalaInlineInfoAttr.name))
- }
+ def compilerSettings: ScalaSettings = settings
// helpers that need access to global.
// TODO @lry create a separate component, they don't belong to BTypesFromSymbols
@@ -418,8 +409,8 @@ class BTypesFromSymbols[G <: Global](val global: G) extends BTypes {
// phase travel required, see implementation of `compiles`. for nested classes, it checks if the
// enclosingTopLevelClass is being compiled. after flatten, all classes are considered top-level,
// so `compiles` would return `false`.
- if (exitingPickler(currentRun.compiles(classSym))) buildFromSymbol // InlineInfo required for classes being compiled, we have to create the classfile attribute
- else if (!inlinerEnabled) BTypes.EmptyInlineInfo // For other classes, we need the InlineInfo only inf the inliner is enabled.
+ if (exitingPickler(currentRun.compiles(classSym))) buildFromSymbol // InlineInfo required for classes being compiled, we have to create the classfile attribute
+ else if (!compilerSettings.YoptInlinerEnabled) BTypes.EmptyInlineInfo // For other classes, we need the InlineInfo only inf the inliner is enabled.
else {
// For classes not being compiled, the InlineInfo is read from the classfile attribute. This
// fixes an issue with mixed-in methods: the mixin phase enters mixin methods only to class
diff --git a/src/compiler/scala/tools/nsc/backend/jvm/BackendReporting.scala b/src/compiler/scala/tools/nsc/backend/jvm/BackendReporting.scala
index a06fb4bab8..d641f708d2 100644
--- a/src/compiler/scala/tools/nsc/backend/jvm/BackendReporting.scala
+++ b/src/compiler/scala/tools/nsc/backend/jvm/BackendReporting.scala
@@ -4,6 +4,8 @@ package backend.jvm
import scala.tools.asm.tree.{AbstractInsnNode, MethodNode}
import scala.tools.nsc.backend.jvm.BTypes.InternalName
import scala.reflect.internal.util.Position
+import scala.tools.nsc.settings.ScalaSettings
+import scala.util.control.ControlThrowable
/**
* Interface for emitting inline warnings. The interface is required because the implementation
@@ -73,24 +75,22 @@ object BackendReporting {
}
}
- case class Invalid[A](e: A) extends Exception
+ case class Invalid[A](e: A) extends ControlThrowable
/**
* See documentation of orThrow above.
*/
def tryEither[A, B](op: => Either[A, B]): Either[A, B] = try { op } catch { case Invalid(e) => Left(e.asInstanceOf[A]) }
- final case class WarnSettings(atInlineFailed: Boolean, noInlineMixed: Boolean, noInlineMissingBytecode: Boolean, noInlineMissingScalaInlineInfoAttr: Boolean)
-
sealed trait OptimizerWarning {
- def emitWarning(settings: WarnSettings): Boolean
+ def emitWarning(settings: ScalaSettings): Boolean
}
// Method filter in RightBiasedEither requires an implicit empty value. Taking the value here
// in scope allows for-comprehensions that desugar into filter calls (for example when using a
// tuple de-constructor).
implicit object emptyOptimizerWarning extends OptimizerWarning {
- def emitWarning(settings: WarnSettings): Boolean = false
+ def emitWarning(settings: ScalaSettings): Boolean = false
}
sealed trait MissingBytecodeWarning extends OptimizerWarning {
@@ -112,17 +112,17 @@ object BackendReporting {
missingClass.map(c => s" Reason:\n$c").getOrElse("")
}
- def emitWarning(settings: WarnSettings): Boolean = this match {
+ def emitWarning(settings: ScalaSettings): Boolean = this match {
case ClassNotFound(_, javaDefined) =>
- if (javaDefined) settings.noInlineMixed
- else settings.noInlineMissingBytecode
+ if (javaDefined) settings.YoptWarningNoInlineMixed
+ else settings.YoptWarningNoInlineMissingBytecode
case m @ MethodNotFound(_, _, _, missing) =>
if (m.isArrayMethod) false
- else settings.noInlineMissingBytecode || missing.exists(_.emitWarning(settings))
+ else settings.YoptWarningNoInlineMissingBytecode || missing.exists(_.emitWarning(settings))
case FieldNotFound(_, _, _, missing) =>
- settings.noInlineMissingBytecode || missing.exists(_.emitWarning(settings))
+ settings.YoptWarningNoInlineMissingBytecode || missing.exists(_.emitWarning(settings))
}
}
@@ -141,9 +141,9 @@ object BackendReporting {
s"Failed to get the type of class symbol $classFullName due to SI-9111."
}
- def emitWarning(settings: WarnSettings): Boolean = this match {
+ def emitWarning(settings: ScalaSettings): Boolean = this match {
case NoClassBTypeInfoMissingBytecode(cause) => cause.emitWarning(settings)
- case NoClassBTypeInfoClassSymbolInfoFailedSI9111(_) => settings.noInlineMissingBytecode
+ case NoClassBTypeInfoClassSymbolInfoFailedSI9111(_) => settings.YoptWarningNoInlineMissingBytecode
}
}
@@ -175,11 +175,11 @@ object BackendReporting {
cause.toString
}
- def emitWarning(settings: WarnSettings): Boolean = this match {
+ def emitWarning(settings: ScalaSettings): Boolean = this match {
case MethodInlineInfoIncomplete(_, _, _, cause) => cause.emitWarning(settings)
case MethodInlineInfoMissing(_, _, _, Some(cause)) => cause.emitWarning(settings)
- case MethodInlineInfoMissing(_, _, _, None) => settings.noInlineMissingBytecode
+ case MethodInlineInfoMissing(_, _, _, None) => settings.YoptWarningNoInlineMissingBytecode
case MethodInlineInfoError(_, _, _, cause) => cause.emitWarning(settings)
@@ -214,11 +214,21 @@ object BackendReporting {
case SynchronizedMethod(_, _, _) =>
s"Method $calleeMethodSig cannot be inlined because it is synchronized."
+
+ case StrictfpMismatch(_, _, _, callsiteClass, callsiteName, callsiteDesc) =>
+ s"""The callsite method ${BackendReporting.methodSignature(callsiteClass, callsiteName, callsiteDesc)}
+ |does not have the same strictfp mode as the callee $calleeMethodSig.
+ """.stripMargin
+
+ case ResultingMethodTooLarge(_, _, _, callsiteClass, callsiteName, callsiteDesc) =>
+ s"""The size of the callsite method ${BackendReporting.methodSignature(callsiteClass, callsiteName, callsiteDesc)}
+ |would exceed the JVM method size limit after inlining $calleeMethodSig.
+ """.stripMargin
}
- def emitWarning(settings: WarnSettings): Boolean = this match {
- case _: IllegalAccessInstruction | _: MethodWithHandlerCalledOnNonEmptyStack | _: SynchronizedMethod =>
- settings.atInlineFailed
+ def emitWarning(settings: ScalaSettings): Boolean = this match {
+ case _: IllegalAccessInstruction | _: MethodWithHandlerCalledOnNonEmptyStack | _: SynchronizedMethod | _: StrictfpMismatch | _: ResultingMethodTooLarge =>
+ settings.YoptWarningEmitAtInlineFailed
case IllegalAccessCheckFailed(_, _, _, _, _, cause) =>
cause.emitWarning(settings)
@@ -231,6 +241,10 @@ object BackendReporting {
case class MethodWithHandlerCalledOnNonEmptyStack(calleeDeclarationClass: InternalName, name: String, descriptor: String,
callsiteClass: InternalName, callsiteName: String, callsiteDesc: String) extends CannotInlineWarning
case class SynchronizedMethod(calleeDeclarationClass: InternalName, name: String, descriptor: String) extends CannotInlineWarning
+ case class StrictfpMismatch(calleeDeclarationClass: InternalName, name: String, descriptor: String,
+ callsiteClass: InternalName, callsiteName: String, callsiteDesc: String) extends CannotInlineWarning
+ case class ResultingMethodTooLarge(calleeDeclarationClass: InternalName, name: String, descriptor: String,
+ callsiteClass: InternalName, callsiteName: String, callsiteDesc: String) extends CannotInlineWarning
/**
* Used in the InlineInfo of a ClassBType, when some issue occurred obtaining the inline information.
@@ -250,11 +264,11 @@ object BackendReporting {
s"Cannot read ScalaInlineInfo version $version in classfile $internalName. Use a more recent compiler."
}
- def emitWarning(settings: WarnSettings): Boolean = this match {
- case NoInlineInfoAttribute(_) => settings.noInlineMissingScalaInlineInfoAttr
+ def emitWarning(settings: ScalaSettings): Boolean = this match {
+ case NoInlineInfoAttribute(_) => settings.YoptWarningNoInlineMissingScalaInlineInfoAttr
case ClassNotFoundWhenBuildingInlineInfoFromSymbol(cause) => cause.emitWarning(settings)
- case ClassSymbolInfoFailureSI9111(_) => settings.noInlineMissingBytecode
- case UnknownScalaInlineInfoVersion(_, _) => settings.noInlineMissingScalaInlineInfoAttr
+ case ClassSymbolInfoFailureSI9111(_) => settings.YoptWarningNoInlineMissingBytecode
+ case UnknownScalaInlineInfoVersion(_, _) => settings.YoptWarningNoInlineMissingScalaInlineInfoAttr
}
}
diff --git a/src/compiler/scala/tools/nsc/backend/jvm/GenBCode.scala b/src/compiler/scala/tools/nsc/backend/jvm/GenBCode.scala
index be1595dc29..c6ee36d7b2 100644
--- a/src/compiler/scala/tools/nsc/backend/jvm/GenBCode.scala
+++ b/src/compiler/scala/tools/nsc/backend/jvm/GenBCode.scala
@@ -14,7 +14,6 @@ import scala.reflect.internal.util.Statistics
import scala.tools.asm
import scala.tools.asm.tree.ClassNode
-import scala.tools.nsc.backend.jvm.opt.LocalOpt
/*
* Prepare in-memory representations of classfiles using the ASM Tree API, and serialize them to disk.
@@ -215,17 +214,12 @@ abstract class GenBCode extends BCodeSyncAndTry {
* - converting the plain ClassNode to byte array and placing it on queue-3
*/
class Worker2 {
- lazy val localOpt = new LocalOpt(settings)
-
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) {
- localOpt.minimalRemoveUnreachableCode(plain)
- callGraph.addClass(plain)
- }
+ if (plain != null) callGraph.addClass(plain)
}
bTypes.inliner.runInliner()
}
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 14e8cccc60..201ab15177 100644
--- a/src/compiler/scala/tools/nsc/backend/jvm/opt/BytecodeUtils.scala
+++ b/src/compiler/scala/tools/nsc/backend/jvm/opt/BytecodeUtils.scala
@@ -10,6 +10,7 @@ package opt
import scala.annotation.{tailrec, switch}
import scala.collection.mutable
import scala.reflect.internal.util.Collections._
+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._
@@ -21,6 +22,12 @@ import scala.tools.nsc.backend.jvm.BTypes._
object BytecodeUtils {
+ // http://docs.oracle.com/javase/specs/jvms/se7/html/jvms-4.html#jvms-4.9.1
+ final val maxJVMMethodSize = 65535
+
+ // 5% margin, more than enough for the instructions added by the inliner (store / load args, null check for instance methods)
+ final val maxMethodSizeAfterInline = maxJVMMethodSize - (maxJVMMethodSize / 20)
+
object Goto {
def unapply(instruction: AbstractInsnNode): Option[JumpInsnNode] = {
if (instruction.getOpcode == Opcodes.GOTO) Some(instruction.asInstanceOf[JumpInsnNode])
@@ -83,10 +90,14 @@ object BytecodeUtils {
def isSynchronizedMethod(methodNode: MethodNode): Boolean = (methodNode.access & Opcodes.ACC_SYNCHRONIZED) != 0
+ def isNativeMethod(methodNode: MethodNode): Boolean = (methodNode.access & Opcodes.ACC_NATIVE) != 0
+
def isFinalClass(classNode: ClassNode): Boolean = (classNode.access & Opcodes.ACC_FINAL) != 0
def isFinalMethod(methodNode: MethodNode): Boolean = (methodNode.access & (Opcodes.ACC_FINAL | Opcodes.ACC_PRIVATE | Opcodes.ACC_STATIC)) != 0
+ def isStrictfpMethod(methodNode: MethodNode): Boolean = (methodNode.access & Opcodes.ACC_STRICT) != 0
+
def nextExecutableInstruction(instruction: AbstractInsnNode, alsoKeep: AbstractInsnNode => Boolean = Set()): Option[AbstractInsnNode] = {
var result = instruction
do { result = result.getNext }
@@ -215,7 +226,7 @@ object BytecodeUtils {
* to create a separate visitor for computing those values, duplicating the functionality from the
* MethodWriter.
*/
- def computeMaxLocalsMaxStack(method: MethodNode) {
+ def computeMaxLocalsMaxStack(method: MethodNode): Unit = {
val cw = new ClassWriter(ClassWriter.COMPUTE_MAXS)
val excs = method.exceptions.asScala.toArray
val mw = cw.visitMethod(method.access, method.name, method.desc, method.signature, excs).asInstanceOf[MethodWriter]
@@ -224,6 +235,21 @@ object BytecodeUtils {
method.maxStack = mw.getMaxStack
}
+ def codeSizeOKForInlining(caller: MethodNode, callee: MethodNode): Boolean = {
+ // Looking at the implementation of CodeSizeEvaluator, all instructions except tableswitch and
+ // lookupswitch are <= 8 bytes. These should be rare enough for 8 to be an OK rough upper bound.
+ def roughUpperBound(methodNode: MethodNode): Int = methodNode.instructions.size * 8
+
+ def maxSize(methodNode: MethodNode): Int = {
+ val eval = new CodeSizeEvaluator(null)
+ methodNode.accept(eval)
+ eval.getMaxSize
+ }
+
+ (roughUpperBound(caller) + roughUpperBound(callee) > maxMethodSizeAfterInline) &&
+ (maxSize(caller) + maxSize(callee) > maxMethodSizeAfterInline)
+ }
+
def removeLineNumberNodes(classNode: ClassNode): Unit = {
for (m <- classNode.methods.asScala) removeLineNumberNodes(m.instructions)
}
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 47d32c94cb..028f0f8fa6 100644
--- a/src/compiler/scala/tools/nsc/backend/jvm/opt/CallGraph.scala
+++ b/src/compiler/scala/tools/nsc/backend/jvm/opt/CallGraph.scala
@@ -43,14 +43,14 @@ class CallGraph[BT <: BTypes](val btypes: BT) {
// callee, we only check there for the methodInlineInfo, we should find it there.
calleeDeclarationClassBType.info.orThrow.inlineInfo.methodInfos.get(methodSignature) match {
case Some(methodInlineInfo) =>
- val canInlineFromSource = inlineGlobalEnabled || calleeSource == CompilationUnit
+ val canInlineFromSource = compilerSettings.YoptInlineGlobal || calleeSource == CompilationUnit
val isAbstract = BytecodeUtils.isAbstractMethod(calleeMethodNode)
// (1) A non-final method can be safe to inline if the receiver type is a final subclass. Example:
// class A { @inline def f = 1 }; object B extends A; B.f // can be inlined
//
- // TODO: type analysis can render more calls statically resolved. Example˜∫
+ // TODO: type analysis can render more calls statically resolved. Example:
// new A.f // can be inlined, the receiver type is known to be exactly A.
val isStaticallyResolved: Boolean = {
methodInlineInfo.effectivelyFinal ||
@@ -68,8 +68,13 @@ class CallGraph[BT <: BTypes](val btypes: BT) {
// (2) Final trait methods can be rewritten from the interface to the static implementation
// method to enable inlining.
CallsiteInfo(
- safeToInline = canInlineFromSource && isStaticallyResolved && !isAbstract, // (1)
- safeToRewrite = canInlineFromSource && isRewritableTraitCall, // (2)
+ safeToInline =
+ canInlineFromSource &&
+ isStaticallyResolved && // (1)
+ !isAbstract &&
+ !BytecodeUtils.isConstructor(calleeMethodNode) &&
+ !BytecodeUtils.isNativeMethod(calleeMethodNode),
+ safeToRewrite = canInlineFromSource && isRewritableTraitCall, // (2)
annotatedInline = methodInlineInfo.annotatedInline,
annotatedNoInline = methodInlineInfo.annotatedNoInline,
warning = warning)
@@ -92,6 +97,7 @@ class CallGraph[BT <: BTypes](val btypes: BT) {
// TODO: for now we run a basic analyzer to get the stack height at the call site.
// once we run a more elaborate analyzer (types, nullness), we can get the stack height out of there.
+ localOpt.minimalRemoveUnreachableCode(methodNode, definingClass.internalName)
val analyzer = new AsmAnalyzer(methodNode, definingClass.internalName)
methodNode.instructions.iterator.asScala.collect({
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 e14e57d3ab..ac5c9ce2e6 100644
--- a/src/compiler/scala/tools/nsc/backend/jvm/opt/Inliner.scala
+++ b/src/compiler/scala/tools/nsc/backend/jvm/opt/Inliner.scala
@@ -16,7 +16,7 @@ import scala.collection.convert.decorateAsJava._
import AsmUtils._
import BytecodeUtils._
import collection.mutable
-import scala.tools.asm.tree.analysis.{SourceInterpreter, Analyzer}
+import scala.tools.asm.tree.analysis.SourceInterpreter
import BackendReporting._
import scala.tools.nsc.backend.jvm.BTypes.InternalName
@@ -24,21 +24,39 @@ class Inliner[BT <: BTypes](val btypes: BT) {
import btypes._
import callGraph._
+ def eliminateUnreachableCodeAndUpdateCallGraph(methodNode: MethodNode, definingClass: InternalName): Unit = {
+ localOpt.minimalRemoveUnreachableCode(methodNode, definingClass) foreach {
+ case invocation: MethodInsnNode => callGraph.callsites.remove(invocation)
+ case _ =>
+ }
+ }
+
def runInliner(): Unit = {
rewriteFinalTraitMethodInvocations()
for (request <- collectAndOrderInlineRequests) {
val Right(callee) = request.callee // collectAndOrderInlineRequests returns callsites with a known callee
- val r = inline(request.callsiteInstruction, request.callsiteStackHeight, request.callsiteMethod, request.callsiteClass,
- callee.callee, callee.calleeDeclarationClass,
- receiverKnownNotNull = false, keepLineNumbers = false)
-
- for (warning <- r) {
- if ((callee.annotatedInline && btypes.warnSettings.atInlineFailed) || warning.emitWarning(warnSettings)) {
- val annotWarn = if (callee.annotatedInline) " is annotated @inline but" else ""
- val msg = s"${BackendReporting.methodSignature(callee.calleeDeclarationClass.internalName, callee.callee)}$annotWarn could not be inlined:\n$warning"
- backendReporting.inlinerWarning(request.callsitePosition, msg)
+ // Inlining a method can create unreachable code. Example:
+ // def f = throw e
+ // def g = f; println() // println is unreachable after inlining f
+ // If we have an inline request for a call to g, and f has been already inlined into g, we
+ // need to run DCE before inlining g.
+ eliminateUnreachableCodeAndUpdateCallGraph(callee.callee, callee.calleeDeclarationClass.internalName)
+
+ // DCE above removes unreachable callsites from the call graph. If the inlining request denotes
+ // such an eliminated callsite, do nothing.
+ if (callGraph.callsites contains request.callsiteInstruction) {
+ val r = inline(request.callsiteInstruction, request.callsiteStackHeight, request.callsiteMethod, request.callsiteClass,
+ callee.callee, callee.calleeDeclarationClass,
+ receiverKnownNotNull = false, keepLineNumbers = false)
+
+ for (warning <- r) {
+ if ((callee.annotatedInline && btypes.compilerSettings.YoptWarningEmitAtInlineFailed) || warning.emitWarning(compilerSettings)) {
+ val annotWarn = if (callee.annotatedInline) " is annotated @inline but" else ""
+ val msg = s"${BackendReporting.methodSignature(callee.calleeDeclarationClass.internalName, callee.callee)}$annotWarn could not be inlined:\n$warning"
+ backendReporting.inlinerWarning(request.callsitePosition, msg)
+ }
}
}
}
@@ -75,7 +93,7 @@ class Inliner[BT <: BTypes](val btypes: BT) {
val res = doInlineCallsite(callsite)
if (!res) {
- if (annotatedInline && btypes.warnSettings.atInlineFailed) {
+ if (annotatedInline && btypes.compilerSettings.YoptWarningEmitAtInlineFailed) {
// if the callsite is annotated @inline, we report an inline warning even if the underlying
// reason is, for example, mixed compilation (which has a separate -Yopt-warning flag).
def initMsg = s"${BackendReporting.methodSignature(calleeDeclClass.internalName, callee)} is annotated @inline but cannot be inlined"
@@ -86,7 +104,7 @@ class Inliner[BT <: BTypes](val btypes: BT) {
backendReporting.inlinerWarning(pos, s"$initMsg: the method is not final and may be overridden." + warnMsg)
else
backendReporting.inlinerWarning(pos, s"$initMsg." + warnMsg)
- } else if (warning.isDefined && warning.get.emitWarning(warnSettings)) {
+ } else if (warning.isDefined && warning.get.emitWarning(compilerSettings)) {
// when annotatedInline is false, and there is some warning, the callsite metadata is possibly incomplete.
backendReporting.inlinerWarning(pos, s"there was a problem determining if method ${callee.name} can be inlined: \n"+ warning.get)
}
@@ -95,7 +113,7 @@ class Inliner[BT <: BTypes](val btypes: BT) {
res
case Callsite(ins, _, _, Left(warning), _, _, pos) =>
- if (warning.emitWarning(warnSettings))
+ if (warning.emitWarning(compilerSettings))
backendReporting.inlinerWarning(pos, s"failed to determine if ${ins.name} should be inlined:\n$warning")
false
}).toList
@@ -106,7 +124,8 @@ class Inliner[BT <: BTypes](val btypes: BT) {
*/
def doInlineCallsite(callsite: Callsite): Boolean = callsite match {
case Callsite(_, _, _, Right(Callee(callee, calleeDeclClass, safeToInline, _, annotatedInline, _, warning)), _, _, pos) =>
- annotatedInline && safeToInline
+ if (compilerSettings.YoptInlineHeuristics.value == "everything") safeToInline
+ else annotatedInline && safeToInline
case _ => false
}
@@ -167,6 +186,8 @@ class Inliner[BT <: BTypes](val btypes: BT) {
// VerifyError. We run a `SourceInterpreter` to find all producer instructions of the
// receiver value and add a cast to the self type after each.
if (!selfTypeOk) {
+ // there's no need to run eliminateUnreachableCode here. building the call graph does that
+ // already, no code can become unreachable in the meantime.
val analyzer = new AsmAnalyzer(callsite.callsiteMethod, callsite.callsiteClass.internalName, new SourceInterpreter)
val receiverValue = analyzer.frameAt(callsite.callsiteInstruction).peekDown(traitMethodArgumentTypes.length)
for (i <- receiverValue.insns.asScala) {
@@ -311,6 +332,7 @@ class Inliner[BT <: BTypes](val btypes: BT) {
val localVarShift = callsiteMethod.maxLocals
clonedInstructions.iterator.asScala foreach {
case varInstruction: VarInsnNode => varInstruction.`var` += localVarShift
+ case iinc: IincInsnNode => iinc.`var` += localVarShift
case _ => ()
}
@@ -433,6 +455,9 @@ class Inliner[BT <: BTypes](val btypes: BT) {
// Remove the elided invocation from the call graph
callGraph.callsites.remove(callsiteInstruction)
+ // Inlining a method body can render some code unreachable, see example above (in runInliner).
+ unreachableCodeEliminated -= callsiteMethod
+
callsiteMethod.maxLocals += returnType.getSize + callee.maxLocals
callsiteMethod.maxStack = math.max(callsiteMethod.maxStack, callee.maxStack + callsiteStackHeight)
@@ -472,10 +497,18 @@ class Inliner[BT <: BTypes](val btypes: BT) {
callsiteStackHeight > expectedArgs
}
- if (isSynchronizedMethod(callee)) {
+ if (codeSizeOKForInlining(callsiteMethod, callee)) {
+ Some(ResultingMethodTooLarge(
+ calleeDeclarationClass.internalName, callee.name, callee.desc,
+ callsiteClass.internalName, callsiteMethod.name, callsiteMethod.desc))
+ } else if (isSynchronizedMethod(callee)) {
// Could be done by locking on the receiver, wrapping the inlined code in a try and unlocking
// in finally. But it's probably not worth the effort, scala never emits synchronized methods.
Some(SynchronizedMethod(calleeDeclarationClass.internalName, callee.name, callee.desc))
+ } else if (isStrictfpMethod(callsiteMethod) != isStrictfpMethod(callee)) {
+ Some(StrictfpMismatch(
+ calleeDeclarationClass.internalName, callee.name, callee.desc,
+ callsiteClass.internalName, callsiteMethod.name, callsiteMethod.desc))
} else if (!callee.tryCatchBlocks.isEmpty && stackHasNonParameters) {
Some(MethodWithHandlerCalledOnNonEmptyStack(
calleeDeclarationClass.internalName, callee.name, callee.desc,
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 f6cfc5598b..5f51a94673 100644
--- a/src/compiler/scala/tools/nsc/backend/jvm/opt/LocalOpt.scala
+++ b/src/compiler/scala/tools/nsc/backend/jvm/opt/LocalOpt.scala
@@ -14,7 +14,6 @@ import scala.tools.asm.tree._
import scala.collection.convert.decorateAsScala._
import scala.tools.nsc.backend.jvm.BTypes.InternalName
import scala.tools.nsc.backend.jvm.opt.BytecodeUtils._
-import scala.tools.nsc.settings.ScalaSettings
/**
* Optimizations within a single method.
@@ -47,18 +46,9 @@ import scala.tools.nsc.settings.ScalaSettings
* stale labels
* - eliminate labels that are not referenced, merge sequences of label definitions.
*/
-class LocalOpt(settings: ScalaSettings) {
- /**
- * Remove unreachable code from all methods of `classNode`. See of its overload.
- *
- * @param classNode The class to optimize
- * @return `true` if unreachable code was removed from any method
- */
- def minimalRemoveUnreachableCode(classNode: ClassNode): Boolean = {
- classNode.methods.asScala.foldLeft(false) {
- case (changed, method) => minimalRemoveUnreachableCode(method, classNode.name) || changed
- }
- }
+class LocalOpt[BT <: BTypes](val btypes: BT) {
+ import LocalOptImpls._
+ import btypes._
/**
* Remove unreachable code from a method.
@@ -66,25 +56,30 @@ class LocalOpt(settings: ScalaSettings) {
* This implementation only removes instructions that are unreachable for an ASM analyzer /
* interpreter. This ensures that future analyses will not produce `null` frames. The inliner
* and call graph builder depend on this property.
+ *
+ * @return A set containing the eliminated instructions
*/
- def minimalRemoveUnreachableCode(method: MethodNode, ownerClassName: InternalName): Boolean = {
- if (method.instructions.size == 0) return false // fast path for abstract methods
+ def minimalRemoveUnreachableCode(method: MethodNode, ownerClassName: InternalName): Set[AbstractInsnNode] = {
+ if (method.instructions.size == 0) return Set.empty // fast path for abstract methods
+ if (unreachableCodeEliminated(method)) return Set.empty // we know there is no unreachable code
// For correctness, after removing unreachable code, we have to eliminate empty exception
// handlers, see scaladoc of def methodOptimizations. Removing an live handler may render more
// code unreachable and therefore requires running another round.
- def removalRound(): Boolean = {
- val (codeRemoved, liveLabels) = removeUnreachableCodeImpl(method, ownerClassName)
- if (codeRemoved) {
+ def removalRound(): Set[AbstractInsnNode] = {
+ val (removedInstructions, liveLabels) = removeUnreachableCodeImpl(method, ownerClassName)
+ val removedRecursively = if (removedInstructions.nonEmpty) {
val liveHandlerRemoved = removeEmptyExceptionHandlers(method).exists(h => liveLabels(h.start))
if (liveHandlerRemoved) removalRound()
- }
- codeRemoved
+ else Set.empty
+ } else Set.empty
+ removedInstructions ++ removedRecursively
}
- val codeRemoved = removalRound()
- if (codeRemoved) removeUnusedLocalVariableNodes(method)()
- codeRemoved
+ val removedInstructions = removalRound()
+ if (removedInstructions.nonEmpty) removeUnusedLocalVariableNodes(method)()
+ unreachableCodeEliminated += method
+ removedInstructions
}
/**
@@ -95,7 +90,7 @@ class LocalOpt(settings: ScalaSettings) {
* @return `true` if unreachable code was eliminated in some method, `false` otherwise.
*/
def methodOptimizations(clazz: ClassNode): Boolean = {
- !settings.YoptNone && clazz.methods.asScala.foldLeft(false) {
+ !compilerSettings.YoptNone && clazz.methods.asScala.foldLeft(false) {
case (changed, method) => methodOptimizations(method, clazz.name) || changed
}
}
@@ -144,15 +139,15 @@ class LocalOpt(settings: ScalaSettings) {
def removalRound(): Boolean = {
// unreachable-code, empty-handlers and simplify-jumps run until reaching a fixpoint (see doc on class LocalOpt)
- val (codeRemoved, handlersRemoved, liveHandlerRemoved) = if (settings.YoptUnreachableCode) {
- val (codeRemoved, liveLabels) = removeUnreachableCodeImpl(method, ownerClassName)
+ val (codeRemoved, handlersRemoved, liveHandlerRemoved) = if (compilerSettings.YoptUnreachableCode) {
+ val (removedInstructions, liveLabels) = removeUnreachableCodeImpl(method, ownerClassName)
val removedHandlers = removeEmptyExceptionHandlers(method)
- (codeRemoved, removedHandlers.nonEmpty, removedHandlers.exists(h => liveLabels(h.start)))
+ (removedInstructions.nonEmpty, removedHandlers.nonEmpty, removedHandlers.exists(h => liveLabels(h.start)))
} else {
(false, false, false)
}
- val jumpsChanged = if (settings.YoptSimplifyJumps) simplifyJumps(method) else false
+ val jumpsChanged = if (compilerSettings.YoptSimplifyJumps) simplifyJumps(method) else false
// Eliminating live handlers and simplifying jump instructions may render more code
// unreachable, so we need to run another round.
@@ -165,13 +160,13 @@ class LocalOpt(settings: ScalaSettings) {
// (*) Removing stale local variable descriptors is required for correctness of unreachable-code
val localsRemoved =
- if (settings.YoptCompactLocals) compactLocalVariables(method) // also removes unused
- else if (settings.YoptUnreachableCode) removeUnusedLocalVariableNodes(method)() // (*)
+ if (compilerSettings.YoptCompactLocals) compactLocalVariables(method) // also removes unused
+ else if (compilerSettings.YoptUnreachableCode) removeUnusedLocalVariableNodes(method)() // (*)
else false
- val lineNumbersRemoved = if (settings.YoptEmptyLineNumbers) removeEmptyLineNumbers(method) else false
+ val lineNumbersRemoved = if (compilerSettings.YoptEmptyLineNumbers) removeEmptyLineNumbers(method) else false
- val labelsRemoved = if (settings.YoptEmptyLabels) removeEmptyLabelNodes(method) else false
+ val labelsRemoved = if (compilerSettings.YoptEmptyLabels) removeEmptyLabelNodes(method) else false
// assert that local variable annotations are empty (we don't emit them) - otherwise we'd have
// to eliminate those covering an empty range, similar to removeUnusedLocalVariableNodes.
@@ -179,15 +174,22 @@ class LocalOpt(settings: ScalaSettings) {
assert(nullOrEmpty(method.visibleLocalVariableAnnotations), method.visibleLocalVariableAnnotations)
assert(nullOrEmpty(method.invisibleLocalVariableAnnotations), method.invisibleLocalVariableAnnotations)
+ unreachableCodeEliminated += method
+
codeHandlersOrJumpsChanged || localsRemoved || lineNumbersRemoved || labelsRemoved
}
+}
+
+object LocalOptImpls {
/**
* Removes unreachable basic blocks.
*
* TODO: rewrite, don't use computeMaxLocalsMaxStack (runs a ClassWriter) / Analyzer. Too slow.
+ *
+ * @return A set containing eliminated instructions, and a set containing all live label nodes.
*/
- def removeUnreachableCodeImpl(method: MethodNode, ownerClassName: InternalName): (Boolean, Set[LabelNode]) = {
+ def removeUnreachableCodeImpl(method: MethodNode, ownerClassName: InternalName): (Set[AbstractInsnNode], Set[LabelNode]) = {
// The data flow analysis requires the maxLocals / maxStack fields of the method to be computed.
computeMaxLocalsMaxStack(method)
val a = new Analyzer(new BasicInterpreter)
@@ -197,6 +199,7 @@ class LocalOpt(settings: ScalaSettings) {
val initialSize = method.instructions.size
var i = 0
var liveLabels = Set.empty[LabelNode]
+ var removedInstructions = Set.empty[AbstractInsnNode]
val itr = method.instructions.iterator()
while (itr.hasNext) {
itr.next() match {
@@ -209,11 +212,12 @@ class LocalOpt(settings: ScalaSettings) {
// Instruction iterators allow removing during iteration.
// Removing is O(1): instructions are doubly linked list elements.
itr.remove()
+ removedInstructions += ins
}
}
i += 1
}
- (method.instructions.size != initialSize, liveLabels)
+ (removedInstructions, liveLabels)
}
/**
diff --git a/src/compiler/scala/tools/nsc/backend/opt/DeadCodeElimination.scala b/src/compiler/scala/tools/nsc/backend/opt/DeadCodeElimination.scala
index 3704acb055..1b6631e7a4 100644
--- a/src/compiler/scala/tools/nsc/backend/opt/DeadCodeElimination.scala
+++ b/src/compiler/scala/tools/nsc/backend/opt/DeadCodeElimination.scala
@@ -173,7 +173,7 @@ abstract class DeadCodeElimination extends SubComponent {
moveToWorkList()
case LOAD_FIELD(sym, isStatic) if isStatic || !inliner.isClosureClass(sym.owner) =>
- // static load may trigger static initization.
+ // static load may trigger static initialization.
// non-static load can throw NPE (but we know closure fields can't be accessed via a
// null reference.
moveToWorkList()
@@ -191,7 +191,7 @@ abstract class DeadCodeElimination extends SubComponent {
case LOAD_EXCEPTION(_) | DUP(_) | LOAD_MODULE(_) => true
case _ =>
dropOf((bb1, idx1)) = (bb,idx) :: dropOf.getOrElse((bb1, idx1), Nil)
- debuglog("DROP is innessential: " + i + " because of: " + bb1(idx1) + " at " + bb1 + ":" + idx1)
+ debuglog("DROP is inessential: " + i + " because of: " + bb1(idx1) + " at " + bb1 + ":" + idx1)
false
}
}
diff --git a/src/compiler/scala/tools/nsc/plugins/Plugin.scala b/src/compiler/scala/tools/nsc/plugins/Plugin.scala
index 5a7a0df595..1a5529140c 100644
--- a/src/compiler/scala/tools/nsc/plugins/Plugin.scala
+++ b/src/compiler/scala/tools/nsc/plugins/Plugin.scala
@@ -60,13 +60,15 @@ abstract class Plugin {
* @return true to continue, or false to opt out
*/
def init(options: List[String], error: String => Unit): Boolean = {
- if (!options.isEmpty) error(s"Error: $name takes no options")
+ // call to deprecated method required here, we must continue to support
+ // code that subclasses that override `processOptions`.
+ processOptions(options, error)
true
}
@deprecated("use Plugin#init instead", since="2.11")
def processOptions(options: List[String], error: String => Unit): Unit = {
- init(options, error)
+ if (!options.isEmpty) error(s"Error: $name takes no options")
}
/** A description of this plugin's options, suitable as a response
diff --git a/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala b/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala
index d273995e6e..630276e412 100644
--- a/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala
+++ b/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala
@@ -139,6 +139,18 @@ trait ScalaSettings extends AbsScalaSettings
val XnoPatmatAnalysis = BooleanSetting ("-Xno-patmat-analysis", "Don't perform exhaustivity/unreachability analysis. Also, ignore @switch annotation.")
val XfullLubs = BooleanSetting ("-Xfull-lubs", "Retains pre 2.10 behavior of less aggressive truncation of least upper bounds.")
+ // XML parsing options
+ object XxmlSettings extends MultiChoiceEnumeration {
+ val coalescing = Choice("coalescing", "Convert PCData to Text and coalesce sibling nodes")
+ def isCoalescing = (Xxml contains coalescing) || (!isScala212 && !Xxml.isSetByUser)
+ }
+ val Xxml = MultiChoiceSetting(
+ name = "-Xxml",
+ helpArg = "property",
+ descr = "Configure XML parsing",
+ domain = XxmlSettings
+ )
+
/** Compatibility stubs for options whose value name did
* not previously match the option name.
*/
@@ -256,6 +268,13 @@ trait ScalaSettings extends AbsScalaSettings
def YoptInlineGlobal = Yopt.contains(YoptChoices.inlineGlobal)
def YoptInlinerEnabled = YoptInlineProject || YoptInlineGlobal
+ val YoptInlineHeuristics = ChoiceSetting(
+ name = "-Yopt-inline-heuristics",
+ helpArg = "strategy",
+ descr = "Set the heuristics for inlining decisions.",
+ choices = List("at-inline-annotated", "everything"),
+ default = "at-inline-annotated")
+
object YoptWarningsChoices extends MultiChoiceEnumeration {
val none = Choice("none" , "No optimizer warnings.")
val atInlineFailedSummary = Choice("at-inline-failed-summary" , "One-line summary if there were @inline method calls that could not be inlined.")
@@ -267,7 +286,7 @@ trait ScalaSettings extends AbsScalaSettings
val YoptWarnings = MultiChoiceSetting(
name = "-Yopt-warnings",
- helpArg = "warnings",
+ helpArg = "warning",
descr = "Enable optimizer warnings",
domain = YoptWarningsChoices,
default = Some(List(YoptWarningsChoices.atInlineFailed.name))) withPostSetHook (self => {
@@ -275,6 +294,15 @@ trait ScalaSettings extends AbsScalaSettings
else YinlinerWarnings.value = true
})
+ def YoptWarningEmitAtInlineFailed =
+ !YoptWarnings.isSetByUser ||
+ YoptWarnings.contains(YoptWarningsChoices.atInlineFailedSummary) ||
+ YoptWarnings.contains(YoptWarningsChoices.atInlineFailed)
+
+ def YoptWarningNoInlineMixed = YoptWarnings.contains(YoptWarningsChoices.noInlineMixed)
+ def YoptWarningNoInlineMissingBytecode = YoptWarnings.contains(YoptWarningsChoices.noInlineMissingBytecode)
+ def YoptWarningNoInlineMissingScalaInlineInfoAttr = YoptWarnings.contains(YoptWarningsChoices.noInlineMissingScalaInlineInfoAttr)
+
private def removalIn212 = "This flag is scheduled for removal in 2.12. If you have a case where you need this flag then please report a bug."
object YstatisticsPhases extends MultiChoiceEnumeration { val parser, typer, patmat, erasure, cleanup, jvm = Value }
@@ -345,12 +373,7 @@ trait ScalaSettings extends AbsScalaSettings
/** Test whether this is scaladoc we're looking at */
def isScaladoc = false
- /**
- * Helper utilities for use by checkConflictingSettings()
- */
- def isBCodeActive = !isICodeAskedFor
- def isBCodeAskedFor = (Ybackend.value != "GenASM")
- def isICodeAskedFor = ((Ybackend.value == "GenASM") || optimiseSettings.exists(_.value) || writeICode.isSetByUser)
+ def isBCodeActive = Ybackend.value == "GenBCode"
object MacroExpand {
val None = "none"
diff --git a/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala b/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala
index 1ffa064b78..a59b9d3f48 100644
--- a/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala
+++ b/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala
@@ -15,6 +15,7 @@ import scala.collection.mutable.{ ListBuffer, ArrayBuffer }
import scala.annotation.switch
import scala.reflect.internal.{ JavaAccFlags }
import scala.reflect.internal.pickling.{PickleBuffer, ByteCodecs}
+import scala.reflect.io.NoAbstractFile
import scala.tools.nsc.io.AbstractFile
import scala.tools.nsc.util.ClassFileLookup
@@ -1022,11 +1023,18 @@ abstract class ClassfileParser {
val sflags = jflags.toScalaFlags
val owner = ownerForFlags(jflags)
val scope = getScope(jflags)
- val innerClass = owner.newClass(name.toTypeName, NoPosition, sflags) setInfo completer
- val innerModule = owner.newModule(name.toTermName, NoPosition, sflags) setInfo completer
+ def newStub(name: Name) =
+ owner.newStubSymbol(name, s"Class file for ${entry.externalName} not found").setFlag(JAVA)
- innerModule.moduleClass setInfo loaders.moduleClassLoader
- List(innerClass, innerModule.moduleClass) foreach (_.associatedFile = file)
+ val (innerClass, innerModule) = if (file == NoAbstractFile) {
+ (newStub(name.toTypeName), newStub(name.toTermName))
+ } else {
+ val cls = owner.newClass(name.toTypeName, NoPosition, sflags) setInfo completer
+ val mod = owner.newModule(name.toTermName, NoPosition, sflags) setInfo completer
+ mod.moduleClass setInfo loaders.moduleClassLoader
+ List(cls, mod.moduleClass) foreach (_.associatedFile = file)
+ (cls, mod)
+ }
scope enter innerClass
scope enter innerModule
@@ -1046,10 +1054,8 @@ abstract class ClassfileParser {
for (entry <- innerClasses.entries) {
// create a new class member for immediate inner classes
if (entry.outerName == currentClass) {
- val file = classFileLookup.findClassFile(entry.externalName.toString) getOrElse {
- throw new AssertionError(s"Class file for ${entry.externalName} not found")
- }
- enterClassAndModule(entry, file)
+ val file = classFileLookup.findClassFile(entry.externalName.toString)
+ enterClassAndModule(entry, file.getOrElse(NoAbstractFile))
}
}
}
@@ -1135,16 +1141,12 @@ abstract class ClassfileParser {
private def innerSymbol(entry: InnerClassEntry): Symbol = {
val name = entry.originalName.toTypeName
val enclosing = entry.enclosing
- def getMember = (
+ val member = (
if (enclosing == clazz) entry.scope lookup name
else lookupMemberAtTyperPhaseIfPossible(enclosing, name)
)
- getMember
- /* There used to be an assertion that this result is not NoSymbol; changing it to an error
- * revealed it had been going off all the time, but has been swallowed by a catch t: Throwable
- * in Repository.scala. Since it has been accomplishing nothing except misleading anyone who
- * thought it wasn't triggering, I removed it entirely.
- */
+ def newStub = enclosing.newStubSymbol(name, s"Unable to locate class corresponding to inner class entry for $name in owner ${entry.outerName}")
+ member.orElse(newStub)
}
}
diff --git a/src/compiler/scala/tools/nsc/transform/AddInterfaces.scala b/src/compiler/scala/tools/nsc/transform/AddInterfaces.scala
index 3591372bbe..79776485de 100644
--- a/src/compiler/scala/tools/nsc/transform/AddInterfaces.scala
+++ b/src/compiler/scala/tools/nsc/transform/AddInterfaces.scala
@@ -207,7 +207,7 @@ abstract class AddInterfaces extends InfoTransform { self: Erasure =>
}
def transformMixinInfo(tp: Type): Type = tp match {
- case ClassInfoType(parents, decls, clazz) =>
+ case ClassInfoType(parents, decls, clazz) if clazz.isPackageClass || !clazz.isJavaDefined =>
if (clazz.needsImplClass)
implClass(clazz setFlag lateINTERFACE) // generate an impl class
diff --git a/src/compiler/scala/tools/nsc/transform/Constructors.scala b/src/compiler/scala/tools/nsc/transform/Constructors.scala
index d0fca12e6a..86685d46de 100644
--- a/src/compiler/scala/tools/nsc/transform/Constructors.scala
+++ b/src/compiler/scala/tools/nsc/transform/Constructors.scala
@@ -315,7 +315,7 @@ abstract class Constructors extends Statics with Transform with ast.TreeDSL {
}
def rewriteDelayedInit() {
- /* XXX This is not corect: remainingConstrStats.nonEmpty excludes too much,
+ /* XXX This is not correct: remainingConstrStats.nonEmpty excludes too much,
* but excluding it includes too much. The constructor sequence being mimicked
* needs to be reproduced with total fidelity.
*
diff --git a/src/compiler/scala/tools/nsc/transform/Delambdafy.scala b/src/compiler/scala/tools/nsc/transform/Delambdafy.scala
index 94e88589f5..45a89ac594 100644
--- a/src/compiler/scala/tools/nsc/transform/Delambdafy.scala
+++ b/src/compiler/scala/tools/nsc/transform/Delambdafy.scala
@@ -15,13 +15,12 @@ import scala.collection.mutable.LinkedHashMap
* Currently Uncurry is responsible for that transformation.
*
* From a lambda, Delambdafy will create
- * 1) a static forwarder at the top level of the class that contained the lambda
- * 2) a new top level class that
+ * 1) a new top level class that
a) has fields and a constructor taking the captured environment (including possibly the "this"
* reference)
- * b) an apply method that calls the static forwarder
+ * b) an apply method that calls the target method
* c) if needed a bridge method for the apply method
- * 3) an instantiation of the newly created class which replaces the lambda
+ * 2) an instantiation of the newly created class which replaces the lambda
*
* TODO the main work left to be done is to plug into specialization. Primarily that means choosing a
* specialized FunctionN trait instead of the generic FunctionN trait as a parent and creating the
@@ -76,36 +75,25 @@ abstract class Delambdafy extends Transform with TypingTransformers with ast.Tre
referrers
}
- val accessorMethods = mutable.ArrayBuffer[Tree]()
-
- // the result of the transformFunction method. A class definition for the lambda, an expression
- // insantiating the lambda class, and an accessor method for the lambda class to be able to
- // call the implementation
- case class TransformedFunction(lambdaClassDef: ClassDef, newExpr: Tree, accessorMethod: Tree)
+ // the result of the transformFunction method.
+ sealed abstract class TransformedFunction
+ // A class definition for the lambda, an expression instantiating the lambda class
+ case class DelambdafyAnonClass(lambdaClassDef: ClassDef, newExpr: Tree) extends TransformedFunction
// here's the main entry point of the transform
override def transform(tree: Tree): Tree = tree match {
// the main thing we care about is lambdas
case fun @ Function(_, _) =>
- // a lambda beccomes a new class, an instantiation expression, and an
- // accessor method
- val TransformedFunction(lambdaClassDef, newExpr, accessorMethod) = transformFunction(fun)
- // we'll add accessor methods to the current template later
- accessorMethods += accessorMethod
- val pkg = lambdaClassDef.symbol.owner
-
- // we'll add the lambda class to the package later
- lambdaClassDefs(pkg) = lambdaClassDef :: lambdaClassDefs(pkg)
-
- super.transform(newExpr)
- // when we encounter a template (basically the thing that holds body of a class/trait)
- // we need to updated it to include newly created accessor methods after transforming it
- case Template(_, _, _) =>
- try {
- // during this call accessorMethods will be populated from the Function case
- val Template(parents, self, body) = super.transform(tree)
- Template(parents, self, body ++ accessorMethods)
- } finally accessorMethods.clear()
+ transformFunction(fun) match {
+ case DelambdafyAnonClass(lambdaClassDef, newExpr) =>
+ // a lambda becomes a new class, an instantiation expression
+ val pkg = lambdaClassDef.symbol.owner
+
+ // we'll add the lambda class to the package later
+ lambdaClassDefs(pkg) = lambdaClassDef :: lambdaClassDefs(pkg)
+
+ super.transform(newExpr)
+ }
case _ => super.transform(tree)
}
@@ -120,8 +108,7 @@ abstract class Delambdafy extends Transform with TypingTransformers with ast.Tre
private def optionSymbol(sym: Symbol): Option[Symbol] = if (sym.exists) Some(sym) else None
- // turns a lambda into a new class def, a New expression instantiating that class, and an
- // accessor method fo the body of the lambda
+ // turns a lambda into a new class def, a New expression instantiating that class
private def transformFunction(originalFunction: Function): TransformedFunction = {
val functionTpe = originalFunction.tpe
val targs = functionTpe.typeArgs
@@ -132,46 +119,16 @@ abstract class Delambdafy extends Transform with TypingTransformers with ast.Tre
// passed into the constructor of the anonymous function class
val captures = FreeVarTraverser.freeVarsOf(originalFunction)
- /**
- * Creates the apply method for the anonymous subclass of FunctionN
- */
- def createAccessorMethod(thisProxy: Symbol, fun: Function): DefDef = {
- val target = targetMethod(fun)
- if (!thisProxy.exists) {
- target setFlag STATIC
- }
- val params = ((optionSymbol(thisProxy) map {proxy:Symbol => ValDef(proxy)}) ++ (target.paramss.flatten map ValDef.apply)).toList
-
- val methSym = oldClass.newMethod(unit.freshTermName(nme.accessor.toString() + "$"), target.pos, FINAL | BRIDGE | SYNTHETIC | PROTECTED | STATIC)
+ val target = targetMethod(originalFunction)
+ target.makeNotPrivate(target.owner)
+ if (!thisReferringMethods.contains(target))
+ target setFlag STATIC
- val paramSyms = params map {param => methSym.newSyntheticValueParam(param.symbol.tpe, param.name) }
-
- params zip paramSyms foreach { case (valdef, sym) => valdef.symbol = sym }
- params foreach (_.symbol.owner = methSym)
-
- val methodType = MethodType(paramSyms, restpe)
- methSym setInfo methodType
-
- oldClass.info.decls enter methSym
-
- val body = localTyper.typed {
- val newTarget = Select(if (thisProxy.exists) gen.mkAttributedRef(paramSyms(0)) else gen.mkAttributedThis(oldClass), target)
- val newParams = paramSyms drop (if (thisProxy.exists) 1 else 0) map Ident
- Apply(newTarget, newParams)
- } setPos fun.pos
- val methDef = DefDef(methSym, List(params), body)
-
- // Have to repack the type to avoid mismatches when existentials
- // appear in the result - see SI-4869.
- // TODO probably don't need packedType
- methDef.tpt setType localTyper.packedType(body, methSym)
- methDef
- }
/**
* Creates the apply method for the anonymous subclass of FunctionN
*/
- def createApplyMethod(newClass: Symbol, fun: Function, accessor: DefDef, thisProxy: Symbol): DefDef = {
+ def createApplyMethod(newClass: Symbol, fun: Function, thisProxy: Symbol): DefDef = {
val methSym = newClass.newMethod(nme.apply, fun.pos, FINAL | SYNTHETIC)
val params = fun.vparams map (_.duplicate)
@@ -187,8 +144,12 @@ abstract class Delambdafy extends Transform with TypingTransformers with ast.Tre
newClass.info.decls enter methSym
val Apply(_, oldParams) = fun.body
+ val qual = if (thisProxy.exists)
+ Select(gen.mkAttributedThis(newClass), thisProxy)
+ else
+ gen.mkAttributedThis(oldClass) // sort of a lie, EmptyTree.<static method> would be more honest, but the backend chokes on that.
- val body = localTyper typed Apply(Select(gen.mkAttributedThis(oldClass), accessor.symbol), (optionSymbol(thisProxy) map {tp => Select(gen.mkAttributedThis(newClass), tp)}).toList ++ oldParams)
+ val body = localTyper typed Apply(Select(qual, target), oldParams)
body.substituteSymbols(fun.vparams map (_.symbol), params map (_.symbol))
body changeOwner (fun.symbol -> methSym)
@@ -271,18 +232,16 @@ abstract class Delambdafy extends Transform with TypingTransformers with ast.Tre
// the Optional proxy that will hold a reference to the 'this'
// object used by the lambda, if any. NoSymbol if there is no this proxy
val thisProxy = {
- val target = targetMethod(originalFunction)
- if (thisReferringMethods contains target) {
+ if (target.hasFlag(STATIC))
+ NoSymbol
+ else {
val sym = lambdaClass.newVariable(nme.FAKE_LOCAL_THIS, originalFunction.pos, SYNTHETIC)
- sym.info = oldClass.tpe
- sym
- } else NoSymbol
+ sym.setInfo(oldClass.tpe)
+ }
}
val decapturify = new DeCapturifyTransformer(captureProxies2, unit, oldClass, lambdaClass, originalFunction.symbol.pos, thisProxy)
- val accessorMethod = createAccessorMethod(thisProxy, originalFunction)
-
val decapturedFunction = decapturify.transform(originalFunction).asInstanceOf[Function]
val members = (optionSymbol(thisProxy).toList ++ (captureProxies2 map (_._2))) map {member =>
@@ -294,7 +253,7 @@ abstract class Delambdafy extends Transform with TypingTransformers with ast.Tre
val constr = createConstructor(lambdaClass, members)
// apply method with same arguments and return type as original lambda.
- val applyMethodDef = createApplyMethod(lambdaClass, decapturedFunction, accessorMethod, thisProxy)
+ val applyMethodDef = createApplyMethod(lambdaClass, decapturedFunction, thisProxy)
val bridgeMethod = createBridgeMethod(lambdaClass, originalFunction, applyMethodDef)
@@ -312,10 +271,10 @@ abstract class Delambdafy extends Transform with TypingTransformers with ast.Tre
val body = members ++ List(constr, applyMethodDef) ++ bridgeMethod
// TODO if member fields are private this complains that they're not accessible
- (localTyper.typedPos(decapturedFunction.pos)(ClassDef(lambdaClass, body)).asInstanceOf[ClassDef], thisProxy, accessorMethod)
+ (localTyper.typedPos(decapturedFunction.pos)(ClassDef(lambdaClass, body)).asInstanceOf[ClassDef], thisProxy)
}
- val (anonymousClassDef, thisProxy, accessorMethod) = makeAnonymousClass
+ val (anonymousClassDef, thisProxy) = makeAnonymousClass
pkg.info.decls enter anonymousClassDef.symbol
@@ -327,7 +286,7 @@ abstract class Delambdafy extends Transform with TypingTransformers with ast.Tre
val typedNewStat = localTyper.typedPos(originalFunction.pos)(newStat)
- TransformedFunction(anonymousClassDef, typedNewStat, accessorMethod)
+ DelambdafyAnonClass(anonymousClassDef, typedNewStat)
}
/**
diff --git a/src/compiler/scala/tools/nsc/transform/Erasure.scala b/src/compiler/scala/tools/nsc/transform/Erasure.scala
index facce9062b..9fdc3a9d72 100644
--- a/src/compiler/scala/tools/nsc/transform/Erasure.scala
+++ b/src/compiler/scala/tools/nsc/transform/Erasure.scala
@@ -188,14 +188,16 @@ abstract class Erasure extends AddInterfaces
/* Drop redundant types (ones which are implemented by some other parent) from the immediate parents.
* This is important on Android because there is otherwise an interface explosion.
*/
- def minimizeParents(parents: List[Type]): List[Type] = {
- var rest = parents
- var leaves = collection.mutable.ListBuffer.empty[Type]
+ def minimizeParents(parents: List[Type]): List[Type] = if (parents.isEmpty) parents else {
+ def isInterfaceOrTrait(sym: Symbol) = sym.isInterface || sym.isTrait
+
+ var rest = parents.tail
+ var leaves = collection.mutable.ListBuffer.empty[Type] += parents.head
while(rest.nonEmpty) {
val candidate = rest.head
val nonLeaf = leaves exists { t => t.typeSymbol isSubClass candidate.typeSymbol }
if(!nonLeaf) {
- leaves = leaves filterNot { t => candidate.typeSymbol isSubClass t.typeSymbol }
+ leaves = leaves filterNot { t => isInterfaceOrTrait(t.typeSymbol) && (candidate.typeSymbol isSubClass t.typeSymbol) }
leaves += candidate
}
rest = rest.tail
diff --git a/src/compiler/scala/tools/nsc/transform/LambdaLift.scala b/src/compiler/scala/tools/nsc/transform/LambdaLift.scala
index 5e2fe21eec..d1be1558b9 100644
--- a/src/compiler/scala/tools/nsc/transform/LambdaLift.scala
+++ b/src/compiler/scala/tools/nsc/transform/LambdaLift.scala
@@ -376,7 +376,7 @@ abstract class LambdaLift extends InfoTransform {
private def addFreeArgs(pos: Position, sym: Symbol, args: List[Tree]) = {
free get sym match {
- case Some(fvs) => args ++ (fvs.toList map (fv => atPos(pos)(proxyRef(fv))))
+ case Some(fvs) => addFree(sym, free = fvs.toList map (fv => atPos(pos)(proxyRef(fv))), original = args)
case _ => args
}
}
@@ -388,9 +388,9 @@ abstract class LambdaLift extends InfoTransform {
case DefDef(_, _, _, vparams :: _, _, _) =>
val addParams = cloneSymbols(ps).map(_.setFlag(PARAM))
sym.updateInfo(
- lifted(MethodType(sym.info.params ::: addParams, sym.info.resultType)))
+ lifted(MethodType(addFree(sym, free = addParams, original = sym.info.params), sym.info.resultType)))
- copyDefDef(tree)(vparamss = List(vparams ++ freeParams))
+ copyDefDef(tree)(vparamss = List(addFree(sym, free = freeParams, original = vparams)))
case ClassDef(_, _, _, _) =>
// SI-6231
// Disabled attempt to to add getters to freeParams
@@ -571,4 +571,12 @@ abstract class LambdaLift extends InfoTransform {
}
} // class LambdaLifter
+ private def addFree[A](sym: Symbol, free: List[A], original: List[A]): List[A] = {
+ val prependFree = (
+ !sym.isConstructor // this condition is redundant for now. It will be needed if we remove the second condition in 2.12.x
+ && (settings.Ydelambdafy.value == "method" && sym.isDelambdafyTarget) // SI-8359 Makes the lambda body a viable as the target MethodHandle for a call to LambdaMetafactory
+ )
+ if (prependFree) free ::: original
+ else original ::: free
+ }
}
diff --git a/src/compiler/scala/tools/nsc/transform/LazyVals.scala b/src/compiler/scala/tools/nsc/transform/LazyVals.scala
index 38671ebaae..df622d4d1d 100644
--- a/src/compiler/scala/tools/nsc/transform/LazyVals.scala
+++ b/src/compiler/scala/tools/nsc/transform/LazyVals.scala
@@ -219,7 +219,7 @@ abstract class LazyVals extends Transform with TypingTransformers with ast.TreeD
* l$
* } or
* <rhs> when the lazy value has type Unit (for which there is no field
- * to cache it's value.
+ * to cache its value.
*
* Similarly as for normal lazy val members (see Mixin), the result will be a tree of the form
* { if ((bitmap&n & MASK) == 0) this.l$compute()
diff --git a/src/compiler/scala/tools/nsc/transform/Mixin.scala b/src/compiler/scala/tools/nsc/transform/Mixin.scala
index 408f4466e1..11f9483f77 100644
--- a/src/compiler/scala/tools/nsc/transform/Mixin.scala
+++ b/src/compiler/scala/tools/nsc/transform/Mixin.scala
@@ -26,7 +26,7 @@ abstract class Mixin extends InfoTransform with ast.TreeDSL {
*/
private val treatedClassInfos = perRunCaches.newMap[Symbol, Type]() withDefaultValue NoType
- /** Map a lazy, mixedin field accessor to it's trait member accessor */
+ /** Map a lazy, mixedin field accessor to its trait member accessor */
private val initializer = perRunCaches.newMap[Symbol, Symbol]()
// --------- helper functions -----------------------------------------------
@@ -886,7 +886,7 @@ abstract class Mixin extends InfoTransform with ast.TreeDSL {
}
/* Complete lazy field accessors. Applies only to classes,
- * for it's own (non inherited) lazy fields. If 'checkinit'
+ * for its own (non inherited) lazy fields. If 'checkinit'
* is enabled, getters that check for the initialized bit are
* generated, and the class constructor is changed to set the
* initialized bits.
diff --git a/src/compiler/scala/tools/nsc/transform/SampleTransform.scala b/src/compiler/scala/tools/nsc/transform/SampleTransform.scala
index cffb483072..ba303f7c2b 100644
--- a/src/compiler/scala/tools/nsc/transform/SampleTransform.scala
+++ b/src/compiler/scala/tools/nsc/transform/SampleTransform.scala
@@ -27,7 +27,7 @@ abstract class SampleTransform extends Transform {
tree1 match {
case Block(List(), expr) => // a simple optimization
expr
- case Block(defs, sup @ Super(qual, mix)) => // A hypthothetic transformation, which replaces
+ case Block(defs, sup @ Super(qual, mix)) => // A hypothetical transformation, which replaces
// {super} by {super.sample}
treeCopy.Block( // `copy` is the usual lazy tree copier
tree1, defs,
diff --git a/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala b/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala
index 086512677e..1a24c668ba 100644
--- a/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala
+++ b/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala
@@ -610,7 +610,7 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
exitingSpecialize(sClass setInfo specializedInfoType)
val fullEnv = outerEnv ++ env
- /* Enter 'sym' in the scope of the current specialized class. It's type is
+ /* Enter 'sym' in the scope of the current specialized class. Its type is
* mapped through the active environment, binding type variables to concrete
* types. The existing typeEnv for `sym` is composed with the current active
* environment
@@ -1368,7 +1368,7 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
)
def specializeCalls(unit: CompilationUnit) = new TypingTransformer(unit) {
- /** Map a specializable method to it's rhs, when not deferred. */
+ /** Map a specializable method to its rhs, when not deferred. */
val body = perRunCaches.newMap[Symbol, Tree]()
/** Map a specializable method to its value parameter symbols. */
diff --git a/src/compiler/scala/tools/nsc/transform/UnCurry.scala b/src/compiler/scala/tools/nsc/transform/UnCurry.scala
index 3330fbcae2..6484d96a52 100644
--- a/src/compiler/scala/tools/nsc/transform/UnCurry.scala
+++ b/src/compiler/scala/tools/nsc/transform/UnCurry.scala
@@ -71,6 +71,14 @@ abstract class UnCurry extends InfoTransform
private val noApply = mutable.HashSet[Tree]()
private val newMembers = mutable.Map[Symbol, mutable.Buffer[Tree]]()
+ private lazy val forceSpecializationInfoTransformOfFunctionN: Unit = {
+ if (currentRun.specializePhase != NoPhase) { // be robust in case of -Ystop-after:uncurry
+ exitingSpecialize {
+ FunctionClass.seq.foreach(cls => cls.info)
+ }
+ }
+ }
+
/** Add a new synthetic member for `currentOwner` */
private def addNewMember(t: Tree): Unit =
newMembers.getOrElseUpdate(currentOwner, mutable.Buffer()) += t
@@ -221,8 +229,16 @@ abstract class UnCurry extends InfoTransform
def mkMethod(owner: Symbol, name: TermName, additionalFlags: FlagSet = NoFlags): DefDef =
gen.mkMethodFromFunction(localTyper)(fun, owner, name, additionalFlags)
- val canUseDelamdafyMethod = (inConstructorFlag == 0) // Avoiding synthesizing code prone to SI-6666, SI-8363 by using old-style lambda translation
+ def isSpecialized = {
+ forceSpecializationInfoTransformOfFunctionN
+ val specialized = specializeTypes.specializedType(fun.tpe)
+ !(specialized =:= fun.tpe)
+ }
+ def canUseDelamdafyMethod = (
+ (inConstructorFlag == 0) // Avoiding synthesizing code prone to SI-6666, SI-8363 by using old-style lambda translation
+ && !isSpecialized // DelambdafyTransformer currently only emits generic FunctionN-s, use the old style in the meantime
+ )
if (inlineFunctionExpansion || !canUseDelamdafyMethod) {
val parents = addSerializable(abstractFunctionForFunctionType(fun.tpe))
val anonClass = fun.symbol.owner newAnonymousFunctionClass(fun.pos, inConstructorFlag) addAnnotation SerialVersionUIDAnnotation
diff --git a/src/compiler/scala/tools/nsc/transform/patmat/Logic.scala b/src/compiler/scala/tools/nsc/transform/patmat/Logic.scala
index 0b53dc37de..cef22d7d6b 100644
--- a/src/compiler/scala/tools/nsc/transform/patmat/Logic.scala
+++ b/src/compiler/scala/tools/nsc/transform/patmat/Logic.scala
@@ -9,8 +9,8 @@ package tools.nsc.transform.patmat
import scala.language.postfixOps
import scala.collection.mutable
-import scala.reflect.internal.util.Statistics
-import scala.reflect.internal.util.HashSet
+import scala.reflect.internal.util.{NoPosition, Position, Statistics, HashSet}
+import scala.tools.nsc.Global
trait Logic extends Debugging {
import PatternMatchingStats._
@@ -71,6 +71,8 @@ trait Logic extends Debugging {
def unapply(v: Var): Some[Tree]
}
+ def uncheckedWarning(pos: Position, msg: String): Unit
+
def reportWarning(message: String): Unit
// resets hash consing -- only supposed to be called by TreeMakersToProps
@@ -89,6 +91,8 @@ trait Logic extends Debugging {
// compute the domain and return it (call registerNull first!)
def domainSyms: Option[Set[Sym]]
+ def groupedDomains: List[Set[Sym]]
+
// the symbol for this variable being equal to its statically known type
// (only available if registerEquality has been called for that type before)
def symForStaticTp: Option[Sym]
@@ -117,6 +121,9 @@ trait Logic extends Debugging {
final case class Not(a: Prop) extends Prop
+ // mutually exclusive (i.e., not more than one symbol is set)
+ final case class AtMostOne(ops: List[Sym]) extends Prop
+
case object True extends Prop
case object False extends Prop
@@ -191,7 +198,8 @@ trait Logic extends Debugging {
case Not(negated) => negationNormalFormNot(negated)
case True
| False
- | (_: Sym) => p
+ | (_: Sym)
+ | (_: AtMostOne) => p
}
def simplifyProp(p: Prop): Prop = p match {
@@ -251,6 +259,7 @@ trait Logic extends Debugging {
case Not(a) => apply(a)
case Eq(a, b) => applyVar(a); applyConst(b)
case s: Sym => applySymbol(s)
+ case AtMostOne(ops) => ops.foreach(applySymbol)
case _ =>
}
def applyVar(x: Var): Unit = {}
@@ -283,6 +292,23 @@ trait Logic extends Debugging {
}
}
+ // to govern how much time we spend analyzing matches for unreachability/exhaustivity
+ object AnalysisBudget {
+ val maxDPLLdepth = global.settings.YpatmatExhaustdepth.value
+ val maxFormulaSize = 100 * math.min(Int.MaxValue / 100, maxDPLLdepth)
+
+ private def advice =
+ s"Please try with scalac -Ypatmat-exhaust-depth ${maxDPLLdepth * 2} or -Ypatmat-exhaust-depth off."
+
+ def recursionDepthReached =
+ s"Exhaustivity analysis reached max recursion depth, not all missing cases are reported.\n($advice)"
+
+ abstract class Exception(val advice: String) extends RuntimeException("CNF budget exceeded")
+
+ object formulaSizeExceeded extends Exception(s"The analysis required more space than allowed.\n$advice")
+
+ }
+
// TODO: remove since deprecated
val budgetProp = scala.sys.Prop[String]("scalac.patmat.analysisBudget")
if (budgetProp.isSet) {
@@ -356,7 +382,23 @@ trait Logic extends Debugging {
// when sym is true, what must hold...
implied foreach (impliedSym => addAxiom(Or(Not(sym), impliedSym)))
// ... and what must not?
- excluded foreach (excludedSym => addAxiom(Or(Not(sym), Not(excludedSym))))
+ excluded foreach {
+ excludedSym =>
+ val related = Set(sym, excludedSym)
+ val exclusive = v.groupedDomains.exists {
+ domain => related subsetOf domain.toSet
+ }
+
+ // TODO: populate `v.exclusiveDomains` with `Set`s from the start, and optimize to:
+ // val exclusive = v.exclusiveDomains.exists { inDomain => inDomain(sym) && inDomain(excludedSym) }
+ if (!exclusive)
+ addAxiom(Or(Not(sym), Not(excludedSym)))
+ }
+ }
+
+ // all symbols in a domain are mutually exclusive
+ v.groupedDomains.foreach {
+ syms => if (syms.size > 1) addAxiom(AtMostOne(syms.toList))
}
}
@@ -385,7 +427,7 @@ trait Logic extends Debugging {
def findModelFor(solvable: Solvable): Model
- def findAllModelsFor(solvable: Solvable): List[Solution]
+ def findAllModelsFor(solvable: Solvable, pos: Position = NoPosition): List[Solution]
}
}
@@ -431,7 +473,9 @@ trait ScalaLogic extends Interface with Logic with TreeAndTypeAnalysis {
// once we go to run-time checks (on Const's), convert them to checkable types
// TODO: there seems to be bug for singleton domains (variable does not show up in model)
lazy val domain: Option[Set[Const]] = {
- val subConsts = enumerateSubtypes(staticTp).map{ tps =>
+ val subConsts =
+ enumerateSubtypes(staticTp, grouped = false)
+ .headOption.map { tps =>
tps.toSet[Type].map{ tp =>
val domainC = TypeConst(tp)
registerEquality(domainC)
@@ -449,6 +493,15 @@ trait ScalaLogic extends Interface with Logic with TreeAndTypeAnalysis {
observed(); allConsts
}
+ lazy val groupedDomains: List[Set[Sym]] = {
+ val subtypes = enumerateSubtypes(staticTp, grouped = true)
+ subtypes.map {
+ subTypes =>
+ val syms = subTypes.flatMap(tpe => symForEqualsTo.get(TypeConst(tpe))).toSet
+ if (mayBeNull) syms + symForEqualsTo(NullConst) else syms
+ }.filter(_.nonEmpty)
+ }
+
// populate equalitySyms
// don't care about the result, but want only one fresh symbol per distinct constant c
def registerEquality(c: Const): Unit = {ensureCanModify(); symForEqualsTo getOrElseUpdate(c, Sym(this, c))}
diff --git a/src/compiler/scala/tools/nsc/transform/patmat/MatchAnalysis.scala b/src/compiler/scala/tools/nsc/transform/patmat/MatchAnalysis.scala
index 34ebbc7463..a11906ace1 100644
--- a/src/compiler/scala/tools/nsc/transform/patmat/MatchAnalysis.scala
+++ b/src/compiler/scala/tools/nsc/transform/patmat/MatchAnalysis.scala
@@ -95,58 +95,84 @@ trait TreeAndTypeAnalysis extends Debugging {
val typer: Typer
// TODO: domain of other feasibly enumerable built-in types (char?)
- def enumerateSubtypes(tp: Type): Option[List[Type]] =
+ def enumerateSubtypes(tp: Type, grouped: Boolean): List[List[Type]] =
tp.typeSymbol match {
// TODO case _ if tp.isTupleType => // recurse into component types?
- case UnitClass =>
- Some(List(UnitTpe))
- case BooleanClass =>
- Some(ConstantTrue :: ConstantFalse :: Nil)
+ case UnitClass if !grouped =>
+ List(List(UnitTpe))
+ case BooleanClass if !grouped =>
+ List(ConstantTrue :: ConstantFalse :: Nil)
// TODO case _ if tp.isTupleType => // recurse into component types
- case modSym: ModuleClassSymbol =>
- Some(List(tp))
+ case modSym: ModuleClassSymbol if !grouped =>
+ List(List(tp))
case sym: RefinementClassSymbol =>
- val parentSubtypes: List[Option[List[Type]]] = tp.parents.map(parent => enumerateSubtypes(parent))
- if (parentSubtypes exists (_.isDefined))
+ val parentSubtypes = tp.parents.flatMap(parent => enumerateSubtypes(parent, grouped))
+ if (parentSubtypes exists (_.nonEmpty)) {
// If any of the parents is enumerable, then the refinement type is enumerable.
- Some(
- // We must only include subtypes of the parents that conform to `tp`.
- // See neg/virtpatmat_exhaust_compound.scala for an example.
- parentSubtypes flatMap (_.getOrElse(Nil)) filter (_ <:< tp)
- )
- else None
+ // We must only include subtypes of the parents that conform to `tp`.
+ // See neg/virtpatmat_exhaust_compound.scala for an example.
+ parentSubtypes map (_.filter(_ <:< tp))
+ }
+ else Nil
// make sure it's not a primitive, else (5: Byte) match { case 5 => ... } sees no Byte
case sym if sym.isSealed =>
- val subclasses = debug.patmatResult(s"enum $sym sealed, subclasses")(
- // symbols which are both sealed and abstract need not be covered themselves, because
- // all of their children must be and they cannot otherwise be created.
- sym.sealedDescendants.toList
- sortBy (_.sealedSortName)
- filterNot (x => x.isSealed && x.isAbstractClass && !isPrimitiveValueClass(x))
- )
val tpApprox = typer.infer.approximateAbstracts(tp)
val pre = tpApprox.prefix
- Some(debug.patmatResult(s"enum sealed tp=$tp, tpApprox=$tpApprox as") {
- // valid subtypes are turned into checkable types, as we are entering the realm of the dynamic
- subclasses flatMap { sym =>
+ def filterChildren(children: List[Symbol]): List[Type] = {
+ children flatMap { sym =>
// have to filter out children which cannot match: see ticket #3683 for an example
// compare to the fully known type `tp` (modulo abstract types),
// so that we can rule out stuff like: sealed trait X[T]; class XInt extends X[Int] --> XInt not valid when enumerating X[String]
// however, must approximate abstract types in
- val memberType = nestedMemberType(sym, pre, tpApprox.typeSymbol.owner)
- val subTp = appliedType(memberType, sym.typeParams.map(_ => WildcardType))
+ val memberType = nestedMemberType(sym, pre, tpApprox.typeSymbol.owner)
+ val subTp = appliedType(memberType, sym.typeParams.map(_ => WildcardType))
val subTpApprox = typer.infer.approximateAbstracts(subTp) // TODO: needed?
// debug.patmat("subtp"+(subTpApprox <:< tpApprox, subTpApprox, tpApprox))
if (subTpApprox <:< tpApprox) Some(checkableType(subTp))
else None
}
- })
+ }
+
+ if(grouped) {
+ def enumerateChildren(sym: Symbol) = {
+ sym.children.toList
+ .sortBy(_.sealedSortName)
+ .filterNot(x => x.isSealed && x.isAbstractClass && !isPrimitiveValueClass(x))
+ }
+
+ // enumerate only direct subclasses,
+ // subclasses of subclasses are enumerated in the next iteration
+ // and added to a new group
+ def groupChildren(wl: List[Symbol],
+ acc: List[List[Type]]): List[List[Type]] = wl match {
+ case hd :: tl =>
+ val children = enumerateChildren(hd)
+ groupChildren(tl ++ children, acc :+ filterChildren(children))
+ case Nil => acc
+ }
+
+ groupChildren(sym :: Nil, Nil)
+ } else {
+ val subclasses = debug.patmatResult(s"enum $sym sealed, subclasses")(
+ // symbols which are both sealed and abstract need not be covered themselves, because
+ // all of their children must be and they cannot otherwise be created.
+ sym.sealedDescendants.toList
+ sortBy (_.sealedSortName)
+ filterNot (x => x.isSealed && x.isAbstractClass && !isPrimitiveValueClass(x))
+ )
+
+ List(debug.patmatResult(s"enum sealed tp=$tp, tpApprox=$tpApprox as") {
+ // valid subtypes are turned into checkable types, as we are entering the realm of the dynamic
+ filterChildren(subclasses)
+ })
+ }
+
case sym =>
debug.patmat("enum unsealed "+ ((tp, sym, sym.isSealed, isPrimitiveValueClass(sym))))
- None
+ Nil
}
// approximate a type to the static type that is fully checkable at run time,
@@ -176,7 +202,7 @@ trait TreeAndTypeAnalysis extends Debugging {
def uncheckableType(tp: Type): Boolean = {
val checkable = (
(isTupleType(tp) && tupleComponents(tp).exists(tp => !uncheckableType(tp)))
- || enumerateSubtypes(tp).nonEmpty)
+ || enumerateSubtypes(tp, grouped = false).nonEmpty)
// if (!checkable) debug.patmat("deemed uncheckable: "+ tp)
!checkable
}
@@ -399,6 +425,7 @@ trait MatchAnalysis extends MatchApproximation {
trait MatchAnalyzer extends MatchApproximator {
def uncheckedWarning(pos: Position, msg: String) = currentRun.reporting.uncheckedWarning(pos, msg)
+ def warn(pos: Position, ex: AnalysisBudget.Exception, kind: String) = uncheckedWarning(pos, s"Cannot check match for $kind.\n${ex.advice}")
def reportWarning(message: String) = global.reporter.warning(typer.context.tree.pos, message)
// TODO: model dependencies between variables: if V1 corresponds to (x: List[_]) and V2 is (x.hd), V2 cannot be assigned when V1 = null or V1 = Nil
@@ -429,44 +456,50 @@ trait MatchAnalysis extends MatchApproximation {
val propsCasesOk = approximate(True) map caseWithoutBodyToProp
val propsCasesFail = approximate(False) map (t => Not(caseWithoutBodyToProp(t)))
- val (eqAxiomsFail, symbolicCasesFail) = removeVarEq(propsCasesFail, modelNull = true)
- val (eqAxiomsOk, symbolicCasesOk) = removeVarEq(propsCasesOk, modelNull = true)
- val eqAxioms = simplify(And(eqAxiomsOk, eqAxiomsFail)) // I'm pretty sure eqAxiomsOk == eqAxiomsFail, but not 100% sure.
-
- val prefix = mutable.ArrayBuffer[Prop]()
- prefix += eqAxioms
-
- var prefixRest = symbolicCasesFail
- var current = symbolicCasesOk
- var reachable = true
- var caseIndex = 0
-
- debug.patmat("reachability, vars:\n" + ((propsCasesFail flatMap gatherVariables).distinct map (_.describe) mkString ("\n")))
- debug.patmat(s"equality axioms:\n$eqAxiomsOk")
-
- // invariant (prefixRest.length == current.length) && (prefix.reverse ++ prefixRest == symbolicCasesFail)
- // termination: prefixRest.length decreases by 1
- while (prefixRest.nonEmpty && reachable) {
- val prefHead = prefixRest.head
- caseIndex += 1
- prefixRest = prefixRest.tail
- if (prefixRest.isEmpty) reachable = true
- else {
- prefix += prefHead
- current = current.tail
+ try {
+ val (eqAxiomsFail, symbolicCasesFail) = removeVarEq(propsCasesFail, modelNull = true)
+ val (eqAxiomsOk, symbolicCasesOk) = removeVarEq(propsCasesOk, modelNull = true)
+ val eqAxioms = simplify(And(eqAxiomsOk, eqAxiomsFail)) // I'm pretty sure eqAxiomsOk == eqAxiomsFail, but not 100% sure.
+
+ val prefix = mutable.ArrayBuffer[Prop]()
+ prefix += eqAxioms
+
+ var prefixRest = symbolicCasesFail
+ var current = symbolicCasesOk
+ var reachable = true
+ var caseIndex = 0
+
+ debug.patmat("reachability, vars:\n" + ((propsCasesFail flatMap gatherVariables).distinct map (_.describe) mkString ("\n")))
+ debug.patmat(s"equality axioms:\n$eqAxiomsOk")
+
+ // invariant (prefixRest.length == current.length) && (prefix.reverse ++ prefixRest == symbolicCasesFail)
+ // termination: prefixRest.length decreases by 1
+ while (prefixRest.nonEmpty && reachable) {
+ val prefHead = prefixRest.head
+ caseIndex += 1
+ prefixRest = prefixRest.tail
+ if (prefixRest.isEmpty) reachable = true
+ else {
+ prefix += prefHead
+ current = current.tail
val and = And((current.head +: prefix): _*)
val model = findModelFor(eqFreePropToSolvable(and))
- // debug.patmat("trying to reach:\n"+ cnfString(current.head) +"\nunder prefix:\n"+ cnfString(prefix))
- // if (NoModel ne model) debug.patmat("reached: "+ modelString(model))
+ // debug.patmat("trying to reach:\n"+ cnfString(current.head) +"\nunder prefix:\n"+ cnfString(prefix))
+ // if (NoModel ne model) debug.patmat("reached: "+ modelString(model))
- reachable = NoModel ne model
+ reachable = NoModel ne model
+ }
}
- }
- if (Statistics.canEnable) Statistics.stopTimer(patmatAnaReach, start)
+ if (Statistics.canEnable) Statistics.stopTimer(patmatAnaReach, start)
- if (reachable) None else Some(caseIndex)
+ if (reachable) None else Some(caseIndex)
+ } catch {
+ case ex: AnalysisBudget.Exception =>
+ warn(prevBinder.pos, ex, "unreachability")
+ None // CNF budget exceeded
+ }
}
// exhaustivity
@@ -507,32 +540,38 @@ trait MatchAnalysis extends MatchApproximation {
// when does the match fail?
val matchFails = Not(\/(symbolicCases))
- // debug output:
+ // debug output:
debug.patmat("analysing:")
showTreeMakers(cases)
// debug.patmat("\nvars:\n"+ (vars map (_.describe) mkString ("\n")))
// debug.patmat("\nmatchFails as CNF:\n"+ cnfString(propToSolvable(matchFails)))
- // find the models (under which the match fails)
- val matchFailModels = findAllModelsFor(propToSolvable(matchFails))
+ try {
+ // find the models (under which the match fails)
+ val matchFailModels = findAllModelsFor(propToSolvable(matchFails), prevBinder.pos)
- val scrutVar = Var(prevBinderTree)
- val counterExamples = {
- matchFailModels.flatMap {
- model =>
- val varAssignments = expandModel(model)
- varAssignments.flatMap(modelToCounterExample(scrutVar) _)
+ val scrutVar = Var(prevBinderTree)
+ val counterExamples = {
+ matchFailModels.flatMap {
+ model =>
+ val varAssignments = expandModel(model)
+ varAssignments.flatMap(modelToCounterExample(scrutVar) _)
+ }
}
- }
-
- // sorting before pruning is important here in order to
- // keep neg/t7020.scala stable
- // since e.g. List(_, _) would cover List(1, _)
- val pruned = CounterExample.prune(counterExamples.sortBy(_.toString)).map(_.toString)
- if (Statistics.canEnable) Statistics.stopTimer(patmatAnaExhaust, start)
- pruned
+ // sorting before pruning is important here in order to
+ // keep neg/t7020.scala stable
+ // since e.g. List(_, _) would cover List(1, _)
+ val pruned = CounterExample.prune(counterExamples.sortBy(_.toString)).map(_.toString)
+
+ if (Statistics.canEnable) Statistics.stopTimer(patmatAnaExhaust, start)
+ pruned
+ } catch {
+ case ex: AnalysisBudget.Exception =>
+ warn(prevBinder.pos, ex, "exhaustivity")
+ Nil // CNF budget exceeded
+ }
}
}
diff --git a/src/compiler/scala/tools/nsc/transform/patmat/MatchTreeMaking.scala b/src/compiler/scala/tools/nsc/transform/patmat/MatchTreeMaking.scala
index b703b5bc6d..e1fe220556 100644
--- a/src/compiler/scala/tools/nsc/transform/patmat/MatchTreeMaking.scala
+++ b/src/compiler/scala/tools/nsc/transform/patmat/MatchTreeMaking.scala
@@ -577,8 +577,6 @@ trait MatchTreeMaking extends MatchCodeGen with Debugging {
lengthMax3(casesNoSubstOnly) > 2
}
val requireSwitch = hasSwitchAnnotation && exceedsTwoCasesOrAlts
- if (hasSwitchAnnotation && !requireSwitch)
- reporter.warning(scrut.pos, "matches with two cases or fewer are emitted using if-then-else instead of switch")
(suppression, requireSwitch)
case _ =>
(Suppression.NoSuppression, false)
diff --git a/src/compiler/scala/tools/nsc/transform/patmat/Solving.scala b/src/compiler/scala/tools/nsc/transform/patmat/Solving.scala
index 27217f0dc2..9710c5c66b 100644
--- a/src/compiler/scala/tools/nsc/transform/patmat/Solving.scala
+++ b/src/compiler/scala/tools/nsc/transform/patmat/Solving.scala
@@ -11,6 +11,7 @@ import scala.reflect.internal.util.Statistics
import scala.language.postfixOps
import scala.collection.mutable
import scala.reflect.internal.util.Collections._
+import scala.reflect.internal.util.Position
// a literal is a (possibly negated) variable
class Lit(val v: Int) extends AnyVal {
@@ -64,7 +65,23 @@ trait Solving extends Logic {
def size = symbols.size
}
- case class Solvable(cnf: Cnf, symbolMapping: SymbolMapping)
+ def cnfString(f: Array[Clause]): String
+
+ final case class Solvable(cnf: Cnf, symbolMapping: SymbolMapping) {
+ def ++(other: Solvable) = {
+ require(this.symbolMapping eq other.symbolMapping)
+ Solvable(cnf ++ other.cnf, symbolMapping)
+ }
+
+ override def toString: String = {
+ "Solvable\nLiterals:\n" +
+ (for {
+ (lit, sym) <- symbolMapping.symForVar.toSeq.sortBy(_._1)
+ } yield {
+ s"$lit -> $sym"
+ }).mkString("\n") + "Cnf:\n" + cnfString(cnf)
+ }
+ }
trait CnfBuilder {
private[this] val buff = ArrayBuffer[Clause]()
@@ -95,7 +112,11 @@ trait Solving extends Logic {
}
}
- def buildCnf: Array[Clause] = buff.toArray
+ def buildCnf: Array[Clause] = {
+ val cnf = buff.toArray
+ buff.clear()
+ cnf
+ }
}
@@ -130,20 +151,23 @@ trait Solving extends Logic {
def apply(p: Prop): Solvable = {
- def convert(p: Prop): Lit = {
+ def convert(p: Prop): Option[Lit] = {
p match {
case And(fv) =>
- and(fv.map(convert))
+ Some(and(fv.flatMap(convert)))
case Or(fv) =>
- or(fv.map(convert))
+ Some(or(fv.flatMap(convert)))
case Not(a) =>
- not(convert(a))
+ convert(a).map(not)
case sym: Sym =>
- convertSym(sym)
+ Some(convertSym(sym))
case True =>
- constTrue
+ Some(constTrue)
case False =>
- constFalse
+ Some(constFalse)
+ case AtMostOne(ops) =>
+ atMostOne(ops)
+ None
case _: Eq =>
throw new MatchError(p)
}
@@ -189,8 +213,57 @@ trait Solving extends Logic {
// no need for auxiliary variable
def not(a: Lit): Lit = -a
+ /**
+ * This encoding adds 3n-4 variables auxiliary variables
+ * to encode that at most 1 symbol can be set.
+ * See also "Towards an Optimal CNF Encoding of Boolean Cardinality Constraints"
+ * http://www.carstensinz.de/papers/CP-2005.pdf
+ */
+ def atMostOne(ops: List[Sym]) {
+ (ops: @unchecked) match {
+ case hd :: Nil => convertSym(hd)
+ case x1 :: tail =>
+ // sequential counter: 3n-4 clauses
+ // pairwise encoding: n*(n-1)/2 clauses
+ // thus pays off only if n > 5
+ if (ops.lengthCompare(5) > 0) {
+
+ @inline
+ def /\(a: Lit, b: Lit) = addClauseProcessed(clause(a, b))
+
+ val (mid, xn :: Nil) = tail.splitAt(tail.size - 1)
+
+ // 1 <= x1,...,xn <==>
+ //
+ // (!x1 \/ s1) /\ (!xn \/ !sn-1) /\
+ //
+ // /\
+ // / \ (!xi \/ si) /\ (!si-1 \/ si) /\ (!xi \/ !si-1)
+ // 1 < i < n
+ val s1 = newLiteral()
+ /\(-convertSym(x1), s1)
+ val snMinus = mid.foldLeft(s1) {
+ case (siMinus, sym) =>
+ val xi = convertSym(sym)
+ val si = newLiteral()
+ /\(-xi, si)
+ /\(-siMinus, si)
+ /\(-xi, -siMinus)
+ si
+ }
+ /\(-convertSym(xn), -snMinus)
+ } else {
+ ops.map(convertSym).combinations(2).foreach {
+ case a :: b :: Nil =>
+ addClauseProcessed(clause(-a, -b))
+ case _ =>
+ }
+ }
+ }
+ }
+
// add intermediate variable since we want the formula to be SAT!
- addClauseProcessed(clause(convert(p)))
+ addClauseProcessed(convert(p).toSet)
Solvable(buildCnf, symbolMapping)
}
@@ -244,19 +317,54 @@ trait Solving extends Logic {
def eqFreePropToSolvable(p: Prop): Solvable = {
+ def doesFormulaExceedSize(p: Prop): Boolean = {
+ p match {
+ case And(ops) =>
+ if (ops.size > AnalysisBudget.maxFormulaSize) {
+ true
+ } else {
+ ops.exists(doesFormulaExceedSize)
+ }
+ case Or(ops) =>
+ if (ops.size > AnalysisBudget.maxFormulaSize) {
+ true
+ } else {
+ ops.exists(doesFormulaExceedSize)
+ }
+ case Not(a) => doesFormulaExceedSize(a)
+ case _ => false
+ }
+ }
+
+ val simplified = simplify(p)
+ if (doesFormulaExceedSize(simplified)) {
+ throw AnalysisBudget.formulaSizeExceeded
+ }
+
// collect all variables since after simplification / CNF conversion
// they could have been removed from the formula
val symbolMapping = new SymbolMapping(gatherSymbols(p))
-
- val simplified = simplify(p)
val cnfExtractor = new AlreadyInCNF(symbolMapping)
+ val cnfTransformer = new TransformToCnf(symbolMapping)
+
+ def cnfFor(prop: Prop): Solvable = {
+ prop match {
+ case cnfExtractor.ToCnf(solvable) =>
+ // this is needed because t6942 would generate too many clauses with Tseitin
+ // already in CNF, just add clauses
+ solvable
+ case p =>
+ cnfTransformer.apply(p)
+ }
+ }
+
simplified match {
- case cnfExtractor.ToCnf(solvable) =>
- // this is needed because t6942 would generate too many clauses with Tseitin
- // already in CNF, just add clauses
- solvable
- case p =>
- new TransformToCnf(symbolMapping).apply(p)
+ case And(props) =>
+ // SI-6942:
+ // CNF(P1 /\ ... /\ PN) == CNF(P1) ++ CNF(...) ++ CNF(PN)
+ props.map(cnfFor).reduce(_ ++ _)
+ case p =>
+ cnfFor(p)
}
}
}
@@ -288,7 +396,7 @@ trait Solving extends Logic {
val NoTseitinModel: TseitinModel = null
// returns all solutions, if any (TODO: better infinite recursion backstop -- detect fixpoint??)
- def findAllModelsFor(solvable: Solvable): List[Solution] = {
+ def findAllModelsFor(solvable: Solvable, pos: Position): List[Solution] = {
debug.patmat("find all models for\n"+ cnfString(solvable.cnf))
// we must take all vars from non simplified formula
@@ -308,13 +416,12 @@ trait Solving extends Logic {
final case class TseitinSolution(model: TseitinModel, unassigned: List[Int]) {
def projectToSolution(symForVar: Map[Int, Sym]) = Solution(projectToModel(model, symForVar), unassigned map symForVar)
}
+
def findAllModels(clauses: Array[Clause],
models: List[TseitinSolution],
- recursionDepthAllowed: Int = global.settings.YpatmatExhaustdepth.value): List[TseitinSolution]=
+ recursionDepthAllowed: Int = AnalysisBudget.maxDPLLdepth): List[TseitinSolution]=
if (recursionDepthAllowed == 0) {
- val maxDPLLdepth = global.settings.YpatmatExhaustdepth.value
- reportWarning("(Exhaustivity analysis reached max recursion depth, not all missing cases are reported. " +
- s"Please try with scalac -Ypatmat-exhaust-depth ${maxDPLLdepth * 2} or -Ypatmat-exhaust-depth off.)")
+ uncheckedWarning(pos, AnalysisBudget.recursionDepthReached)
models
} else {
debug.patmat("find all models for\n" + cnfString(clauses))
diff --git a/src/compiler/scala/tools/nsc/typechecker/AnalyzerPlugins.scala b/src/compiler/scala/tools/nsc/typechecker/AnalyzerPlugins.scala
index 2c27bdb03a..0574869714 100644
--- a/src/compiler/scala/tools/nsc/typechecker/AnalyzerPlugins.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/AnalyzerPlugins.scala
@@ -57,7 +57,7 @@ trait AnalyzerPlugins { self: Analyzer =>
* `analyzer.transformed` hash map, indexed by the definition's rhs tree.
*
* NOTE: Invoking the type checker can lead to cyclic reference errors. For instance, if this
- * method is called from the type completer of a recursive method, type checking the mehtod
+ * method is called from the type completer of a recursive method, type checking the method
* rhs will invoke the same completer again. It might be possible to avoid this situation by
* assigning `tpe` to `defTree.symbol` (untested) - the final type computed by this method
* will then be assigned to the definition's symbol by monoTypeCompleter (in Namers).
diff --git a/src/compiler/scala/tools/nsc/typechecker/Contexts.scala b/src/compiler/scala/tools/nsc/typechecker/Contexts.scala
index ca25e59c4b..542f58795a 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Contexts.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Contexts.scala
@@ -167,7 +167,7 @@ trait Contexts { self: Analyzer =>
* afterwards errors are thrown. This is configured in `rootContext`. Additionally, more
* fine grained control is needed based on the kind of error; ambiguity errors are often
* suppressed during exploratory typing, such as determining whether `a == b` in an argument
- * position is an assignment or a named argument, when `Infererencer#isApplicableSafe` type checks
+ * position is an assignment or a named argument, when `Inferencer#isApplicableSafe` type checks
* applications with and without an expected type, or whtn `Typer#tryTypedApply` tries to fit arguments to
* a function type with/without implicit views.
*
@@ -1108,10 +1108,10 @@ trait Contexts { self: Analyzer =>
//
// A type-import-on-demand declaration never causes any other declaration to be shadowed.
//
- // Scala: Bindings of different kinds have a precedence defined on them:
+ // Scala: Bindings of different kinds have a precedence defined on them:
//
- // 1) Definitions and declarations that are local, inherited, or made available by a
- // package clause in the same compilation unit where the definition occurs have
+ // 1) Definitions and declarations that are local, inherited, or made available by a
+ // package clause in the same compilation unit where the definition occurs have
// highest precedence.
// 2) Explicit imports have next highest precedence.
def depthOk(imp: ImportInfo) = (
diff --git a/src/compiler/scala/tools/nsc/typechecker/Infer.scala b/src/compiler/scala/tools/nsc/typechecker/Infer.scala
index cf97474d9a..f9582a54ff 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Infer.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Infer.scala
@@ -376,7 +376,7 @@ trait Infer extends Checkable {
}
/** Overload which allocates fresh type vars.
* The other one exists because apparently inferExprInstance needs access to the typevars
- * after the call, and its wasteful to return a tuple and throw it away almost every time.
+ * after the call, and it's wasteful to return a tuple and throw it away almost every time.
*/
private def exprTypeArgs(tparams: List[Symbol], restpe: Type, pt: Type, useWeaklyCompatible: Boolean): List[Type] =
exprTypeArgs(tparams map freshVar, tparams, restpe, pt, useWeaklyCompatible)
@@ -553,9 +553,8 @@ trait Infer extends Checkable {
// ...or lower bound of a type param, since they're asking for it.
def canWarnAboutAny = {
val loBounds = tparams map (_.info.bounds.lo)
- val hasAny = pt :: restpe :: formals ::: argtpes ::: loBounds exists (t =>
- (t contains AnyClass) || (t contains AnyValClass)
- )
+ def containsAny(t: Type) = (t contains AnyClass) || (t contains AnyValClass)
+ val hasAny = pt :: restpe :: formals ::: argtpes ::: loBounds exists (_.dealiasWidenChain exists containsAny)
!hasAny
}
def argumentPosition(idx: Int): Position = context.tree match {
diff --git a/src/compiler/scala/tools/nsc/typechecker/Namers.scala b/src/compiler/scala/tools/nsc/typechecker/Namers.scala
index 24238b8e41..77c49a862a 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Namers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Namers.scala
@@ -1125,7 +1125,7 @@ trait Namers extends MethodSynthesis {
for (vparam <- vparams) {
if (vparam.tpt.isEmpty) {
val overriddenParamTp = overriddenParams.head.tpe
- // references to type parameteres in overriddenParamTp link to the type skolems, so the
+ // references to type parameters in overriddenParamTp link to the type skolems, so the
// assigned type is consistent with the other / existing parameter types in vparamSymss.
vparam.symbol setInfo overriddenParamTp
vparam.tpt defineType overriddenParamTp setPos vparam.pos.focus
diff --git a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala
index 5abfbe850f..a3a4c70d1e 100644
--- a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala
@@ -584,7 +584,7 @@ abstract class RefChecks extends InfoTransform with scala.reflect.internal.trans
!other.isDeferred && other.isJavaDefined && !sym.enclClass.isSubClass(other.enclClass) && {
// #3622: erasure operates on uncurried types --
// note on passing sym in both cases: only sym.isType is relevant for uncurry.transformInfo
- // !!! erasure.erasure(sym, uncurry.transformInfo(sym, tp)) gives erreneous of inaccessible type - check whether that's still the case!
+ // !!! erasure.erasure(sym, uncurry.transformInfo(sym, tp)) gives erroneous or inaccessible type - check whether that's still the case!
def uncurryAndErase(tp: Type) = erasure.erasure(sym)(uncurry.transformInfo(sym, tp))
val tp1 = uncurryAndErase(clazz.thisType.memberType(sym))
val tp2 = uncurryAndErase(clazz.thisType.memberType(other))
diff --git a/src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala b/src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala
index db81eecdf5..e0d96df062 100644
--- a/src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala
@@ -322,7 +322,7 @@ abstract class SuperAccessors extends transform.Transform with transform.TypingT
case Super(_, mix) =>
if (sym.isValue && !sym.isMethod || sym.hasAccessorFlag) {
if (!settings.overrideVars)
- reporter.error(tree.pos, "super may be not be used on " + sym.accessedOrSelf)
+ reporter.error(tree.pos, "super may not be used on " + sym.accessedOrSelf)
} else if (isDisallowed(sym)) {
reporter.error(tree.pos, "super not allowed here: use this." + name.decode + " instead")
}
diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
index 391ef9e337..27a574a449 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
@@ -4301,7 +4301,7 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper
val selector1 = atPos(tree.pos.focusStart) { if (arity == 1) ids.head else gen.mkTuple(ids) }
// SI-8120 If we don't duplicate the cases, the original Match node will share trees with ones that
// receive symbols owned by this function. However if, after a silent mode session, we discard
- // this Function and try a different approach (e.g. applying a view to the reciever) we end up
+ // this Function and try a different approach (e.g. applying a view to the receiver) we end up
// with orphaned symbols which blows up far down the pipeline (or can be detected with -Ycheck:typer).
val body = treeCopy.Match(tree, selector1, (cases map duplicateAndKeepPositions).asInstanceOf[List[CaseDef]])
typed1(atPos(tree.pos) { Function(params, body) }, mode, pt)
@@ -4881,10 +4881,11 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper
(// this -> Foo.this
if (sym.isThisSym)
typed1(This(sym.owner) setPos tree.pos, mode, pt)
- // Inferring classOf type parameter from expected type. Otherwise an
- // actual call to the stubbed classOf method is generated, returning null.
- else if (isPredefClassOf(sym) && pt.typeSymbol == ClassClass && pt.typeArgs.nonEmpty)
- typedClassOf(tree, TypeTree(pt.typeArgs.head))
+ else if (isPredefClassOf(sym) && pt.typeSymbol == ClassClass && pt.typeArgs.nonEmpty) {
+ // Inferring classOf type parameter from expected type. Otherwise an
+ // actual call to the stubbed classOf method is generated, returning null.
+ typedClassOf(tree, TypeTree(pt.typeArgs.head).setPos(tree.pos.focus))
+ }
else {
val pre1 = if (sym.isTopLevel) sym.owner.thisType else if (qual == EmptyTree) NoPrefix else qual.tpe
val tree1 = if (qual == EmptyTree) tree else atPos(tree.pos)(Select(atPos(tree.pos.focusStart)(qual), name))
diff --git a/src/interactive/scala/tools/nsc/interactive/CompilerControl.scala b/src/interactive/scala/tools/nsc/interactive/CompilerControl.scala
index 2e4f6b08e9..9caebb711d 100644
--- a/src/interactive/scala/tools/nsc/interactive/CompilerControl.scala
+++ b/src/interactive/scala/tools/nsc/interactive/CompilerControl.scala
@@ -302,7 +302,7 @@ trait CompilerControl { self: Global =>
abstract class WorkItem extends (() => Unit) {
val onCompilerThread = self.onCompilerThread
- /** Raise a MissingReponse, if the work item carries a response. */
+ /** Raise a MissingResponse, if the work item carries a response. */
def raiseMissing(): Unit
}
diff --git a/src/interactive/scala/tools/nsc/interactive/Global.scala b/src/interactive/scala/tools/nsc/interactive/Global.scala
index 2d09435f60..727bfdd510 100644
--- a/src/interactive/scala/tools/nsc/interactive/Global.scala
+++ b/src/interactive/scala/tools/nsc/interactive/Global.scala
@@ -315,7 +315,7 @@ class Global(settings: Settings, _reporter: Reporter, projectName: String = "")
private val NoResponse: Response[_] = new Response[Any]
/** The response that is currently pending, i.e. the compiler
- * is working on providing an asnwer for it.
+ * is working on providing an answer for it.
*/
private var pendingResponse: Response[_] = NoResponse
diff --git a/src/interactive/scala/tools/nsc/interactive/Lexer.scala b/src/interactive/scala/tools/nsc/interactive/Lexer.scala
index 82e8de3f3d..7daf24c204 100644
--- a/src/interactive/scala/tools/nsc/interactive/Lexer.scala
+++ b/src/interactive/scala/tools/nsc/interactive/Lexer.scala
@@ -195,7 +195,7 @@ class Lexer(rd: Reader) {
case 'n' => putAcceptString("null"); token = NullLit
case '"' => getString()
case '-' | '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9' => getNumber()
- case _ => error("unrecoginezed start of token: '"+ch+"'")
+ case _ => error("unrecognized start of token: '"+ch+"'")
}
//println("["+token+"]")
}
diff --git a/src/library/scala/Mutable.scala b/src/library/scala/Mutable.scala
index 8ef0424db6..43f98ee4df 100644
--- a/src/library/scala/Mutable.scala
+++ b/src/library/scala/Mutable.scala
@@ -11,7 +11,7 @@
package scala
/**
- * A marker trait for mutable datatructures such as mutable collections
+ * A marker trait for mutable data structures such as mutable collections
*
* @since 2.8
*/
diff --git a/src/library/scala/Predef.scala b/src/library/scala/Predef.scala
index bf7739345e..42448b38f2 100644
--- a/src/library/scala/Predef.scala
+++ b/src/library/scala/Predef.scala
@@ -58,7 +58,7 @@ import scala.io.StdIn
* condition fails, then the caller of the function is to blame rather than a
* logical error having been made within `addNaturals` itself. `ensures` is a
* form of `assert` that declares the guarantee the function is providing with
- * regards to it's return value.
+ * regards to its return value.
*
* === Implicit Conversions ===
* A number of commonly applied implicit conversions are also defined here, and
@@ -85,7 +85,7 @@ object Predef extends LowPriorityImplicits with DeprecatedPredef {
type String = java.lang.String
type Class[T] = java.lang.Class[T]
- // miscelleaneous -----------------------------------------------------
+ // miscellaneous -----------------------------------------------------
scala.`package` // to force scala package object to be seen.
scala.collection.immutable.List // to force Nil, :: to be seen.
diff --git a/src/library/scala/annotation/switch.scala b/src/library/scala/annotation/switch.scala
index 23e3923407..00124cf88b 100644
--- a/src/library/scala/annotation/switch.scala
+++ b/src/library/scala/annotation/switch.scala
@@ -22,6 +22,9 @@ package scala.annotation
}
}}}
*
+ * Note: for pattern matches with one or two cases, the compiler generates jump instructions.
+ * Annotating such a match with `@switch` does not issue any warning.
+ *
* @author Paul Phillips
* @since 2.8
*/
diff --git a/src/library/scala/collection/GenTraversableOnce.scala b/src/library/scala/collection/GenTraversableOnce.scala
index 8c7c754af8..f77462ce88 100644
--- a/src/library/scala/collection/GenTraversableOnce.scala
+++ b/src/library/scala/collection/GenTraversableOnce.scala
@@ -278,7 +278,7 @@ trait GenTraversableOnce[+A] extends Any {
*
* @param op the binary operator.
* @tparam B the result type of the binary operator.
- * @return an option value containing the result of `reduceLeft(op)` is this $coll is nonempty,
+ * @return an option value containing the result of `reduceLeft(op)` if this $coll is nonempty,
* `None` otherwise.
*/
def reduceLeftOption[B >: A](op: (B, A) => B): Option[B]
@@ -290,7 +290,7 @@ trait GenTraversableOnce[+A] extends Any {
*
* @param op the binary operator.
* @tparam B the result type of the binary operator.
- * @return an option value containing the result of `reduceRight(op)` is this $coll is nonempty,
+ * @return an option value containing the result of `reduceRight(op)` if this $coll is nonempty,
* `None` otherwise.
*/
def reduceRightOption[B >: A](op: (A, B) => B): Option[B]
diff --git a/src/library/scala/collection/SeqLike.scala b/src/library/scala/collection/SeqLike.scala
index 66fce0f902..b775480532 100644
--- a/src/library/scala/collection/SeqLike.scala
+++ b/src/library/scala/collection/SeqLike.scala
@@ -413,7 +413,7 @@ trait SeqLike[+A, +Repr] extends Any with IterableLike[A, Repr] with GenSeqLike[
* @inheritdoc
*
* Another way to express this
- * is that `xs union ys` computes the order-presevring multi-set union of `xs` and `ys`.
+ * is that `xs union ys` computes the order-preserving multi-set union of `xs` and `ys`.
* `union` is hence a counter-part of `diff` and `intersect` which also work on multi-sets.
*
* $willNotTerminateInf
diff --git a/src/library/scala/collection/TraversableLike.scala b/src/library/scala/collection/TraversableLike.scala
index 32d31f0be8..96374ef653 100644
--- a/src/library/scala/collection/TraversableLike.scala
+++ b/src/library/scala/collection/TraversableLike.scala
@@ -54,7 +54,7 @@ import scala.language.higherKinds
* `HashMap` of objects. The traversal order for hash maps will
* depend on the hash codes of its elements, and these hash codes might
* differ from one run to the next. By contrast, a `LinkedHashMap`
- * is ordered because it's `foreach` method visits elements in the
+ * is ordered because its `foreach` method visits elements in the
* order they were inserted into the `HashMap`.
*
* @author Martin Odersky
diff --git a/src/library/scala/collection/TraversableOnce.scala b/src/library/scala/collection/TraversableOnce.scala
index 2eab58009c..c5b0d0f085 100644
--- a/src/library/scala/collection/TraversableOnce.scala
+++ b/src/library/scala/collection/TraversableOnce.scala
@@ -128,8 +128,21 @@ trait TraversableOnce[+A] extends Any with GenTraversableOnce[A] {
* @example `Seq("a", 1, 5L).collectFirst({ case x: Int => x*10 }) = Some(10)`
*/
def collectFirst[B](pf: PartialFunction[A, B]): Option[B] = {
- // make sure to use an iterator or `seq`
- self.toIterator.foreach(pf.runWith(b => return Some(b)))
+ // TODO 2.12 -- move out alternate implementations into child classes
+ val i: Iterator[A] = self match {
+ case it: Iterator[A] => it
+ case _: GenIterable[_] => self.toIterator // If it might be parallel, be sure to .seq or use iterator!
+ case _ => // Not parallel, not iterable--just traverse
+ self.foreach(pf.runWith(b => return Some(b)))
+ return None
+ }
+ // Presumably the fastest way to get in and out of a partial function is for a sentinel function to return itself
+ // (Tested to be lower-overhead than runWith. Would be better yet to not need to (formally) allocate it--change in 2.12.)
+ val sentinel: Function1[A, Any] = new scala.runtime.AbstractFunction1[A, Any]{ def apply(a: A) = this }
+ while (i.hasNext) {
+ val x = pf.applyOrElse(i.next, sentinel)
+ if (x.asInstanceOf[AnyRef] ne sentinel) return Some(x.asInstanceOf[B])
+ }
None
}
diff --git a/src/library/scala/collection/concurrent/Map.scala b/src/library/scala/collection/concurrent/Map.scala
index 2eea15b8dc..cfb567abe9 100644
--- a/src/library/scala/collection/concurrent/Map.scala
+++ b/src/library/scala/collection/concurrent/Map.scala
@@ -49,7 +49,7 @@ trait Map[A, B] extends scala.collection.mutable.Map[A, B] {
def putIfAbsent(k: A, v: B): Option[B]
/**
- * Removes the entry for the specified key if its currently mapped to the
+ * Removes the entry for the specified key if it's currently mapped to the
* specified value.
*
* $atomicop
diff --git a/src/library/scala/collection/immutable/Stream.scala b/src/library/scala/collection/immutable/Stream.scala
index f303e79bb3..cf7b7e272a 100644
--- a/src/library/scala/collection/immutable/Stream.scala
+++ b/src/library/scala/collection/immutable/Stream.scala
@@ -360,7 +360,7 @@ self =>
* `List(BigInt(12)) ++ fibs`.
*
* @tparam B The element type of the returned collection.'''That'''
- * @param that The [[scala.collection.GenTraversableOnce]] the be contatenated
+ * @param that The [[scala.collection.GenTraversableOnce]] the be concatenated
* to this `Stream`.
* @return A new collection containing the result of concatenating `this` with
* `that`.
diff --git a/src/library/scala/collection/mutable/AVLTree.scala b/src/library/scala/collection/mutable/AVLTree.scala
index cc2acb74d4..b63d0aae33 100644
--- a/src/library/scala/collection/mutable/AVLTree.scala
+++ b/src/library/scala/collection/mutable/AVLTree.scala
@@ -27,7 +27,7 @@ private[mutable] sealed trait AVLTree[+A] extends Serializable {
/**
* Returns a new tree containing the given element.
- * Thows an IllegalArgumentException if element is already present.
+ * Throws an IllegalArgumentException if element is already present.
*
*/
def insert[B >: A](value: B, ordering: Ordering[B]): AVLTree[B] = Node(value, Leaf, Leaf)
@@ -95,7 +95,7 @@ private case class Node[A](data: A, left: AVLTree[A], right: AVLTree[A]) extends
/**
* Returns a new tree containing the given element.
- * Thows an IllegalArgumentException if element is already present.
+ * Throws an IllegalArgumentException if element is already present.
*
*/
override def insert[B >: A](value: B, ordering: Ordering[B]) = {
diff --git a/src/library/scala/collection/mutable/HashTable.scala b/src/library/scala/collection/mutable/HashTable.scala
index 65d9c35052..b48a32fa37 100644
--- a/src/library/scala/collection/mutable/HashTable.scala
+++ b/src/library/scala/collection/mutable/HashTable.scala
@@ -449,7 +449,7 @@ private[collection] object HashTable {
// h
/* OLD VERSION
- * quick, but bad for sequence 0-10000 - little enthropy in higher bits
+ * quick, but bad for sequence 0-10000 - little entropy in higher bits
* since 2003 */
// var h: Int = hcode + ~(hcode << 9)
// h = h ^ (h >>> 14)
diff --git a/src/library/scala/collection/mutable/UnrolledBuffer.scala b/src/library/scala/collection/mutable/UnrolledBuffer.scala
index 1fda318e51..2212486bcf 100644
--- a/src/library/scala/collection/mutable/UnrolledBuffer.scala
+++ b/src/library/scala/collection/mutable/UnrolledBuffer.scala
@@ -85,7 +85,7 @@ extends scala.collection.mutable.AbstractBuffer[T]
def classTagCompanion = UnrolledBuffer
- /** Concatenates the targer unrolled buffer to this unrolled buffer.
+ /** Concatenates the target unrolled buffer to this unrolled buffer.
*
* The specified buffer `that` is cleared after this operation. This is
* an O(1) operation.
diff --git a/src/library/scala/collection/mutable/WrappedArray.scala b/src/library/scala/collection/mutable/WrappedArray.scala
index 53fca9f779..8740bda835 100644
--- a/src/library/scala/collection/mutable/WrappedArray.scala
+++ b/src/library/scala/collection/mutable/WrappedArray.scala
@@ -93,7 +93,7 @@ object WrappedArray {
def empty[T <: AnyRef]: WrappedArray[T] = EmptyWrappedArray.asInstanceOf[WrappedArray[T]]
// If make is called explicitly we use whatever we're given, even if it's
- // empty. This may be unnecesssary (if WrappedArray is to honor the collections
+ // empty. This may be unnecessary (if WrappedArray is to honor the collections
// contract all empty ones must be equal, so discriminating based on the reference
// equality of an empty array should not come up) but we may as well be
// conservative since wrapRefArray contributes most of the unnecessary allocations.
diff --git a/src/library/scala/concurrent/JavaConversions.scala b/src/library/scala/concurrent/JavaConversions.scala
index 3d0597ca22..91e55d30cb 100644
--- a/src/library/scala/concurrent/JavaConversions.scala
+++ b/src/library/scala/concurrent/JavaConversions.scala
@@ -11,7 +11,7 @@ package scala.concurrent
import java.util.concurrent.{ExecutorService, Executor}
import scala.language.implicitConversions
-/** The `JavaConversions` object provides implicit converstions supporting
+/** The `JavaConversions` object provides implicit conversions supporting
* interoperability between Scala and Java concurrency classes.
*
* @author Philipp Haller
diff --git a/src/library/scala/concurrent/duration/Duration.scala b/src/library/scala/concurrent/duration/Duration.scala
index 2eded9f060..182c2d172a 100644
--- a/src/library/scala/concurrent/duration/Duration.scala
+++ b/src/library/scala/concurrent/duration/Duration.scala
@@ -182,6 +182,7 @@ object Duration {
def compare(other: Duration) = if (other eq this) 0 else 1
def unary_- : Duration = this
def toUnit(unit: TimeUnit): Double = Double.NaN
+ private def readResolve(): AnyRef = Undefined // Instructs deserialization to use this same instance
}
sealed abstract class Infinite extends Duration {
@@ -230,7 +231,7 @@ object Duration {
* but itself. This value closely corresponds to Double.PositiveInfinity,
* matching its semantics in arithmetic operations.
*/
- val Inf: Infinite = new Infinite {
+ val Inf: Infinite = new Infinite {
override def toString = "Duration.Inf"
def compare(other: Duration) = other match {
case x if x eq Undefined => -1 // Undefined != Undefined
@@ -239,6 +240,7 @@ object Duration {
}
def unary_- : Duration = MinusInf
def toUnit(unit: TimeUnit): Double = Double.PositiveInfinity
+ private def readResolve(): AnyRef = Inf // Instructs deserialization to use this same instance
}
/**
@@ -251,6 +253,7 @@ object Duration {
def compare(other: Duration) = if (other eq this) 0 else -1
def unary_- : Duration = Inf
def toUnit(unit: TimeUnit): Double = Double.NegativeInfinity
+ private def readResolve(): AnyRef = MinusInf // Instructs deserialization to use this same instance
}
// Java Factories
diff --git a/src/library/scala/math/BigDecimal.scala b/src/library/scala/math/BigDecimal.scala
index cf95f945ba..d6e2963ad8 100644
--- a/src/library/scala/math/BigDecimal.scala
+++ b/src/library/scala/math/BigDecimal.scala
@@ -431,7 +431,7 @@ extends ScalaNumber with ScalaNumericConversions with Serializable {
* with unequal `hashCode`s. These hash codes agree with `BigInt`
* for whole numbers up ~4934 digits (the range of IEEE 128 bit floating
* point). Beyond this, hash codes will disagree; this prevents the
- * explicit represention of the `BigInt` form for `BigDecimal` values
+ * explicit representation of the `BigInt` form for `BigDecimal` values
* with large exponents.
*/
override def hashCode(): Int = {
diff --git a/src/library/scala/sys/process/BasicIO.scala b/src/library/scala/sys/process/BasicIO.scala
index b31bbf0540..066b2f5373 100644
--- a/src/library/scala/sys/process/BasicIO.scala
+++ b/src/library/scala/sys/process/BasicIO.scala
@@ -203,7 +203,7 @@ object BasicIO {
/** Returns a `ProcessIO` connected to stdout and stderr, and, optionally, stdin. */
def standard(connectInput: Boolean): ProcessIO = standard(input(connectInput))
- /** Retruns a `ProcessIO` connected to stdout, stderr and the provided `in` */
+ /** Returns a `ProcessIO` connected to stdout, stderr and the provided `in` */
def standard(in: OutputStream => Unit): ProcessIO = new ProcessIO(in, toStdOut, toStdErr)
/** Send all the input from the stream to stderr, and closes the input stream
diff --git a/src/library/scala/sys/process/ProcessLogger.scala b/src/library/scala/sys/process/ProcessLogger.scala
index ae347221ef..6072894007 100644
--- a/src/library/scala/sys/process/ProcessLogger.scala
+++ b/src/library/scala/sys/process/ProcessLogger.scala
@@ -88,7 +88,7 @@ object ProcessLogger {
/** Creates a [[scala.sys.process.ProcessLogger]] that sends all output to the corresponding
* function.
*
- * @param fout This function will receive standard outpout.
+ * @param fout This function will receive standard output.
*
* @param ferr This function will receive standard error.
*/
diff --git a/src/library/scala/util/control/Exception.scala b/src/library/scala/util/control/Exception.scala
index be6d03a145..aa30887ba0 100644
--- a/src/library/scala/util/control/Exception.scala
+++ b/src/library/scala/util/control/Exception.scala
@@ -155,7 +155,7 @@ object Exception {
/** A `Catch` object which catches everything. */
final def allCatch[T]: Catch[T] = new Catch(allCatcher[T]) withDesc "<everything>"
- /** A `Catch` object witch catches non-fatal exceptions. */
+ /** A `Catch` object which catches non-fatal exceptions. */
final def nonFatalCatch[T]: Catch[T] = new Catch(nonFatalCatcher[T]) withDesc "<non-fatal>"
/** Creates a `Catch` object which will catch any of the supplied exceptions.
diff --git a/src/library/scala/util/hashing/MurmurHash3.scala b/src/library/scala/util/hashing/MurmurHash3.scala
index 1bfaeb255b..4e5537954f 100644
--- a/src/library/scala/util/hashing/MurmurHash3.scala
+++ b/src/library/scala/util/hashing/MurmurHash3.scala
@@ -191,7 +191,7 @@ private[hashing] class MurmurHash3 {
* This is based on the earlier MurmurHash3 code by Rex Kerr, but the
* MurmurHash3 algorithm was since changed by its creator Austin Appleby
* to remedy some weaknesses and improve performance. This represents the
- * latest and supposedly final version of the algortihm (revision 136).
+ * latest and supposedly final version of the algorithm (revision 136).
*
* @see [[http://code.google.com/p/smhasher]]
*/
diff --git a/src/library/scala/util/matching/Regex.scala b/src/library/scala/util/matching/Regex.scala
index 5c4e706dc1..6d3d015b1a 100644
--- a/src/library/scala/util/matching/Regex.scala
+++ b/src/library/scala/util/matching/Regex.scala
@@ -477,7 +477,7 @@ class Regex private[matching](val pattern: Pattern, groupNames: String*) extends
/**
* Replaces some of the matches using a replacer function that returns an [[scala.Option]].
* The replacer function takes a [[scala.util.matching.Regex.Match]] so that extra
- * information can be btained from the match. For example:
+ * information can be obtained from the match. For example:
*
* {{{
* import scala.util.matching.Regex._
diff --git a/src/partest-extras/scala/tools/partest/ASMConverters.scala b/src/partest-extras/scala/tools/partest/ASMConverters.scala
index 67a4e8ae01..f6e2d2a9ec 100644
--- a/src/partest-extras/scala/tools/partest/ASMConverters.scala
+++ b/src/partest-extras/scala/tools/partest/ASMConverters.scala
@@ -89,7 +89,7 @@ object ASMConverters {
private def lst[T](xs: java.util.List[T]): List[T] = if (xs == null) Nil else xs.asScala.toList
- // Heterogenous List[Any] is used in FrameNode: type information about locals / stack values
+ // Heterogeneous List[Any] is used in FrameNode: type information about locals / stack values
// are stored in a List[Any] (Integer, String or LabelNode), see Javadoc of MethodNode#visitFrame.
// Opcodes (eg Opcodes.INTEGER) and Reference types (eg "java/lang/Object") are returned unchanged,
// LabelNodes are mapped to their LabelEntry.
diff --git a/src/partest-extras/scala/tools/partest/ParserTest.scala b/src/partest-extras/scala/tools/partest/ParserTest.scala
new file mode 100644
index 0000000000..e4c92e3dc3
--- /dev/null
+++ b/src/partest-extras/scala/tools/partest/ParserTest.scala
@@ -0,0 +1,21 @@
+/* NSC -- new Scala compiler
+ * Copyright 2005-2014 LAMP/EPFL
+ */
+
+package scala.tools.partest
+
+/** A class for testing parser output.
+ * Just supply the `code` and update the check file.
+ */
+abstract class ParserTest extends DirectTest {
+
+ override def extraSettings: String = "-usejavacp -Ystop-after:parser -Xprint:parser"
+
+ override def show(): Unit = {
+ // redirect err to out, for logging
+ val prevErr = System.err
+ System.setErr(System.out)
+ compile()
+ System.setErr(prevErr)
+ }
+}
diff --git a/src/reflect/scala/reflect/api/Quasiquotes.scala b/src/reflect/scala/reflect/api/Quasiquotes.scala
index eaae05bed5..554b43afaf 100644
--- a/src/reflect/scala/reflect/api/Quasiquotes.scala
+++ b/src/reflect/scala/reflect/api/Quasiquotes.scala
@@ -3,7 +3,7 @@ package api
trait Quasiquotes { self: Universe =>
- /** Implicit class that introduces `q`, `tq`, `cq,` `p` and `fq` string interpolators
+ /** Implicit class that introduces `q`, `tq`, `cq,` `pq` and `fq` string interpolators
* that are also known as quasiquotes. With their help you can easily manipulate
* Scala reflection ASTs.
*
diff --git a/src/reflect/scala/reflect/internal/Definitions.scala b/src/reflect/scala/reflect/internal/Definitions.scala
index 756ed870ca..c86d08e925 100644
--- a/src/reflect/scala/reflect/internal/Definitions.scala
+++ b/src/reflect/scala/reflect/internal/Definitions.scala
@@ -936,7 +936,7 @@ trait Definitions extends api.StandardDefinitions {
// TODO these aren't final! They are now overridden in AnyRef/Object. Prior to the fix
// for SI-8129, they were actually *overloaded* by the members in AnyRef/Object.
// We should unfinalize these, override in AnyValClass, and make the overrides final.
- // Refchecks never actually looks at these, so its just for consistency.
+ // Refchecks never actually looks at these, so it's just for consistency.
lazy val Any_== = enterNewMethod(AnyClass, nme.EQ, AnyTpe :: Nil, BooleanTpe, FINAL)
lazy val Any_!= = enterNewMethod(AnyClass, nme.NE, AnyTpe :: Nil, BooleanTpe, FINAL)
diff --git a/src/reflect/scala/reflect/internal/ReificationSupport.scala b/src/reflect/scala/reflect/internal/ReificationSupport.scala
index c418321234..eddfec82e7 100644
--- a/src/reflect/scala/reflect/internal/ReificationSupport.scala
+++ b/src/reflect/scala/reflect/internal/ReificationSupport.scala
@@ -292,7 +292,7 @@ trait ReificationSupport { self: SymbolTable =>
if (ctorMods.isTrait)
result(ctorMods, Nil, edefs, body)
else {
- // undo conversion from (implicit ... ) to ()(implicit ... ) when its the only parameter section
+ // undo conversion from (implicit ... ) to ()(implicit ... ) when it's the only parameter section
val vparamssRestoredImplicits = ctorVparamss match {
case Nil :: (tail @ ((head :: _) :: _)) if head.mods.isImplicit => tail
case other => other
diff --git a/src/reflect/scala/reflect/internal/Symbols.scala b/src/reflect/scala/reflect/internal/Symbols.scala
index d85ec22a84..e9cbfd54eb 100644
--- a/src/reflect/scala/reflect/internal/Symbols.scala
+++ b/src/reflect/scala/reflect/internal/Symbols.scala
@@ -794,6 +794,7 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
final def isAnonymousFunction = isSynthetic && (name containsName tpnme.ANON_FUN_NAME)
final def isDelambdafyFunction = isSynthetic && (name containsName tpnme.DELAMBDAFY_LAMBDA_CLASS_NAME)
+ final def isDelambdafyTarget = isSynthetic && isMethod && (name containsName tpnme.ANON_FUN_NAME)
final def isDefinedInPackage = effectiveOwner.isPackageClass
final def needsFlatClasses = phase.flatClasses && rawowner != NoSymbol && !rawowner.isPackageClass
@@ -2060,7 +2061,7 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
*/
final def outerClass: Symbol =
if (this == NoSymbol) {
- // ideally we shouldn't get here, but its better to harden against this than suffer the infinite loop in SI-9133
+ // ideally we shouldn't get here, but it's better to harden against this than suffer the infinite loop in SI-9133
devWarningDumpStack("NoSymbol.outerClass", 15)
NoSymbol
} else if (owner.isClass) owner
diff --git a/src/reflect/scala/reflect/internal/TreeGen.scala b/src/reflect/scala/reflect/internal/TreeGen.scala
index 75a1969d22..b2248ad518 100644
--- a/src/reflect/scala/reflect/internal/TreeGen.scala
+++ b/src/reflect/scala/reflect/internal/TreeGen.scala
@@ -365,7 +365,7 @@ abstract class TreeGen {
DefDef(NoMods, nme.MIXIN_CONSTRUCTOR, Nil, ListOfNil, TypeTree(), Block(lvdefs, Literal(Constant(()))))))
}
else {
- // convert (implicit ... ) to ()(implicit ... ) if its the only parameter section
+ // convert (implicit ... ) to ()(implicit ... ) if it's the only parameter section
if (vparamss1.isEmpty || !vparamss1.head.isEmpty && vparamss1.head.head.mods.isImplicit)
vparamss1 = List() :: vparamss1
val superCall = pendingSuperCall // we can't know in advance which of the parents will end up as a superclass
diff --git a/src/reflect/scala/reflect/internal/Types.scala b/src/reflect/scala/reflect/internal/Types.scala
index 86a53a1b02..f74d976b82 100644
--- a/src/reflect/scala/reflect/internal/Types.scala
+++ b/src/reflect/scala/reflect/internal/Types.scala
@@ -3658,7 +3658,7 @@ trait Types
// JZ: We used to register this as a perRunCache so it would be cleared eagerly at
// the end of the compilation run. But, that facility didn't actually clear this map (SI-8129)!
// When i fixed that bug, run/tpeCache-tyconCache.scala started failing. Why was that?
- // I've removed the registration for now. I don't think its particularly harmful anymore
+ // I've removed the registration for now. I don't think it's particularly harmful anymore
// as a) this is now a weak set, and b) it is discarded completely before the next run.
uniqueRunId = currentRunId
}
@@ -4535,7 +4535,7 @@ trait Types
/** Adds the @uncheckedBound annotation if the given `tp` has type arguments */
final def uncheckedBounds(tp: Type): Type = {
- if (tp.typeArgs.isEmpty || UncheckedBoundsClass == NoSymbol) tp // second condition for backwards compatibilty with older scala-reflect.jar
+ if (tp.typeArgs.isEmpty || UncheckedBoundsClass == NoSymbol) tp // second condition for backwards compatibility with older scala-reflect.jar
else tp.withAnnotation(AnnotationInfo marker UncheckedBoundsClass.tpe)
}
diff --git a/src/reflect/scala/reflect/internal/tpe/FindMembers.scala b/src/reflect/scala/reflect/internal/tpe/FindMembers.scala
index 42b13944f6..83a5d23e7c 100644
--- a/src/reflect/scala/reflect/internal/tpe/FindMembers.scala
+++ b/src/reflect/scala/reflect/internal/tpe/FindMembers.scala
@@ -155,7 +155,7 @@ trait FindMembers {
&& ( (member.owner eq other.owner) // same owner, therefore overload
|| (member.flags & PRIVATE) != 0 // (unqualified) private members never participate in overriding
|| (other.flags & PRIVATE) != 0 // ... as overrider or overridee.
- || !(memberTypeLow(member) matches memberTypeHi(other)) // do the member types match? If so, its an override. Otherwise it's an overload.
+ || !(memberTypeLow(member) matches memberTypeHi(other)) // do the member types match? If so, it's an override. Otherwise it's an overload.
)
)
diff --git a/src/reflect/scala/reflect/runtime/JavaMirrors.scala b/src/reflect/scala/reflect/runtime/JavaMirrors.scala
index 6efac6d873..237efd004f 100644
--- a/src/reflect/scala/reflect/runtime/JavaMirrors.scala
+++ b/src/reflect/scala/reflect/runtime/JavaMirrors.scala
@@ -1285,16 +1285,12 @@ private[scala] trait JavaMirrors extends internal.SymbolTable with api.JavaUnive
jclazz getDeclaredConstructor (effectiveParamClasses: _*)
}
- private def jArrayClass(elemClazz: jClass[_]): jClass[_] = {
- jArray.newInstance(elemClazz, 0).getClass
- }
-
/** The Java class that corresponds to given Scala type.
* Pre: Scala type is already transformed to Java level.
*/
def typeToJavaClass(tpe: Type): jClass[_] = tpe match {
case ExistentialType(_, rtpe) => typeToJavaClass(rtpe)
- case TypeRef(_, ArrayClass, List(elemtpe)) => jArrayClass(typeToJavaClass(elemtpe))
+ case TypeRef(_, ArrayClass, List(elemtpe)) => ScalaRunTime.arrayClass(typeToJavaClass(elemtpe))
case TypeRef(_, sym: ClassSymbol, _) => classToJava(sym.asClass)
case tpe @ TypeRef(_, sym: AliasTypeSymbol, _) => typeToJavaClass(tpe.dealias)
case SingleType(_, sym: ModuleSymbol) => classToJava(sym.moduleClass.asClass)
diff --git a/src/repl/scala/tools/nsc/interpreter/ConsoleReaderHelper.scala b/src/repl/scala/tools/nsc/interpreter/ConsoleReaderHelper.scala
index d8efcda8b5..a8d537e314 100644
--- a/src/repl/scala/tools/nsc/interpreter/ConsoleReaderHelper.scala
+++ b/src/repl/scala/tools/nsc/interpreter/ConsoleReaderHelper.scala
@@ -112,8 +112,12 @@ trait VariColumnTabulator extends Tabulator {
def layout(ncols: Int): Option[(Int, Seq[Int], Seq[Seq[String]])] = {
val nrows = items.size /% ncols
val xwise = isAcross || ncols >= items.length
- def maxima(sss: Seq[Seq[String]]) =
- (0 until (ncols min items.size)) map (i => (sss map (ss => ss(i).length)).max)
+ // max width item in each column
+ def maxima(rows: Seq[Seq[String]]) =
+ (0 until (ncols min items.size)) map { col =>
+ val widths = for (r <- rows if r.size > col) yield r(col).length
+ widths.max
+ }
def resulting(rows: Seq[Seq[String]]) = {
val columnWidths = maxima(rows) map (_ + marginSize)
val linelen = columnWidths.sum
@@ -124,9 +128,10 @@ trait VariColumnTabulator extends Tabulator {
else if (xwise) resulting((items grouped ncols).toSeq)
else {
val cols = (items grouped nrows).toList
- val rows = for (i <- 0 until nrows) yield
- for (j <- 0 until ncols) yield
- if (j < cols.size && i < cols(j).size) cols(j)(i) else ""
+ val rows =
+ for (i <- 0 until nrows) yield
+ for (j <- 0 until ncols) yield
+ if (j < cols.size && i < cols(j).size) cols(j)(i) else ""
resulting(rows)
}
}
diff --git a/src/repl/scala/tools/nsc/interpreter/JavapClass.scala b/src/repl/scala/tools/nsc/interpreter/JavapClass.scala
index c80b94bf89..1ccade2172 100644
--- a/src/repl/scala/tools/nsc/interpreter/JavapClass.scala
+++ b/src/repl/scala/tools/nsc/interpreter/JavapClass.scala
@@ -8,6 +8,7 @@ package tools.nsc
package interpreter
import java.lang.{ ClassLoader => JavaClassLoader, Iterable => JIterable }
+import scala.tools.asm.Opcodes
import scala.tools.nsc.util.ScalaClassLoader
import java.io.{ ByteArrayInputStream, CharArrayWriter, FileNotFoundException, PrintWriter, StringWriter, Writer }
import java.util.{ Locale }
@@ -758,32 +759,19 @@ object JavapClass {
import scala.tools.asm.ClassReader
import scala.tools.asm.Opcodes.INVOKESTATIC
import scala.tools.asm.tree.{ ClassNode, MethodInsnNode }
- // the accessor methods invoked statically by the apply of the given closure class
- def accesses(s: String): Seq[(String, String)] = {
- val accessor = """accessor\$\d+""".r
+ def callees(s: String): List[(String, String)] = {
loader classReader s withMethods { ms =>
- ms filter (_.name == "apply") flatMap (_.instructions.toArray.collect {
- case i: MethodInsnNode if i.getOpcode == INVOKESTATIC && when(i.name) { case accessor(_*) => true } => (i.owner, i.name)
- })
+ val nonBridgeApplyMethods = ms filter (_.name == "apply") filter (n => (n.access & Opcodes.ACC_BRIDGE) == 0)
+ val instructions = nonBridgeApplyMethods flatMap (_.instructions.toArray)
+ instructions.collect {
+ case i: MethodInsnNode => (i.owner, i.name)
+ }.toList
}
}
- // get the k.$anonfun for the accessor k.m
- def anonOf(k: String, m: String): String = {
- val res =
- loader classReader k withMethods { ms =>
- ms filter (_.name == m) flatMap (_.instructions.toArray.collect {
- case i: MethodInsnNode if i.getOpcode == INVOKESTATIC && i.name.startsWith("$anonfun") => i.name
- })
- }
- assert(res.size == 1)
- res.head
- }
- // the lambdas invoke accessors that call the anonfuns of interest. Filter k on the k#$anonfuns.
- val ack = accesses(lambda)
- assert(ack.size == 1) // There can be only one.
- ack.head match {
- case (k, _) if target.isModule && !(k endsWith "$") => None
- case (k, m) => Some(s"${k}#${anonOf(k, m)}")
+ callees(lambda) match {
+ case (k, _) :: Nil if target.isModule && !(k endsWith "$") => None
+ case (k, m) :: _ => Some(s"${k}#${m}")
+ case _ => None
}
}
/** Translate the supplied targets to patterns for anonfuns.
diff --git a/src/scaladoc/scala/tools/nsc/doc/Index.scala b/src/scaladoc/scala/tools/nsc/doc/Index.scala
index 84545e9201..a11ca38a86 100644
--- a/src/scaladoc/scala/tools/nsc/doc/Index.scala
+++ b/src/scaladoc/scala/tools/nsc/doc/Index.scala
@@ -11,4 +11,6 @@ trait Index {
type SymbolMap = SortedMap[String, SortedSet[model.MemberEntity]]
def firstLetterIndex: Map[Char, SymbolMap]
+
+ def hasDeprecatedMembers: Boolean
}
diff --git a/src/scaladoc/scala/tools/nsc/doc/base/CommentFactoryBase.scala b/src/scaladoc/scala/tools/nsc/doc/base/CommentFactoryBase.scala
index d31b877262..fb4ed34571 100755
--- a/src/scaladoc/scala/tools/nsc/doc/base/CommentFactoryBase.scala
+++ b/src/scaladoc/scala/tools/nsc/doc/base/CommentFactoryBase.scala
@@ -281,13 +281,16 @@ trait CommentFactoryBase { this: MemberLookupBase =>
parse0(docBody, tags + (key -> value), Some(key), ls, inCodeBlock)
case line :: ls if (lastTagKey.isDefined) =>
- val key = lastTagKey.get
- val value =
- ((tags get key): @unchecked) match {
- case Some(b :: bs) => (b + endOfLine + line) :: bs
- case None => oops("lastTagKey set when no tag exists for key")
- }
- parse0(docBody, tags + (key -> value), lastTagKey, ls, inCodeBlock)
+ val newtags = if (!line.isEmpty) {
+ val key = lastTagKey.get
+ val value =
+ ((tags get key): @unchecked) match {
+ case Some(b :: bs) => (b + endOfLine + line) :: bs
+ case None => oops("lastTagKey set when no tag exists for key")
+ }
+ tags + (key -> value)
+ } else tags
+ parse0(docBody, newtags, lastTagKey, ls, inCodeBlock)
case line :: ls =>
if (docBody.length > 0) docBody append endOfLine
@@ -315,18 +318,18 @@ trait CommentFactoryBase { this: MemberLookupBase =>
val bodyTags: mutable.Map[TagKey, List[Body]] =
mutable.Map(tagsWithoutDiagram mapValues {tag => tag map (parseWikiAtSymbol(_, pos, site))} toSeq: _*)
- def oneTag(key: SimpleTagKey): Option[Body] =
+ def oneTag(key: SimpleTagKey, filterEmpty: Boolean = true): Option[Body] =
((bodyTags remove key): @unchecked) match {
- case Some(r :: rs) =>
+ case Some(r :: rs) if !(filterEmpty && r.blocks.isEmpty) =>
if (!rs.isEmpty) reporter.warning(pos, "Only one '@" + key.name + "' tag is allowed")
Some(r)
- case None => None
+ case _ => None
}
def allTags(key: SimpleTagKey): List[Body] =
- (bodyTags remove key) getOrElse Nil
+ (bodyTags remove key).getOrElse(Nil).filterNot(_.blocks.isEmpty)
- def allSymsOneTag(key: TagKey): Map[String, Body] = {
+ def allSymsOneTag(key: TagKey, filterEmpty: Boolean = true): Map[String, Body] = {
val keys: Seq[SymbolTagKey] =
bodyTags.keys.toSeq flatMap {
case stk: SymbolTagKey if (stk.name == key.name) => Some(stk)
@@ -342,11 +345,11 @@ trait CommentFactoryBase { this: MemberLookupBase =>
reporter.warning(pos, "Only one '@" + key.name + "' tag for symbol " + key.symbol + " is allowed")
(key.symbol, bs.head)
}
- Map.empty[String, Body] ++ pairs
+ Map.empty[String, Body] ++ (if (filterEmpty) pairs.filterNot(_._2.blocks.isEmpty) else pairs)
}
def linkedExceptions: Map[String, Body] = {
- val m = allSymsOneTag(SimpleTagKey("throws"))
+ val m = allSymsOneTag(SimpleTagKey("throws"), filterEmpty = false)
m.map { case (name,body) =>
val link = memberLookup(pos, name, site)
@@ -372,7 +375,7 @@ trait CommentFactoryBase { this: MemberLookupBase =>
version0 = oneTag(SimpleTagKey("version")),
since0 = oneTag(SimpleTagKey("since")),
todo0 = allTags(SimpleTagKey("todo")),
- deprecated0 = oneTag(SimpleTagKey("deprecated")),
+ deprecated0 = oneTag(SimpleTagKey("deprecated"), filterEmpty = false),
note0 = allTags(SimpleTagKey("note")),
example0 = allTags(SimpleTagKey("example")),
constructor0 = oneTag(SimpleTagKey("constructor")),
diff --git a/src/scaladoc/scala/tools/nsc/doc/html/HtmlFactory.scala b/src/scaladoc/scala/tools/nsc/doc/html/HtmlFactory.scala
index 61ab18d42d..8313d842e5 100644
--- a/src/scaladoc/scala/tools/nsc/doc/html/HtmlFactory.scala
+++ b/src/scaladoc/scala/tools/nsc/doc/html/HtmlFactory.scala
@@ -123,6 +123,8 @@ class HtmlFactory(val universe: doc.Universe, index: doc.Index) {
new page.Index(universe, index) writeFor this
new page.IndexScript(universe, index) writeFor this
+ if (index.hasDeprecatedMembers)
+ new page.DeprecatedIndex(universe, index) writeFor this
try {
writeTemplates(_ writeFor this)
for (letter <- index.firstLetterIndex) {
diff --git a/src/scaladoc/scala/tools/nsc/doc/html/HtmlPage.scala b/src/scaladoc/scala/tools/nsc/doc/html/HtmlPage.scala
index ce75749859..86155845b0 100644
--- a/src/scaladoc/scala/tools/nsc/doc/html/HtmlPage.scala
+++ b/src/scaladoc/scala/tools/nsc/doc/html/HtmlPage.scala
@@ -206,25 +206,42 @@ abstract class HtmlPage extends Page { thisPage =>
case tpl :: tpls => templateToHtml(tpl) ++ sep ++ templatesToHtml(tpls, sep)
}
- /** Returns the _big image name corresponding to the DocTemplate Entity (upper left icon) */
- def docEntityKindToBigImage(ety: DocTemplateEntity) =
- if (ety.isTrait && !ety.companion.isEmpty && ety.companion.get.visibility.isPublic && ety.companion.get.inSource != None) "trait_to_object_big.png"
- else if (ety.isTrait) "trait_big.png"
- else if (ety.isClass && !ety.companion.isEmpty && ety.companion.get.visibility.isPublic && ety.companion.get.inSource != None) "class_to_object_big.png"
- else if (ety.isClass) "class_big.png"
- else if ((ety.isAbstractType || ety.isAliasType) && !ety.companion.isEmpty && ety.companion.get.visibility.isPublic && ety.companion.get.inSource != None) "type_to_object_big.png"
- else if ((ety.isAbstractType || ety.isAliasType)) "type_big.png"
- else if (ety.isObject && !ety.companion.isEmpty && ety.companion.get.visibility.isPublic && ety.companion.get.inSource != None && ety.companion.get.isClass) "object_to_class_big.png"
- else if (ety.isObject && !ety.companion.isEmpty && ety.companion.get.visibility.isPublic && ety.companion.get.inSource != None && ety.companion.get.isTrait) "object_to_trait_big.png"
- else if (ety.isObject && !ety.companion.isEmpty && ety.companion.get.visibility.isPublic && ety.companion.get.inSource != None && (ety.companion.get.isAbstractType || ety.companion.get.isAliasType)) "object_to_trait_big.png"
- else if (ety.isObject) "object_big.png"
- else if (ety.isPackage) "package_big.png"
- else "class_big.png" // FIXME: an entity *should* fall into one of the above categories, but AnyRef is somehow not
+ object Image extends Enumeration {
+ val Trait, Class, Type, Object, Package = Value
+ }
+
+ /** Returns the _big image name and the alt attribute
+ * corresponding to the DocTemplate Entity (upper left icon) */
+ def docEntityKindToBigImage(ety: DocTemplateEntity) = {
+ def entityToImage(e: DocTemplateEntity) =
+ if (e.isTrait) Image.Trait
+ else if (e.isClass) Image.Class
+ else if (e.isAbstractType || e.isAliasType) Image.Type
+ else if (e.isObject) Image.Object
+ else if (e.isPackage) Image.Package
+ else {
+ // FIXME: an entity *should* fall into one of the above categories,
+ // but AnyRef is somehow not
+ Image.Class
+ }
+
+ val image = entityToImage(ety)
+ val companionImage = ety.companion filter {
+ e => e.visibility.isPublic && ! e.inSource.isEmpty
+ } map { entityToImage }
+
+ (image, companionImage) match {
+ case (from, Some(to)) =>
+ ((from + "_to_" + to + "_big.png").toLowerCase, from + "/" + to)
+ case (from, None) =>
+ ((from + "_big.png").toLowerCase, from.toString)
+ }
+ }
def permalink(template: Entity, isSelf: Boolean = true): Elem =
<span class="permalink">
<a href={ memberToUrl(template, isSelf) } title="Permalink" target="_top">
- <img src={ relativeLinkTo(List("permalink.png", "lib")) } />
+ <img src={ relativeLinkTo(List("permalink.png", "lib")) } alt="Permalink" />
</a>
</span>
diff --git a/src/scaladoc/scala/tools/nsc/doc/html/page/DeprecatedIndex.scala b/src/scaladoc/scala/tools/nsc/doc/html/page/DeprecatedIndex.scala
new file mode 100755
index 0000000000..f257153bd7
--- /dev/null
+++ b/src/scaladoc/scala/tools/nsc/doc/html/page/DeprecatedIndex.scala
@@ -0,0 +1,58 @@
+/* NSC -- new Scala compiler
+ * Copyright 2007-2013 LAMP/EPFL
+ */
+
+package scala
+package tools
+package nsc
+package doc
+package html
+package page
+
+import doc.model._
+
+class DeprecatedIndex(universe: Universe, index: doc.Index) extends HtmlPage {
+
+ def path = List("deprecated-list.html")
+
+ def title = {
+ val s = universe.settings
+ ( if (!s.doctitle.isDefault) s.doctitle.value else "" ) +
+ ( if (!s.docversion.isDefault) (" " + s.docversion.value) else "" )
+ }
+
+ def headers =
+ <xml:group>
+ <link href={ relativeLinkTo(List("ref-index.css", "lib")) } media="screen" type="text/css" rel="stylesheet"/>
+ <script type="text/javascript" src={ relativeLinkTo{List("jquery.js", "lib")} }></script>
+ </xml:group>
+
+
+ private def entry(name: String, methods: Iterable[MemberEntity]) = {
+ val occurrences = methods.filter(_.deprecation.isDefined).map(method =>
+ templateToHtml(method.inDefinitionTemplates.head)
+ ).toList.distinct
+
+ <div class="entry">
+ <div class="name">{ name }</div>
+ <div class="occurrences">{
+ for (owner <- occurrences) yield owner ++ scala.xml.Text(" ")
+ }</div>
+ </div>
+ }
+
+ def deprecatedEntries = {
+ val available = ('_' +: ('a' to 'z')).flatMap(index.firstLetterIndex.get)
+
+ for (group <- available;
+ value <- group if value._2.find(_.deprecation.isDefined).isDefined)
+ yield value
+ }
+
+ def body =
+ <body>{
+ for(value <- deprecatedEntries) yield
+ entry(value._1, value._2.view)
+ }</body>
+
+}
diff --git a/src/scaladoc/scala/tools/nsc/doc/html/page/Index.scala b/src/scaladoc/scala/tools/nsc/doc/html/page/Index.scala
index ce3a5eb1fc..6bfe480e33 100644
--- a/src/scaladoc/scala/tools/nsc/doc/html/page/Index.scala
+++ b/src/scaladoc/scala/tools/nsc/doc/html/page/Index.scala
@@ -61,12 +61,17 @@ class Index(universe: doc.Universe, val index: doc.Index) extends HtmlPage {
}
}
+ def deprecated: NodeSeq = if (index.hasDeprecatedMembers)
+ <a target="template" href="deprecated-list.html">deprecated</a>
+ else
+ <span>deprecated</span>
+
def browser =
<div id="browser" class="ui-layout-west">
<div class="ui-west-center">
<div id="filter">
<div id="textfilter"></div>
- <div id="letters">{ letters }</div>
+ <div id="letters">{ letters } &#8211; { deprecated }</div>
</div>
<div class="pack" id="tpl">{
def packageElem(pack: model.Package): NodeSeq = {
diff --git a/src/scaladoc/scala/tools/nsc/doc/html/page/Template.scala b/src/scaladoc/scala/tools/nsc/doc/html/page/Template.scala
index e10c54a414..c384ed7034 100644
--- a/src/scaladoc/scala/tools/nsc/doc/html/page/Template.scala
+++ b/src/scaladoc/scala/tools/nsc/doc/html/page/Template.scala
@@ -103,11 +103,13 @@ class Template(universe: doc.Universe, generator: DiagramGenerator, tpl: DocTemp
<body class={ if (tpl.isType) "type" else "value" }>
<div id="definition">
{
+ val (src, alt) = docEntityKindToBigImage(tpl)
+
tpl.companion match {
case Some(companion) if (companion.visibility.isPublic && companion.inSource != None) =>
- <a href={relativeLinkTo(companion)} title={docEntityKindToCompanionTitle(tpl)}><img src={ relativeLinkTo(List(docEntityKindToBigImage(tpl), "lib")) }/></a>
+ <a href={relativeLinkTo(companion)} title={docEntityKindToCompanionTitle(tpl)}><img alt={alt} src={ relativeLinkTo(List(src, "lib")) }/></a>
case _ =>
- <img src={ relativeLinkTo(List(docEntityKindToBigImage(tpl), "lib")) }/>
+ <img alt={alt} src={ relativeLinkTo(List(src, "lib")) }/>
}}
{ owner }
<h1>{ displayName }</h1>{
diff --git a/src/scaladoc/scala/tools/nsc/doc/html/resource/lib/template.css b/src/scaladoc/scala/tools/nsc/doc/html/resource/lib/template.css
index e129e6cf6a..e84d7c1ca6 100644
--- a/src/scaladoc/scala/tools/nsc/doc/html/resource/lib/template.css
+++ b/src/scaladoc/scala/tools/nsc/doc/html/resource/lib/template.css
@@ -210,6 +210,7 @@ dl.attributes > dd {
display: block;
padding-left: 10em;
margin-bottom: 5px;
+ min-height: 15px;
}
#template .values > h3 {
@@ -669,6 +670,7 @@ div.fullcomment dl.paramcmts > dd {
padding-left: 10px;
margin-bottom: 5px;
margin-left: 70px;
+ min-height: 15px;
}
/* Members filter tool */
diff --git a/src/scaladoc/scala/tools/nsc/doc/html/resource/lib/template.js b/src/scaladoc/scala/tools/nsc/doc/html/resource/lib/template.js
index 1ebcb67f04..798a2d430b 100644
--- a/src/scaladoc/scala/tools/nsc/doc/html/resource/lib/template.js
+++ b/src/scaladoc/scala/tools/nsc/doc/html/resource/lib/template.js
@@ -179,7 +179,7 @@ $(document).ready(function(){
filter();
});
- $("#visbl > ol > li.public").click(function() {
+ $("#order > ol > li.alpha").click(function() {
if ($(this).hasClass("out")) {
orderAlpha();
}
diff --git a/src/scaladoc/scala/tools/nsc/doc/model/IndexModelFactory.scala b/src/scaladoc/scala/tools/nsc/doc/model/IndexModelFactory.scala
index 643a089aae..ad53dc6bfa 100755
--- a/src/scaladoc/scala/tools/nsc/doc/model/IndexModelFactory.scala
+++ b/src/scaladoc/scala/tools/nsc/doc/model/IndexModelFactory.scala
@@ -14,10 +14,12 @@ object IndexModelFactory {
def makeIndex(universe: Universe): Index = new Index {
- lazy val firstLetterIndex: Map[Char, SymbolMap] = {
+ lazy val (firstLetterIndex, hasDeprecatedMembers): (Map[Char, SymbolMap], Boolean) = {
object result extends mutable.HashMap[Char,SymbolMap] {
+ var deprecated = false
+
/* symbol name ordering */
implicit def orderingMap = math.Ordering.String
@@ -32,6 +34,8 @@ object IndexModelFactory {
val members = letter.get(d.name).getOrElse {
SortedSet.empty[MemberEntity](Ordering.by { _.toString })
} + d
+ if (!deprecated && members.find(_.deprecation.isDefined).isDefined)
+ deprecated = true
this(firstLetter) = letter + (d.name -> members)
}
}
@@ -50,7 +54,7 @@ object IndexModelFactory {
gather(universe.rootPackage)
- result.toMap
+ (result.toMap, result.deprecated)
}
}
}
diff --git a/test/files/jvm/inner.scala b/test/files/jvm/inner.scala
index c05e803449..dc01b124c5 100644
--- a/test/files/jvm/inner.scala
+++ b/test/files/jvm/inner.scala
@@ -77,7 +77,7 @@ object Scalatest {
def java(cname: String) =
exec(javacmd, "-cp", classpath, cname)
- /** Execute cmd, wait for the process to end and pipe it's output to stdout */
+ /** Execute cmd, wait for the process to end and pipe its output to stdout */
private def exec(args: String*) {
val proc = Runtime.getRuntime().exec(args.toArray)
val inp = new BufferedReader(new InputStreamReader(proc.getInputStream))
diff --git a/test/files/jvm/javaReflection/Test.scala b/test/files/jvm/javaReflection/Test.scala
index 5b6ef1b573..ae5a36eeb2 100644
--- a/test/files/jvm/javaReflection/Test.scala
+++ b/test/files/jvm/javaReflection/Test.scala
@@ -124,8 +124,8 @@ object Test {
// exclude files from Test.scala, just take those from Classes_1.scala
case s if !s.startsWith("Test") && s.endsWith(".class") => s.substring(0, s.length - 6)
}).sortWith((a, b) => {
- // sort such that first there are all anonymous funcitions, then all other classes.
- // within those cathegories, sort lexically.
+ // sort such that first there are all anonymous functions, then all other classes.
+ // within those categories, sort lexically.
// this makes the check file smaller: it differs for anonymous functions between -Ydelambdafy:inline/method.
// the other classes are the same.
if (isAnonFunClassName(a)) !isAnonFunClassName(b) || a < b
diff --git a/test/files/jvm/t8689.scala b/test/files/jvm/t8689.scala
index ef43a1df63..3ee20d711a 100644
--- a/test/files/jvm/t8689.scala
+++ b/test/files/jvm/t8689.scala
@@ -4,10 +4,15 @@ object Test {
import ExecutionContext.Implicits.global
val source1 = Promise[Int]()
val source2 = Promise[Int]()
+ val done = Promise[Unit]()
source2.completeWith(source1.future).future.onComplete {
- case _ => print("success")
+ case _ =>
+ print("success")
+ done.success(())
}
source2.tryFailure(new TimeoutException)
source1.success(123)
+ import duration._
+ Await.result(done.future, 120.seconds)
}
-} \ No newline at end of file
+}
diff --git a/test/files/neg/case-collision2.flags b/test/files/neg/case-collision2.flags
index 5bfa9da5c5..bea46902c9 100644
--- a/test/files/neg/case-collision2.flags
+++ b/test/files/neg/case-collision2.flags
@@ -1 +1 @@
--Ynooptimize -Ybackend:GenBCode -Xfatal-warnings
+-Ybackend:GenBCode -Xfatal-warnings
diff --git a/test/files/neg/inlineMaxSize.check b/test/files/neg/inlineMaxSize.check
new file mode 100644
index 0000000000..d218a8b6e2
--- /dev/null
+++ b/test/files/neg/inlineMaxSize.check
@@ -0,0 +1,9 @@
+inlineMaxSize.scala:7: warning: C::i()I is annotated @inline but could not be inlined:
+The size of the callsite method C::j()I
+would exceed the JVM method size limit after inlining C::i()I.
+
+ @inline final def j = i + i
+ ^
+error: No warnings can be incurred under -Xfatal-warnings.
+one warning found
+one error found
diff --git a/test/files/neg/inlineMaxSize.flags b/test/files/neg/inlineMaxSize.flags
new file mode 100644
index 0000000000..9c6b811622
--- /dev/null
+++ b/test/files/neg/inlineMaxSize.flags
@@ -0,0 +1 @@
+-Ybackend:GenBCode -Ydelambdafy:method -Yopt:l:classpath -Yopt-warnings -Xfatal-warnings \ No newline at end of file
diff --git a/test/files/neg/inlineMaxSize.scala b/test/files/neg/inlineMaxSize.scala
new file mode 100644
index 0000000000..16dc0d9538
--- /dev/null
+++ b/test/files/neg/inlineMaxSize.scala
@@ -0,0 +1,8 @@
+// not a JUnit test because of https://github.com/scala-opt/scala/issues/23
+class C {
+ @inline final def f = 0
+ @inline final def g = f + f + f + f + f + f + f + f + f + f
+ @inline final def h = g + g + g + g + g + g + g + g + g + g
+ @inline final def i = h + h + h + h + h + h + h + h + h + h
+ @inline final def j = i + i
+}
diff --git a/test/files/neg/patmatexhaust-huge.check b/test/files/neg/patmatexhaust-huge.check
new file mode 100644
index 0000000000..66dbd42ef3
--- /dev/null
+++ b/test/files/neg/patmatexhaust-huge.check
@@ -0,0 +1,7 @@
+patmatexhaust-huge.scala:404: warning: match may not be exhaustive.
+It would fail on the following inputs: C392, C397
+ def f(c: C): Int = c match {
+ ^
+error: No warnings can be incurred under -Xfatal-warnings.
+one warning found
+one error found
diff --git a/test/files/neg/patmatexhaust-huge.flags b/test/files/neg/patmatexhaust-huge.flags
new file mode 100644
index 0000000000..591a950f83
--- /dev/null
+++ b/test/files/neg/patmatexhaust-huge.flags
@@ -0,0 +1 @@
+-Xfatal-warnings -unchecked -Ypatmat-exhaust-depth off \ No newline at end of file
diff --git a/test/files/neg/patmatexhaust-huge.scala b/test/files/neg/patmatexhaust-huge.scala
new file mode 100644
index 0000000000..8f87655b7a
--- /dev/null
+++ b/test/files/neg/patmatexhaust-huge.scala
@@ -0,0 +1,806 @@
+sealed trait C
+case object C1 extends C
+case object C2 extends C
+case object C3 extends C
+case object C4 extends C
+case object C5 extends C
+case object C6 extends C
+case object C7 extends C
+case object C8 extends C
+case object C9 extends C
+case object C10 extends C
+case object C11 extends C
+case object C12 extends C
+case object C13 extends C
+case object C14 extends C
+case object C15 extends C
+case object C16 extends C
+case object C17 extends C
+case object C18 extends C
+case object C19 extends C
+case object C20 extends C
+case object C21 extends C
+case object C22 extends C
+case object C23 extends C
+case object C24 extends C
+case object C25 extends C
+case object C26 extends C
+case object C27 extends C
+case object C28 extends C
+case object C29 extends C
+case object C30 extends C
+case object C31 extends C
+case object C32 extends C
+case object C33 extends C
+case object C34 extends C
+case object C35 extends C
+case object C36 extends C
+case object C37 extends C
+case object C38 extends C
+case object C39 extends C
+case object C40 extends C
+case object C41 extends C
+case object C42 extends C
+case object C43 extends C
+case object C44 extends C
+case object C45 extends C
+case object C46 extends C
+case object C47 extends C
+case object C48 extends C
+case object C49 extends C
+case object C50 extends C
+case object C51 extends C
+case object C52 extends C
+case object C53 extends C
+case object C54 extends C
+case object C55 extends C
+case object C56 extends C
+case object C57 extends C
+case object C58 extends C
+case object C59 extends C
+case object C60 extends C
+case object C61 extends C
+case object C62 extends C
+case object C63 extends C
+case object C64 extends C
+case object C65 extends C
+case object C66 extends C
+case object C67 extends C
+case object C68 extends C
+case object C69 extends C
+case object C70 extends C
+case object C71 extends C
+case object C72 extends C
+case object C73 extends C
+case object C74 extends C
+case object C75 extends C
+case object C76 extends C
+case object C77 extends C
+case object C78 extends C
+case object C79 extends C
+case object C80 extends C
+case object C81 extends C
+case object C82 extends C
+case object C83 extends C
+case object C84 extends C
+case object C85 extends C
+case object C86 extends C
+case object C87 extends C
+case object C88 extends C
+case object C89 extends C
+case object C90 extends C
+case object C91 extends C
+case object C92 extends C
+case object C93 extends C
+case object C94 extends C
+case object C95 extends C
+case object C96 extends C
+case object C97 extends C
+case object C98 extends C
+case object C99 extends C
+case object C100 extends C
+case object C101 extends C
+case object C102 extends C
+case object C103 extends C
+case object C104 extends C
+case object C105 extends C
+case object C106 extends C
+case object C107 extends C
+case object C108 extends C
+case object C109 extends C
+case object C110 extends C
+case object C111 extends C
+case object C112 extends C
+case object C113 extends C
+case object C114 extends C
+case object C115 extends C
+case object C116 extends C
+case object C117 extends C
+case object C118 extends C
+case object C119 extends C
+case object C120 extends C
+case object C121 extends C
+case object C122 extends C
+case object C123 extends C
+case object C124 extends C
+case object C125 extends C
+case object C126 extends C
+case object C127 extends C
+case object C128 extends C
+case object C129 extends C
+case object C130 extends C
+case object C131 extends C
+case object C132 extends C
+case object C133 extends C
+case object C134 extends C
+case object C135 extends C
+case object C136 extends C
+case object C137 extends C
+case object C138 extends C
+case object C139 extends C
+case object C140 extends C
+case object C141 extends C
+case object C142 extends C
+case object C143 extends C
+case object C144 extends C
+case object C145 extends C
+case object C146 extends C
+case object C147 extends C
+case object C148 extends C
+case object C149 extends C
+case object C150 extends C
+case object C151 extends C
+case object C152 extends C
+case object C153 extends C
+case object C154 extends C
+case object C155 extends C
+case object C156 extends C
+case object C157 extends C
+case object C158 extends C
+case object C159 extends C
+case object C160 extends C
+case object C161 extends C
+case object C162 extends C
+case object C163 extends C
+case object C164 extends C
+case object C165 extends C
+case object C166 extends C
+case object C167 extends C
+case object C168 extends C
+case object C169 extends C
+case object C170 extends C
+case object C171 extends C
+case object C172 extends C
+case object C173 extends C
+case object C174 extends C
+case object C175 extends C
+case object C176 extends C
+case object C177 extends C
+case object C178 extends C
+case object C179 extends C
+case object C180 extends C
+case object C181 extends C
+case object C182 extends C
+case object C183 extends C
+case object C184 extends C
+case object C185 extends C
+case object C186 extends C
+case object C187 extends C
+case object C188 extends C
+case object C189 extends C
+case object C190 extends C
+case object C191 extends C
+case object C192 extends C
+case object C193 extends C
+case object C194 extends C
+case object C195 extends C
+case object C196 extends C
+case object C197 extends C
+case object C198 extends C
+case object C199 extends C
+case object C200 extends C
+case object C201 extends C
+case object C202 extends C
+case object C203 extends C
+case object C204 extends C
+case object C205 extends C
+case object C206 extends C
+case object C207 extends C
+case object C208 extends C
+case object C209 extends C
+case object C210 extends C
+case object C211 extends C
+case object C212 extends C
+case object C213 extends C
+case object C214 extends C
+case object C215 extends C
+case object C216 extends C
+case object C217 extends C
+case object C218 extends C
+case object C219 extends C
+case object C220 extends C
+case object C221 extends C
+case object C222 extends C
+case object C223 extends C
+case object C224 extends C
+case object C225 extends C
+case object C226 extends C
+case object C227 extends C
+case object C228 extends C
+case object C229 extends C
+case object C230 extends C
+case object C231 extends C
+case object C232 extends C
+case object C233 extends C
+case object C234 extends C
+case object C235 extends C
+case object C236 extends C
+case object C237 extends C
+case object C238 extends C
+case object C239 extends C
+case object C240 extends C
+case object C241 extends C
+case object C242 extends C
+case object C243 extends C
+case object C244 extends C
+case object C245 extends C
+case object C246 extends C
+case object C247 extends C
+case object C248 extends C
+case object C249 extends C
+case object C250 extends C
+case object C251 extends C
+case object C252 extends C
+case object C253 extends C
+case object C254 extends C
+case object C255 extends C
+case object C256 extends C
+case object C257 extends C
+case object C258 extends C
+case object C259 extends C
+case object C260 extends C
+case object C261 extends C
+case object C262 extends C
+case object C263 extends C
+case object C264 extends C
+case object C265 extends C
+case object C266 extends C
+case object C267 extends C
+case object C268 extends C
+case object C269 extends C
+case object C270 extends C
+case object C271 extends C
+case object C272 extends C
+case object C273 extends C
+case object C274 extends C
+case object C275 extends C
+case object C276 extends C
+case object C277 extends C
+case object C278 extends C
+case object C279 extends C
+case object C280 extends C
+case object C281 extends C
+case object C282 extends C
+case object C283 extends C
+case object C284 extends C
+case object C285 extends C
+case object C286 extends C
+case object C287 extends C
+case object C288 extends C
+case object C289 extends C
+case object C290 extends C
+case object C291 extends C
+case object C292 extends C
+case object C293 extends C
+case object C294 extends C
+case object C295 extends C
+case object C296 extends C
+case object C297 extends C
+case object C298 extends C
+case object C299 extends C
+case object C300 extends C
+case object C301 extends C
+case object C302 extends C
+case object C303 extends C
+case object C304 extends C
+case object C305 extends C
+case object C306 extends C
+case object C307 extends C
+case object C308 extends C
+case object C309 extends C
+case object C310 extends C
+case object C311 extends C
+case object C312 extends C
+case object C313 extends C
+case object C314 extends C
+case object C315 extends C
+case object C316 extends C
+case object C317 extends C
+case object C318 extends C
+case object C319 extends C
+case object C320 extends C
+case object C321 extends C
+case object C322 extends C
+case object C323 extends C
+case object C324 extends C
+case object C325 extends C
+case object C326 extends C
+case object C327 extends C
+case object C328 extends C
+case object C329 extends C
+case object C330 extends C
+case object C331 extends C
+case object C332 extends C
+case object C333 extends C
+case object C334 extends C
+case object C335 extends C
+case object C336 extends C
+case object C337 extends C
+case object C338 extends C
+case object C339 extends C
+case object C340 extends C
+case object C341 extends C
+case object C342 extends C
+case object C343 extends C
+case object C344 extends C
+case object C345 extends C
+case object C346 extends C
+case object C347 extends C
+case object C348 extends C
+case object C349 extends C
+case object C350 extends C
+case object C351 extends C
+case object C352 extends C
+case object C353 extends C
+case object C354 extends C
+case object C355 extends C
+case object C356 extends C
+case object C357 extends C
+case object C358 extends C
+case object C359 extends C
+case object C360 extends C
+case object C361 extends C
+case object C362 extends C
+case object C363 extends C
+case object C364 extends C
+case object C365 extends C
+case object C366 extends C
+case object C367 extends C
+case object C368 extends C
+case object C369 extends C
+case object C370 extends C
+case object C371 extends C
+case object C372 extends C
+case object C373 extends C
+case object C374 extends C
+case object C375 extends C
+case object C376 extends C
+case object C377 extends C
+case object C378 extends C
+case object C379 extends C
+case object C380 extends C
+case object C381 extends C
+case object C382 extends C
+case object C383 extends C
+case object C384 extends C
+case object C385 extends C
+case object C386 extends C
+case object C387 extends C
+case object C388 extends C
+case object C389 extends C
+case object C390 extends C
+case object C391 extends C
+case object C392 extends C
+case object C393 extends C
+case object C394 extends C
+case object C395 extends C
+case object C396 extends C
+case object C397 extends C
+case object C398 extends C
+case object C399 extends C
+case object C400 extends C
+
+object M {
+ def f(c: C): Int = c match {
+ case C1 => 1
+ case C2 => 2
+ case C3 => 3
+ case C4 => 4
+ case C5 => 5
+ case C6 => 6
+ case C7 => 7
+ case C8 => 8
+ case C9 => 9
+ case C10 => 10
+ case C11 => 11
+ case C12 => 12
+ case C13 => 13
+ case C14 => 14
+ case C15 => 15
+ case C16 => 16
+ case C17 => 17
+ case C18 => 18
+ case C19 => 19
+ case C20 => 20
+ case C21 => 21
+ case C22 => 22
+ case C23 => 23
+ case C24 => 24
+ case C25 => 25
+ case C26 => 26
+ case C27 => 27
+ case C28 => 28
+ case C29 => 29
+ case C30 => 30
+ case C31 => 31
+ case C32 => 32
+ case C33 => 33
+ case C34 => 34
+ case C35 => 35
+ case C36 => 36
+ case C37 => 37
+ case C38 => 38
+ case C39 => 39
+ case C40 => 40
+ case C41 => 41
+ case C42 => 42
+ case C43 => 43
+ case C44 => 44
+ case C45 => 45
+ case C46 => 46
+ case C47 => 47
+ case C48 => 48
+ case C49 => 49
+ case C50 => 50
+ case C51 => 51
+ case C52 => 52
+ case C53 => 53
+ case C54 => 54
+ case C55 => 55
+ case C56 => 56
+ case C57 => 57
+ case C58 => 58
+ case C59 => 59
+ case C60 => 60
+ case C61 => 61
+ case C62 => 62
+ case C63 => 63
+ case C64 => 64
+ case C65 => 65
+ case C66 => 66
+ case C67 => 67
+ case C68 => 68
+ case C69 => 69
+ case C70 => 70
+ case C71 => 71
+ case C72 => 72
+ case C73 => 73
+ case C74 => 74
+ case C75 => 75
+ case C76 => 76
+ case C77 => 77
+ case C78 => 78
+ case C79 => 79
+ case C80 => 80
+ case C81 => 81
+ case C82 => 82
+ case C83 => 83
+ case C84 => 84
+ case C85 => 85
+ case C86 => 86
+ case C87 => 87
+ case C88 => 88
+ case C89 => 89
+ case C90 => 90
+ case C91 => 91
+ case C92 => 92
+ case C93 => 93
+ case C94 => 94
+ case C95 => 95
+ case C96 => 96
+ case C97 => 97
+ case C98 => 98
+ case C99 => 99
+ case C100 => 100
+ case C101 => 101
+ case C102 => 102
+ case C103 => 103
+ case C104 => 104
+ case C105 => 105
+ case C106 => 106
+ case C107 => 107
+ case C108 => 108
+ case C109 => 109
+ case C110 => 110
+ case C111 => 111
+ case C112 => 112
+ case C113 => 113
+ case C114 => 114
+ case C115 => 115
+ case C116 => 116
+ case C117 => 117
+ case C118 => 118
+ case C119 => 119
+ case C120 => 120
+ case C121 => 121
+ case C122 => 122
+ case C123 => 123
+ case C124 => 124
+ case C125 => 125
+ case C126 => 126
+ case C127 => 127
+ case C128 => 128
+ case C129 => 129
+ case C130 => 130
+ case C131 => 131
+ case C132 => 132
+ case C133 => 133
+ case C134 => 134
+ case C135 => 135
+ case C136 => 136
+ case C137 => 137
+ case C138 => 138
+ case C139 => 139
+ case C140 => 140
+ case C141 => 141
+ case C142 => 142
+ case C143 => 143
+ case C144 => 144
+ case C145 => 145
+ case C146 => 146
+ case C147 => 147
+ case C148 => 148
+ case C149 => 149
+ case C150 => 150
+ case C151 => 151
+ case C152 => 152
+ case C153 => 153
+ case C154 => 154
+ case C155 => 155
+ case C156 => 156
+ case C157 => 157
+ case C158 => 158
+ case C159 => 159
+ case C160 => 160
+ case C161 => 161
+ case C162 => 162
+ case C163 => 163
+ case C164 => 164
+ case C165 => 165
+ case C166 => 166
+ case C167 => 167
+ case C168 => 168
+ case C169 => 169
+ case C170 => 170
+ case C171 => 171
+ case C172 => 172
+ case C173 => 173
+ case C174 => 174
+ case C175 => 175
+ case C176 => 176
+ case C177 => 177
+ case C178 => 178
+ case C179 => 179
+ case C180 => 180
+ case C181 => 181
+ case C182 => 182
+ case C183 => 183
+ case C184 => 184
+ case C185 => 185
+ case C186 => 186
+ case C187 => 187
+ case C188 => 188
+ case C189 => 189
+ case C190 => 190
+ case C191 => 191
+ case C192 => 192
+ case C193 => 193
+ case C194 => 194
+ case C195 => 195
+ case C196 => 196
+ case C197 => 197
+ case C198 => 198
+ case C199 => 199
+ case C200 => 200
+ case C201 => 201
+ case C202 => 202
+ case C203 => 203
+ case C204 => 204
+ case C205 => 205
+ case C206 => 206
+ case C207 => 207
+ case C208 => 208
+ case C209 => 209
+ case C210 => 210
+ case C211 => 211
+ case C212 => 212
+ case C213 => 213
+ case C214 => 214
+ case C215 => 215
+ case C216 => 216
+ case C217 => 217
+ case C218 => 218
+ case C219 => 219
+ case C220 => 220
+ case C221 => 221
+ case C222 => 222
+ case C223 => 223
+ case C224 => 224
+ case C225 => 225
+ case C226 => 226
+ case C227 => 227
+ case C228 => 228
+ case C229 => 229
+ case C230 => 230
+ case C231 => 231
+ case C232 => 232
+ case C233 => 233
+ case C234 => 234
+ case C235 => 235
+ case C236 => 236
+ case C237 => 237
+ case C238 => 238
+ case C239 => 239
+ case C240 => 240
+ case C241 => 241
+ case C242 => 242
+ case C243 => 243
+ case C244 => 244
+ case C245 => 245
+ case C246 => 246
+ case C247 => 247
+ case C248 => 248
+ case C249 => 249
+ case C250 => 250
+ case C251 => 251
+ case C252 => 252
+ case C253 => 253
+ case C254 => 254
+ case C255 => 255
+ case C256 => 256
+ case C257 => 257
+ case C258 => 258
+ case C259 => 259
+ case C260 => 260
+ case C261 => 261
+ case C262 => 262
+ case C263 => 263
+ case C264 => 264
+ case C265 => 265
+ case C266 => 266
+ case C267 => 267
+ case C268 => 268
+ case C269 => 269
+ case C270 => 270
+ case C271 => 271
+ case C272 => 272
+ case C273 => 273
+ case C274 => 274
+ case C275 => 275
+ case C276 => 276
+ case C277 => 277
+ case C278 => 278
+ case C279 => 279
+ case C280 => 280
+ case C281 => 281
+ case C282 => 282
+ case C283 => 283
+ case C284 => 284
+ case C285 => 285
+ case C286 => 286
+ case C287 => 287
+ case C288 => 288
+ case C289 => 289
+ case C290 => 290
+ case C291 => 291
+ case C292 => 292
+ case C293 => 293
+ case C294 => 294
+ case C295 => 295
+ case C296 => 296
+ case C297 => 297
+ case C298 => 298
+ case C299 => 299
+ case C300 => 300
+ case C301 => 301
+ case C302 => 302
+ case C303 => 303
+ case C304 => 304
+ case C305 => 305
+ case C306 => 306
+ case C307 => 307
+ case C308 => 308
+ case C309 => 309
+ case C310 => 310
+ case C311 => 311
+ case C312 => 312
+ case C313 => 313
+ case C314 => 314
+ case C315 => 315
+ case C316 => 316
+ case C317 => 317
+ case C318 => 318
+ case C319 => 319
+ case C320 => 320
+ case C321 => 321
+ case C322 => 322
+ case C323 => 323
+ case C324 => 324
+ case C325 => 325
+ case C326 => 326
+ case C327 => 327
+ case C328 => 328
+ case C329 => 329
+ case C330 => 330
+ case C331 => 331
+ case C332 => 332
+ case C333 => 333
+ case C334 => 334
+ case C335 => 335
+ case C336 => 336
+ case C337 => 337
+ case C338 => 338
+ case C339 => 339
+ case C340 => 340
+ case C341 => 341
+ case C342 => 342
+ case C343 => 343
+ case C344 => 344
+ case C345 => 345
+ case C346 => 346
+ case C347 => 347
+ case C348 => 348
+ case C349 => 349
+ case C350 => 350
+ case C351 => 351
+ case C352 => 352
+ case C353 => 353
+ case C354 => 354
+ case C355 => 355
+ case C356 => 356
+ case C357 => 357
+ case C358 => 358
+ case C359 => 359
+ case C360 => 360
+ case C361 => 361
+ case C362 => 362
+ case C363 => 363
+ case C364 => 364
+ case C365 => 365
+ case C366 => 366
+ case C367 => 367
+ case C368 => 368
+ case C369 => 369
+ case C370 => 370
+ case C371 => 371
+ case C372 => 372
+ case C373 => 373
+ case C374 => 374
+ case C375 => 375
+ case C376 => 376
+ case C377 => 377
+ case C378 => 378
+ case C379 => 379
+ case C380 => 380
+ case C381 => 381
+ case C382 => 382
+ case C383 => 383
+ case C384 => 384
+ case C385 => 385
+ case C386 => 386
+ case C387 => 387
+ case C388 => 388
+ case C389 => 389
+ case C390 => 390
+ case C391 => 391
+// case C392 => 392
+ case C393 => 393
+ case C394 => 394
+ case C395 => 395
+ case C396 => 396
+// case C397 => 397
+ case C398 => 398
+ case C399 => 399
+ case C400 => 400
+ }
+}
diff --git a/test/files/neg/t0899.check b/test/files/neg/t0899.check
index 8b71be8e0c..28cb06ae5a 100644
--- a/test/files/neg/t0899.check
+++ b/test/files/neg/t0899.check
@@ -1,10 +1,10 @@
-t0899.scala:9: error: super may be not be used on value o
+t0899.scala:9: error: super may not be used on value o
override val o = "Ha! " + super.o
^
-t0899.scala:11: error: super may be not be used on variable v
+t0899.scala:11: error: super may not be used on variable v
super.v = "aa"
^
-t0899.scala:12: error: super may be not be used on variable v
+t0899.scala:12: error: super may not be used on variable v
println(super.v)
^
three errors found
diff --git a/test/files/neg/t562.check b/test/files/neg/t562.check
index 8c3823642a..95be075af1 100644
--- a/test/files/neg/t562.check
+++ b/test/files/neg/t562.check
@@ -1,4 +1,4 @@
-t562.scala:10: error: super may be not be used on value y
+t562.scala:10: error: super may not be used on value y
override val y = super.y;
^
one error found
diff --git a/test/files/neg/t8731.check b/test/files/neg/t8731.check
index 2a9af475fc..d47bd55b45 100644
--- a/test/files/neg/t8731.check
+++ b/test/files/neg/t8731.check
@@ -1,9 +1,6 @@
-t8731.scala:5: warning: matches with two cases or fewer are emitted using if-then-else instead of switch
- def f(x: Int) = (x: @annotation.switch) match {
- ^
t8731.scala:10: warning: could not emit switch for @switch annotated match
def g(x: Int) = (x: @annotation.switch) match {
^
error: No warnings can be incurred under -Xfatal-warnings.
-two warnings found
+one warning found
one error found
diff --git a/test/files/neg/t9273.check b/test/files/neg/t9273.check
new file mode 100644
index 0000000000..1dca63a736
--- /dev/null
+++ b/test/files/neg/t9273.check
@@ -0,0 +1,10 @@
+t9273.scala:2: error: class type required but ? found
+ val foo: Class[_] = classOf // error without position, line or file
+ ^
+t9273.scala:3: error: not found: type X
+ val foo1: Class[_] = classOf[X] // good error, all info contained
+ ^
+t9273.scala:7: error: not found: type X
+ val foo4: Class[_] = Predef.classOf[X] // good error, all info contained
+ ^
+three errors found
diff --git a/test/files/neg/t9273.scala b/test/files/neg/t9273.scala
new file mode 100644
index 0000000000..3f99dff17f
--- /dev/null
+++ b/test/files/neg/t9273.scala
@@ -0,0 +1,9 @@
+class MissingLineNumbers {
+ val foo: Class[_] = classOf // error without position, line or file
+ val foo1: Class[_] = classOf[X] // good error, all info contained
+ val foo2 = classOf // Infers T=Nothing
+
+ val foo3: Class[_] = Predef.classOf // Infers T=Nothing. Irregular wrt typedIdent.
+ val foo4: Class[_] = Predef.classOf[X] // good error, all info contained
+ val foo5 = Predef.classOf // Infers T=Nothing
+}
diff --git a/test/files/pos/t3368.flags b/test/files/pos/t3368.flags
new file mode 100644
index 0000000000..cb20509902
--- /dev/null
+++ b/test/files/pos/t3368.flags
@@ -0,0 +1 @@
+-Ystop-after:parser
diff --git a/test/files/pos/t3368.scala b/test/files/pos/t3368.scala
new file mode 100644
index 0000000000..c8e861a899
--- /dev/null
+++ b/test/files/pos/t3368.scala
@@ -0,0 +1,5 @@
+
+trait X {
+ // error: in XML literal: name expected, but char '!' cannot start a name
+ def x = <![CDATA[hi & bye]]> <![CDATA[red & black]]>
+}
diff --git a/test/files/pos/t6942.flags b/test/files/pos/t6942.flags
index e8fb65d50c..0f96f1f872 100644
--- a/test/files/pos/t6942.flags
+++ b/test/files/pos/t6942.flags
@@ -1 +1 @@
--Xfatal-warnings \ No newline at end of file
+-nowarn \ No newline at end of file
diff --git a/test/files/pos/t7815.scala b/test/files/pos/t7815.scala
index 12a434c5b0..0a126f9faa 100644
--- a/test/files/pos/t7815.scala
+++ b/test/files/pos/t7815.scala
@@ -21,7 +21,7 @@ object Foo {
object Main extends App {
def mapWithFoo[A <: AnyRef, B](as: List[A])(implicit foo: Foo.Aux[A, B]) = {
// Should be Eta expandable because the result type of `f` is not
- // dependant on the value, it is just `B`.
+ // dependent on the value, it is just `B`.
as map foo.f
as map foo.g
as map foo.m
diff --git a/test/files/pos/t8359-closelim-crash.flags b/test/files/pos/t8359-closelim-crash.flags
new file mode 100644
index 0000000000..49d036a887
--- /dev/null
+++ b/test/files/pos/t8359-closelim-crash.flags
@@ -0,0 +1 @@
+-optimize
diff --git a/test/files/pos/t8359-closelim-crash.scala b/test/files/pos/t8359-closelim-crash.scala
new file mode 100644
index 0000000000..1413694d10
--- /dev/null
+++ b/test/files/pos/t8359-closelim-crash.scala
@@ -0,0 +1,23 @@
+package test
+
+// This is a minimization of code that crashed the compiler during bootstrapping
+// in the first iteration of https://github.com/scala/scala/pull/4373, the PR
+// that adjusted the order of free and declared params in LambdaLift.
+
+// Was:
+// java.lang.AssertionError: assertion failed:
+// Record Record(<$anon: Function1>,Map(value a$1 -> Deref(LocalVar(value b)))) does not contain a field value b$1
+// at scala.tools.nsc.Global.assert(Global.scala:262)
+// at scala.tools.nsc.backend.icode.analysis.CopyPropagation$copyLattice$State.getFieldNonRecordValue(CopyPropagation.scala:113)
+// at scala.tools.nsc.backend.icode.analysis.CopyPropagation$copyLattice$State.getFieldNonRecordValue(CopyPropagation.scala:122)
+// at scala.tools.nsc.backend.opt.ClosureElimination$ClosureElim$$anonfun$analyzeMethod$1$$anonfun$apply$2.replaceFieldAccess$1(ClosureElimination.scala:124)
+class Typer {
+ def bar(a: Boolean, b: Boolean): Unit = {
+ @inline
+ def baz(): Unit = {
+ ((_: Any) => (Typer.this, a, b)).apply("")
+ }
+ ((_: Any) => baz()).apply("")
+ }
+}
+
diff --git a/test/files/pos/t8861.flags b/test/files/pos/t8861.flags
new file mode 100644
index 0000000000..99a6391058
--- /dev/null
+++ b/test/files/pos/t8861.flags
@@ -0,0 +1 @@
+-Xlint:infer-any -Xfatal-warnings
diff --git a/test/files/pos/t8861.scala b/test/files/pos/t8861.scala
new file mode 100644
index 0000000000..816d15700e
--- /dev/null
+++ b/test/files/pos/t8861.scala
@@ -0,0 +1,11 @@
+
+trait Test {
+ type R = PartialFunction[Any, Unit]
+
+ val x: R = { case "" => }
+ val y: R = { case "" => }
+
+ val z: R = x orElse y
+ val zz = x orElse y
+}
+
diff --git a/test/files/pos/t9181.flags b/test/files/pos/t9181.flags
new file mode 100644
index 0000000000..0f96f1f872
--- /dev/null
+++ b/test/files/pos/t9181.flags
@@ -0,0 +1 @@
+-nowarn \ No newline at end of file
diff --git a/test/files/pos/t9181.scala b/test/files/pos/t9181.scala
new file mode 100644
index 0000000000..2edf6fe4a3
--- /dev/null
+++ b/test/files/pos/t9181.scala
@@ -0,0 +1,806 @@
+sealed trait C
+case object C1 extends C
+case object C2 extends C
+case object C3 extends C
+case object C4 extends C
+case object C5 extends C
+case object C6 extends C
+case object C7 extends C
+case object C8 extends C
+case object C9 extends C
+case object C10 extends C
+case object C11 extends C
+case object C12 extends C
+case object C13 extends C
+case object C14 extends C
+case object C15 extends C
+case object C16 extends C
+case object C17 extends C
+case object C18 extends C
+case object C19 extends C
+case object C20 extends C
+case object C21 extends C
+case object C22 extends C
+case object C23 extends C
+case object C24 extends C
+case object C25 extends C
+case object C26 extends C
+case object C27 extends C
+case object C28 extends C
+case object C29 extends C
+case object C30 extends C
+case object C31 extends C
+case object C32 extends C
+case object C33 extends C
+case object C34 extends C
+case object C35 extends C
+case object C36 extends C
+case object C37 extends C
+case object C38 extends C
+case object C39 extends C
+case object C40 extends C
+case object C41 extends C
+case object C42 extends C
+case object C43 extends C
+case object C44 extends C
+case object C45 extends C
+case object C46 extends C
+case object C47 extends C
+case object C48 extends C
+case object C49 extends C
+case object C50 extends C
+case object C51 extends C
+case object C52 extends C
+case object C53 extends C
+case object C54 extends C
+case object C55 extends C
+case object C56 extends C
+case object C57 extends C
+case object C58 extends C
+case object C59 extends C
+case object C60 extends C
+case object C61 extends C
+case object C62 extends C
+case object C63 extends C
+case object C64 extends C
+case object C65 extends C
+case object C66 extends C
+case object C67 extends C
+case object C68 extends C
+case object C69 extends C
+case object C70 extends C
+case object C71 extends C
+case object C72 extends C
+case object C73 extends C
+case object C74 extends C
+case object C75 extends C
+case object C76 extends C
+case object C77 extends C
+case object C78 extends C
+case object C79 extends C
+case object C80 extends C
+case object C81 extends C
+case object C82 extends C
+case object C83 extends C
+case object C84 extends C
+case object C85 extends C
+case object C86 extends C
+case object C87 extends C
+case object C88 extends C
+case object C89 extends C
+case object C90 extends C
+case object C91 extends C
+case object C92 extends C
+case object C93 extends C
+case object C94 extends C
+case object C95 extends C
+case object C96 extends C
+case object C97 extends C
+case object C98 extends C
+case object C99 extends C
+case object C100 extends C
+case object C101 extends C
+case object C102 extends C
+case object C103 extends C
+case object C104 extends C
+case object C105 extends C
+case object C106 extends C
+case object C107 extends C
+case object C108 extends C
+case object C109 extends C
+case object C110 extends C
+case object C111 extends C
+case object C112 extends C
+case object C113 extends C
+case object C114 extends C
+case object C115 extends C
+case object C116 extends C
+case object C117 extends C
+case object C118 extends C
+case object C119 extends C
+case object C120 extends C
+case object C121 extends C
+case object C122 extends C
+case object C123 extends C
+case object C124 extends C
+case object C125 extends C
+case object C126 extends C
+case object C127 extends C
+case object C128 extends C
+case object C129 extends C
+case object C130 extends C
+case object C131 extends C
+case object C132 extends C
+case object C133 extends C
+case object C134 extends C
+case object C135 extends C
+case object C136 extends C
+case object C137 extends C
+case object C138 extends C
+case object C139 extends C
+case object C140 extends C
+case object C141 extends C
+case object C142 extends C
+case object C143 extends C
+case object C144 extends C
+case object C145 extends C
+case object C146 extends C
+case object C147 extends C
+case object C148 extends C
+case object C149 extends C
+case object C150 extends C
+case object C151 extends C
+case object C152 extends C
+case object C153 extends C
+case object C154 extends C
+case object C155 extends C
+case object C156 extends C
+case object C157 extends C
+case object C158 extends C
+case object C159 extends C
+case object C160 extends C
+case object C161 extends C
+case object C162 extends C
+case object C163 extends C
+case object C164 extends C
+case object C165 extends C
+case object C166 extends C
+case object C167 extends C
+case object C168 extends C
+case object C169 extends C
+case object C170 extends C
+case object C171 extends C
+case object C172 extends C
+case object C173 extends C
+case object C174 extends C
+case object C175 extends C
+case object C176 extends C
+case object C177 extends C
+case object C178 extends C
+case object C179 extends C
+case object C180 extends C
+case object C181 extends C
+case object C182 extends C
+case object C183 extends C
+case object C184 extends C
+case object C185 extends C
+case object C186 extends C
+case object C187 extends C
+case object C188 extends C
+case object C189 extends C
+case object C190 extends C
+case object C191 extends C
+case object C192 extends C
+case object C193 extends C
+case object C194 extends C
+case object C195 extends C
+case object C196 extends C
+case object C197 extends C
+case object C198 extends C
+case object C199 extends C
+case object C200 extends C
+case object C201 extends C
+case object C202 extends C
+case object C203 extends C
+case object C204 extends C
+case object C205 extends C
+case object C206 extends C
+case object C207 extends C
+case object C208 extends C
+case object C209 extends C
+case object C210 extends C
+case object C211 extends C
+case object C212 extends C
+case object C213 extends C
+case object C214 extends C
+case object C215 extends C
+case object C216 extends C
+case object C217 extends C
+case object C218 extends C
+case object C219 extends C
+case object C220 extends C
+case object C221 extends C
+case object C222 extends C
+case object C223 extends C
+case object C224 extends C
+case object C225 extends C
+case object C226 extends C
+case object C227 extends C
+case object C228 extends C
+case object C229 extends C
+case object C230 extends C
+case object C231 extends C
+case object C232 extends C
+case object C233 extends C
+case object C234 extends C
+case object C235 extends C
+case object C236 extends C
+case object C237 extends C
+case object C238 extends C
+case object C239 extends C
+case object C240 extends C
+case object C241 extends C
+case object C242 extends C
+case object C243 extends C
+case object C244 extends C
+case object C245 extends C
+case object C246 extends C
+case object C247 extends C
+case object C248 extends C
+case object C249 extends C
+case object C250 extends C
+case object C251 extends C
+case object C252 extends C
+case object C253 extends C
+case object C254 extends C
+case object C255 extends C
+case object C256 extends C
+case object C257 extends C
+case object C258 extends C
+case object C259 extends C
+case object C260 extends C
+case object C261 extends C
+case object C262 extends C
+case object C263 extends C
+case object C264 extends C
+case object C265 extends C
+case object C266 extends C
+case object C267 extends C
+case object C268 extends C
+case object C269 extends C
+case object C270 extends C
+case object C271 extends C
+case object C272 extends C
+case object C273 extends C
+case object C274 extends C
+case object C275 extends C
+case object C276 extends C
+case object C277 extends C
+case object C278 extends C
+case object C279 extends C
+case object C280 extends C
+case object C281 extends C
+case object C282 extends C
+case object C283 extends C
+case object C284 extends C
+case object C285 extends C
+case object C286 extends C
+case object C287 extends C
+case object C288 extends C
+case object C289 extends C
+case object C290 extends C
+case object C291 extends C
+case object C292 extends C
+case object C293 extends C
+case object C294 extends C
+case object C295 extends C
+case object C296 extends C
+case object C297 extends C
+case object C298 extends C
+case object C299 extends C
+case object C300 extends C
+case object C301 extends C
+case object C302 extends C
+case object C303 extends C
+case object C304 extends C
+case object C305 extends C
+case object C306 extends C
+case object C307 extends C
+case object C308 extends C
+case object C309 extends C
+case object C310 extends C
+case object C311 extends C
+case object C312 extends C
+case object C313 extends C
+case object C314 extends C
+case object C315 extends C
+case object C316 extends C
+case object C317 extends C
+case object C318 extends C
+case object C319 extends C
+case object C320 extends C
+case object C321 extends C
+case object C322 extends C
+case object C323 extends C
+case object C324 extends C
+case object C325 extends C
+case object C326 extends C
+case object C327 extends C
+case object C328 extends C
+case object C329 extends C
+case object C330 extends C
+case object C331 extends C
+case object C332 extends C
+case object C333 extends C
+case object C334 extends C
+case object C335 extends C
+case object C336 extends C
+case object C337 extends C
+case object C338 extends C
+case object C339 extends C
+case object C340 extends C
+case object C341 extends C
+case object C342 extends C
+case object C343 extends C
+case object C344 extends C
+case object C345 extends C
+case object C346 extends C
+case object C347 extends C
+case object C348 extends C
+case object C349 extends C
+case object C350 extends C
+case object C351 extends C
+case object C352 extends C
+case object C353 extends C
+case object C354 extends C
+case object C355 extends C
+case object C356 extends C
+case object C357 extends C
+case object C358 extends C
+case object C359 extends C
+case object C360 extends C
+case object C361 extends C
+case object C362 extends C
+case object C363 extends C
+case object C364 extends C
+case object C365 extends C
+case object C366 extends C
+case object C367 extends C
+case object C368 extends C
+case object C369 extends C
+case object C370 extends C
+case object C371 extends C
+case object C372 extends C
+case object C373 extends C
+case object C374 extends C
+case object C375 extends C
+case object C376 extends C
+case object C377 extends C
+case object C378 extends C
+case object C379 extends C
+case object C380 extends C
+case object C381 extends C
+case object C382 extends C
+case object C383 extends C
+case object C384 extends C
+case object C385 extends C
+case object C386 extends C
+case object C387 extends C
+case object C388 extends C
+case object C389 extends C
+case object C390 extends C
+case object C391 extends C
+case object C392 extends C
+case object C393 extends C
+case object C394 extends C
+case object C395 extends C
+case object C396 extends C
+case object C397 extends C
+case object C398 extends C
+case object C399 extends C
+case object C400 extends C
+
+object M {
+ def f(c: C): Int = c match {
+ case C1 => 1
+ case C2 => 2
+ case C3 => 3
+ case C4 => 4
+ case C5 => 5
+ case C6 => 6
+ case C7 => 7
+ case C8 => 8
+ case C9 => 9
+ case C10 => 10
+ case C11 => 11
+ case C12 => 12
+ case C13 => 13
+ case C14 => 14
+ case C15 => 15
+ case C16 => 16
+ case C17 => 17
+ case C18 => 18
+ case C19 => 19
+ case C20 => 20
+ case C21 => 21
+ case C22 => 22
+ case C23 => 23
+ case C24 => 24
+ case C25 => 25
+ case C26 => 26
+ case C27 => 27
+ case C28 => 28
+ case C29 => 29
+ case C30 => 30
+ case C31 => 31
+ case C32 => 32
+ case C33 => 33
+ case C34 => 34
+ case C35 => 35
+ case C36 => 36
+ case C37 => 37
+ case C38 => 38
+ case C39 => 39
+ case C40 => 40
+ case C41 => 41
+ case C42 => 42
+ case C43 => 43
+ case C44 => 44
+ case C45 => 45
+ case C46 => 46
+ case C47 => 47
+ case C48 => 48
+ case C49 => 49
+ case C50 => 50
+ case C51 => 51
+ case C52 => 52
+ case C53 => 53
+ case C54 => 54
+ case C55 => 55
+ case C56 => 56
+ case C57 => 57
+ case C58 => 58
+ case C59 => 59
+ case C60 => 60
+ case C61 => 61
+ case C62 => 62
+ case C63 => 63
+ case C64 => 64
+ case C65 => 65
+ case C66 => 66
+ case C67 => 67
+ case C68 => 68
+ case C69 => 69
+ case C70 => 70
+ case C71 => 71
+ case C72 => 72
+ case C73 => 73
+ case C74 => 74
+ case C75 => 75
+ case C76 => 76
+ case C77 => 77
+ case C78 => 78
+ case C79 => 79
+ case C80 => 80
+ case C81 => 81
+ case C82 => 82
+ case C83 => 83
+ case C84 => 84
+ case C85 => 85
+ case C86 => 86
+ case C87 => 87
+ case C88 => 88
+ case C89 => 89
+ case C90 => 90
+ case C91 => 91
+ case C92 => 92
+ case C93 => 93
+ case C94 => 94
+ case C95 => 95
+ case C96 => 96
+ case C97 => 97
+ case C98 => 98
+ case C99 => 99
+ case C100 => 100
+ case C101 => 101
+ case C102 => 102
+ case C103 => 103
+ case C104 => 104
+ case C105 => 105
+ case C106 => 106
+ case C107 => 107
+ case C108 => 108
+ case C109 => 109
+ case C110 => 110
+ case C111 => 111
+ case C112 => 112
+ case C113 => 113
+ case C114 => 114
+ case C115 => 115
+ case C116 => 116
+ case C117 => 117
+ case C118 => 118
+ case C119 => 119
+ case C120 => 120
+ case C121 => 121
+ case C122 => 122
+ case C123 => 123
+ case C124 => 124
+ case C125 => 125
+ case C126 => 126
+ case C127 => 127
+ case C128 => 128
+ case C129 => 129
+ case C130 => 130
+ case C131 => 131
+ case C132 => 132
+ case C133 => 133
+ case C134 => 134
+ case C135 => 135
+ case C136 => 136
+ case C137 => 137
+ case C138 => 138
+ case C139 => 139
+ case C140 => 140
+ case C141 => 141
+ case C142 => 142
+ case C143 => 143
+ case C144 => 144
+ case C145 => 145
+ case C146 => 146
+ case C147 => 147
+ case C148 => 148
+ case C149 => 149
+ case C150 => 150
+ case C151 => 151
+ case C152 => 152
+ case C153 => 153
+ case C154 => 154
+ case C155 => 155
+ case C156 => 156
+ case C157 => 157
+ case C158 => 158
+ case C159 => 159
+ case C160 => 160
+ case C161 => 161
+ case C162 => 162
+ case C163 => 163
+ case C164 => 164
+ case C165 => 165
+ case C166 => 166
+ case C167 => 167
+ case C168 => 168
+ case C169 => 169
+ case C170 => 170
+ case C171 => 171
+ case C172 => 172
+ case C173 => 173
+ case C174 => 174
+ case C175 => 175
+ case C176 => 176
+ case C177 => 177
+ case C178 => 178
+ case C179 => 179
+ case C180 => 180
+ case C181 => 181
+ case C182 => 182
+ case C183 => 183
+ case C184 => 184
+ case C185 => 185
+ case C186 => 186
+ case C187 => 187
+ case C188 => 188
+ case C189 => 189
+ case C190 => 190
+ case C191 => 191
+ case C192 => 192
+ case C193 => 193
+ case C194 => 194
+ case C195 => 195
+ case C196 => 196
+ case C197 => 197
+ case C198 => 198
+ case C199 => 199
+ case C200 => 200
+ case C201 => 201
+ case C202 => 202
+ case C203 => 203
+ case C204 => 204
+ case C205 => 205
+ case C206 => 206
+ case C207 => 207
+ case C208 => 208
+ case C209 => 209
+ case C210 => 210
+ case C211 => 211
+ case C212 => 212
+ case C213 => 213
+ case C214 => 214
+ case C215 => 215
+ case C216 => 216
+ case C217 => 217
+ case C218 => 218
+ case C219 => 219
+ case C220 => 220
+ case C221 => 221
+ case C222 => 222
+ case C223 => 223
+ case C224 => 224
+ case C225 => 225
+ case C226 => 226
+ case C227 => 227
+ case C228 => 228
+ case C229 => 229
+ case C230 => 230
+ case C231 => 231
+ case C232 => 232
+ case C233 => 233
+ case C234 => 234
+ case C235 => 235
+ case C236 => 236
+ case C237 => 237
+ case C238 => 238
+ case C239 => 239
+ case C240 => 240
+ case C241 => 241
+ case C242 => 242
+ case C243 => 243
+ case C244 => 244
+ case C245 => 245
+ case C246 => 246
+ case C247 => 247
+ case C248 => 248
+ case C249 => 249
+ case C250 => 250
+ case C251 => 251
+ case C252 => 252
+ case C253 => 253
+ case C254 => 254
+ case C255 => 255
+ case C256 => 256
+ case C257 => 257
+ case C258 => 258
+ case C259 => 259
+ case C260 => 260
+ case C261 => 261
+ case C262 => 262
+ case C263 => 263
+ case C264 => 264
+ case C265 => 265
+ case C266 => 266
+ case C267 => 267
+ case C268 => 268
+ case C269 => 269
+ case C270 => 270
+ case C271 => 271
+ case C272 => 272
+ case C273 => 273
+ case C274 => 274
+ case C275 => 275
+ case C276 => 276
+ case C277 => 277
+ case C278 => 278
+ case C279 => 279
+ case C280 => 280
+ case C281 => 281
+ case C282 => 282
+ case C283 => 283
+ case C284 => 284
+ case C285 => 285
+ case C286 => 286
+ case C287 => 287
+ case C288 => 288
+ case C289 => 289
+ case C290 => 290
+ case C291 => 291
+ case C292 => 292
+ case C293 => 293
+ case C294 => 294
+ case C295 => 295
+ case C296 => 296
+ case C297 => 297
+ case C298 => 298
+ case C299 => 299
+ case C300 => 300
+ case C301 => 301
+ case C302 => 302
+ case C303 => 303
+ case C304 => 304
+ case C305 => 305
+ case C306 => 306
+ case C307 => 307
+ case C308 => 308
+ case C309 => 309
+ case C310 => 310
+ case C311 => 311
+ case C312 => 312
+ case C313 => 313
+ case C314 => 314
+ case C315 => 315
+ case C316 => 316
+ case C317 => 317
+ case C318 => 318
+ case C319 => 319
+ case C320 => 320
+ case C321 => 321
+ case C322 => 322
+ case C323 => 323
+ case C324 => 324
+ case C325 => 325
+ case C326 => 326
+ case C327 => 327
+ case C328 => 328
+ case C329 => 329
+ case C330 => 330
+ case C331 => 331
+ case C332 => 332
+ case C333 => 333
+ case C334 => 334
+ case C335 => 335
+ case C336 => 336
+ case C337 => 337
+ case C338 => 338
+ case C339 => 339
+ case C340 => 340
+ case C341 => 341
+ case C342 => 342
+ case C343 => 343
+ case C344 => 344
+ case C345 => 345
+ case C346 => 346
+ case C347 => 347
+ case C348 => 348
+ case C349 => 349
+ case C350 => 350
+ case C351 => 351
+ case C352 => 352
+ case C353 => 353
+ case C354 => 354
+ case C355 => 355
+ case C356 => 356
+ case C357 => 357
+ case C358 => 358
+ case C359 => 359
+ case C360 => 360
+ case C361 => 361
+ case C362 => 362
+ case C363 => 363
+ case C364 => 364
+ case C365 => 365
+ case C366 => 366
+ case C367 => 367
+ case C368 => 368
+ case C369 => 369
+ case C370 => 370
+ case C371 => 371
+ case C372 => 372
+ case C373 => 373
+ case C374 => 374
+ case C375 => 375
+ case C376 => 376
+ case C377 => 377
+ case C378 => 378
+ case C379 => 379
+ case C380 => 380
+ case C381 => 381
+ case C382 => 382
+ case C383 => 383
+ case C384 => 384
+ case C385 => 385
+ case C386 => 386
+ case C387 => 387
+ case C388 => 388
+ case C389 => 389
+ case C390 => 390
+ case C391 => 391
+ case C392 => 392
+ case C393 => 393
+ case C394 => 394
+ case C395 => 395
+ case C396 => 396
+ case C397 => 397
+ case C398 => 398
+ case C399 => 399
+ case C400 => 400
+ }
+}
diff --git a/test/files/pos/t9239/Declaration.scala b/test/files/pos/t9239/Declaration.scala
new file mode 100644
index 0000000000..452dcc1e77
--- /dev/null
+++ b/test/files/pos/t9239/Declaration.scala
@@ -0,0 +1,3 @@
+class Foo[A]
+trait Bar[A] extends Foo[A]
+class Baz[A] extends Bar[A]
diff --git a/test/files/pos/t9239/Usage.java b/test/files/pos/t9239/Usage.java
new file mode 100644
index 0000000000..d1e3fb0c3e
--- /dev/null
+++ b/test/files/pos/t9239/Usage.java
@@ -0,0 +1,15 @@
+/**
+ * Used to fail with:
+ *
+ * Usage.java:5: error: incompatible types: Baz<String> cannot be converted to Foo<String>
+ * foo(f);
+ * ^
+ */
+public class Usage {
+ public Usage() {
+ Baz<String> f = null;
+ foo(f);
+ }
+
+ public void foo(Foo<String> f) { };
+}
diff --git a/test/files/run/classfile-format-51.scala b/test/files/run/classfile-format-51.scala
index 24b1ee8397..7523130afa 100644
--- a/test/files/run/classfile-format-51.scala
+++ b/test/files/run/classfile-format-51.scala
@@ -12,7 +12,7 @@ import Opcodes._
// it runs a normal compile on the source in the 'code' field that refers to
// DynamicInvoker. Any failure will be dumped to std out.
//
-// By it's nature the test can only work on JDK 7+ because under JDK 6 some of the
+// By its nature the test can only work on JDK 7+ because under JDK 6 some of the
// classes referred to by DynamicInvoker won't be available and DynamicInvoker won't
// verify. So the test includes a version check that short-circuites the whole test
// on JDK 6
diff --git a/test/files/run/classfile-format-52.scala b/test/files/run/classfile-format-52.scala
index e12c84124c..453f61ac84 100644
--- a/test/files/run/classfile-format-52.scala
+++ b/test/files/run/classfile-format-52.scala
@@ -11,7 +11,7 @@ import Opcodes._
// HasDefaultMethod. Then it runs a normal compile on Scala source that extends that
// interface. Any failure will be dumped to std out.
//
-// By it's nature the test can only work on JDK 8+ because under JDK 7- the
+// By its nature the test can only work on JDK 8+ because under JDK 7- the
// interface won't verify.
object Test extends DirectTest {
override def extraSettings: String = "-optimise -usejavacp -d " + testOutput.path + " -cp " + testOutput.path
diff --git a/test/files/run/delambdafy-specialized.check b/test/files/run/delambdafy-specialized.check
new file mode 100644
index 0000000000..c6903b9e29
--- /dev/null
+++ b/test/files/run/delambdafy-specialized.check
@@ -0,0 +1 @@
+scala.runtime.AbstractFunction1$mcII$sp
diff --git a/test/files/run/delambdafy-specialized.flags b/test/files/run/delambdafy-specialized.flags
new file mode 100644
index 0000000000..48b438ddf8
--- /dev/null
+++ b/test/files/run/delambdafy-specialized.flags
@@ -0,0 +1 @@
+-Ydelambdafy:method
diff --git a/test/files/run/delambdafy-specialized.scala b/test/files/run/delambdafy-specialized.scala
new file mode 100644
index 0000000000..634d4e490b
--- /dev/null
+++ b/test/files/run/delambdafy-specialized.scala
@@ -0,0 +1,6 @@
+object Test {
+ def main(args: Array[String]): Unit = {
+ val f = (x: Int) => -x
+ println(f.getClass.getSuperclass.getName)
+ }
+}
diff --git a/test/files/run/delambdafy_t6028.check b/test/files/run/delambdafy_t6028.check
index 7bd8cd7202..419e7043a3 100644
--- a/test/files/run/delambdafy_t6028.check
+++ b/test/files/run/delambdafy_t6028.check
@@ -1,35 +1,35 @@
[[syntax trees at end of lambdalift]] // newSource1.scala
package <empty> {
class T extends Object {
- <paramaccessor> private[this] val classParam: Int = _;
- def <init>(classParam: Int): T = {
+ <paramaccessor> private[this] val classParam: String = _;
+ def <init>(classParam: String): T = {
T.super.<init>();
()
};
- private[this] val field: Int = 0;
- <stable> <accessor> def field(): Int = T.this.field;
- def foo(methodParam: Int): Function0 = {
- val methodLocal: Int = 0;
+ private[this] val field: String = "";
+ <stable> <accessor> def field(): String = T.this.field;
+ def foo(methodParam: String): Function0 = {
+ val methodLocal: String = "";
{
(() => T.this.$anonfun$1(methodParam, methodLocal)).$asInstanceOf[Function0]()
}
};
- def bar(barParam: Int): Object = {
+ def bar(barParam: String): Object = {
@volatile var MethodLocalObject$module: runtime.VolatileObjectRef = scala.runtime.VolatileObjectRef.zero();
T.this.MethodLocalObject$1(barParam, MethodLocalObject$module)
};
- def tryy(tryyParam: Int): Function0 = {
- var tryyLocal: runtime.IntRef = scala.runtime.IntRef.create(0);
+ def tryy(tryyParam: String): Function0 = {
+ var tryyLocal: runtime.ObjectRef = scala.runtime.ObjectRef.create("");
{
- (() => T.this.$anonfun$2(tryyParam, tryyLocal)).$asInstanceOf[Function0]()
+ (new <$anon: Function0>(T.this, tryyParam, tryyLocal): Function0)
}
};
- final <artifact> private[this] def $anonfun$1(methodParam$1: Int, methodLocal$1: Int): Int = T.this.classParam.+(T.this.field()).+(methodParam$1).+(methodLocal$1);
+ final <artifact> private[this] def $anonfun$1(methodParam$1: String, methodLocal$1: String): String = T.this.classParam.+(T.this.field()).+(methodParam$1).+(methodLocal$1);
abstract trait MethodLocalTrait$1 extends Object {
<synthetic> <stable> <artifact> def $outer(): T
};
object MethodLocalObject$2 extends Object with T#MethodLocalTrait$1 {
- def <init>($outer: T, barParam$1: Int): T#MethodLocalObject$2.type = {
+ def <init>($outer: T, barParam$1: String): T#MethodLocalObject$2.type = {
MethodLocalObject$2.super.<init>();
MethodLocalObject$2.this.$asInstanceOf[T#MethodLocalTrait$1$class]()./*MethodLocalTrait$1$class*/$init$(barParam$1);
()
@@ -38,19 +38,34 @@ package <empty> {
<synthetic> <stable> <artifact> def $outer(): T = MethodLocalObject$2.this.$outer;
<synthetic> <stable> <artifact> def $outer(): T = MethodLocalObject$2.this.$outer
};
- final <stable> private[this] def MethodLocalObject$1(barParam$1: Int, MethodLocalObject$module$1: runtime.VolatileObjectRef): T#MethodLocalObject$2.type = {
+ final <stable> private[this] def MethodLocalObject$1(barParam$1: String, MethodLocalObject$module$1: runtime.VolatileObjectRef): T#MethodLocalObject$2.type = {
MethodLocalObject$module$1.elem = new T#MethodLocalObject$2.type(T.this, barParam$1);
MethodLocalObject$module$1.elem.$asInstanceOf[T#MethodLocalObject$2.type]()
};
abstract trait MethodLocalTrait$1$class extends Object with T#MethodLocalTrait$1 {
- def /*MethodLocalTrait$1$class*/$init$(barParam$1: Int): Unit = {
+ def /*MethodLocalTrait$1$class*/$init$(barParam$1: String): Unit = {
()
};
- scala.this.Predef.print(scala.Int.box(barParam$1))
+ scala.this.Predef.print(barParam$1)
};
- final <artifact> private[this] def $anonfun$2(tryyParam$1: Int, tryyLocal$1: runtime.IntRef): Unit = try {
- tryyLocal$1.elem = tryyParam$1
- } finally ()
+ @SerialVersionUID(value = 0) final <synthetic> class $anonfun$tryy$1 extends scala.runtime.AbstractFunction0$mcV$sp with Serializable {
+ def <init>($outer: T, tryyParam$1: String, tryyLocal$1: runtime.ObjectRef): <$anon: Function0> = {
+ $anonfun$tryy$1.super.<init>();
+ ()
+ };
+ final def apply(): Unit = $anonfun$tryy$1.this.apply$mcV$sp();
+ <specialized> def apply$mcV$sp(): Unit = try {
+ $anonfun$tryy$1.this.tryyLocal$1.elem = $anonfun$tryy$1.this.tryyParam$1
+ } finally ();
+ <synthetic> <paramaccessor> <artifact> private[this] val $outer: T = _;
+ <synthetic> <stable> <artifact> def $outer(): T = $anonfun$tryy$1.this.$outer;
+ final <bridge> <artifact> def apply(): Object = {
+ $anonfun$tryy$1.this.apply();
+ scala.runtime.BoxedUnit.UNIT
+ };
+ <synthetic> <paramaccessor> private[this] val tryyParam$1: String = _;
+ <synthetic> <paramaccessor> private[this] val tryyLocal$1: runtime.ObjectRef = _
+ }
}
}
diff --git a/test/files/run/delambdafy_t6028.scala b/test/files/run/delambdafy_t6028.scala
index 0b7ef48c3d..ca39195310 100644
--- a/test/files/run/delambdafy_t6028.scala
+++ b/test/files/run/delambdafy_t6028.scala
@@ -5,11 +5,11 @@ object Test extends DirectTest {
override def extraSettings: String = "-usejavacp -Ydelambdafy:method -Xprint:lambdalift -d " + testOutput.path
- override def code = """class T(classParam: Int) {
- | val field: Int = 0
- | def foo(methodParam: Int) = {val methodLocal = 0 ; () => classParam + field + methodParam + methodLocal }
- | def bar(barParam: Int) = { trait MethodLocalTrait { print(barParam) }; object MethodLocalObject extends MethodLocalTrait; MethodLocalObject }
- | def tryy(tryyParam: Int) = { var tryyLocal = 0; () => try { tryyLocal = tryyParam } finally () }
+ override def code = """class T(classParam: String) {
+ | val field: String = ""
+ | def foo(methodParam: String) = {val methodLocal = "" ; () => classParam + field + methodParam + methodLocal }
+ | def bar(barParam: String) = { trait MethodLocalTrait { print(barParam) }; object MethodLocalObject extends MethodLocalTrait; MethodLocalObject }
+ | def tryy(tryyParam: String) = { var tryyLocal = ""; () => try { tryyLocal = tryyParam } finally () }
|}
|""".stripMargin.trim
diff --git a/test/files/run/delambdafy_t6555.check b/test/files/run/delambdafy_t6555.check
index 6b174c0d2a..b6ccebde78 100644
--- a/test/files/run/delambdafy_t6555.check
+++ b/test/files/run/delambdafy_t6555.check
@@ -5,11 +5,11 @@ package <empty> {
Foo.super.<init>();
()
};
- private[this] val f: Int => Int = {
- final <artifact> def $anonfun(param: Int): Int = param;
- ((param: Int) => $anonfun(param))
+ private[this] val f: String => String = {
+ final <artifact> def $anonfun(param: String): String = param;
+ ((param: String) => $anonfun(param))
};
- <stable> <accessor> def f(): Int => Int = Foo.this.f
+ <stable> <accessor> def f(): String => String = Foo.this.f
}
}
diff --git a/test/files/run/delambdafy_t6555.scala b/test/files/run/delambdafy_t6555.scala
index a1dcfe790c..8d4976e989 100644
--- a/test/files/run/delambdafy_t6555.scala
+++ b/test/files/run/delambdafy_t6555.scala
@@ -5,7 +5,7 @@ object Test extends DirectTest {
override def extraSettings: String = "-usejavacp -Xprint:specialize -Ydelambdafy:method -d " + testOutput.path
- override def code = "class Foo { val f = (param: Int) => param } "
+ override def code = "class Foo { val f = (param: String) => param } "
override def show(): Unit = {
Console.withErr(System.out) {
diff --git a/test/files/run/delambdafy_uncurry_byname_method.check b/test/files/run/delambdafy_uncurry_byname_method.check
index cd3edc7d6f..e0f281b1cd 100644
--- a/test/files/run/delambdafy_uncurry_byname_method.check
+++ b/test/files/run/delambdafy_uncurry_byname_method.check
@@ -5,9 +5,9 @@ package <empty> {
Foo.super.<init>();
()
};
- def bar(x: () => Int): Int = x.apply();
- def foo(): Int = Foo.this.bar({
- final <artifact> def $anonfun(): Int = 1;
+ def bar(x: () => String): String = x.apply();
+ def foo(): String = Foo.this.bar({
+ final <artifact> def $anonfun(): String = "";
(() => $anonfun())
})
}
diff --git a/test/files/run/delambdafy_uncurry_byname_method.scala b/test/files/run/delambdafy_uncurry_byname_method.scala
index 1adeec8433..0ccc1f2e92 100644
--- a/test/files/run/delambdafy_uncurry_byname_method.scala
+++ b/test/files/run/delambdafy_uncurry_byname_method.scala
@@ -6,9 +6,9 @@ object Test extends DirectTest {
override def extraSettings: String = "-usejavacp -Xprint:uncurry -Ydelambdafy:method -Ystop-after:uncurry -d " + testOutput.path
override def code = """class Foo {
- | def bar(x: => Int) = x
+ | def bar(x: => String) = x
|
- | def foo = bar(1)
+ | def foo = bar("")
|}
|""".stripMargin.trim
diff --git a/test/files/run/repl-javap-lambdas.scala b/test/files/run/repl-javap-lambdas.scala
index 15e5bf6877..76a6ec8450 100644
--- a/test/files/run/repl-javap-lambdas.scala
+++ b/test/files/run/repl-javap-lambdas.scala
@@ -7,8 +7,8 @@ object Test extends JavapTest {
def code = """
|object Betty {
| List(1,2,3) count (_ % 2 != 0)
- | def f = List(1,2,3) filter (_ % 2 != 0) map (_ * 2)
- | def g = List(1,2,3) filter (_ % 2 == 0) map (_ * 3) map (_ + 1)
+ | def f = List(1,2,3) filter ((x: Any) => true) map (x => "m1")
+ | def g = List(1,2,3) filter ((x: Any) => true) map (x => "m1") map (x => "m2")
|}
|:javap -fun Betty#g
""".stripMargin
@@ -16,7 +16,7 @@ object Test extends JavapTest {
// three anonfuns of Betty#g
override def yah(res: Seq[String]) = {
import PartialFunction.{ cond => when }
- val r = """\s*private static final .* \$anonfun\$\d+\(.*""".r
+ val r = """.*final .* .*\$anonfun\$\d+\(.*""".r
def filtered = res filter (when(_) { case r(_*) => true })
3 == filtered.size
}
diff --git a/test/files/run/t3368-b.check b/test/files/run/t3368-b.check
new file mode 100644
index 0000000000..4cbe98c577
--- /dev/null
+++ b/test/files/run/t3368-b.check
@@ -0,0 +1,89 @@
+[[syntax trees at end of parser]] // newSource1.scala
+package <empty> {
+ abstract trait X extends scala.AnyRef {
+ def $init$() = {
+ ()
+ };
+ def x = {
+ val $buf = new _root_.scala.xml.NodeBuffer();
+ $buf.$amp$plus(new _root_.scala.xml.PCData("hi & bye"));
+ $buf.$amp$plus(new _root_.scala.xml.PCData("red & black"));
+ $buf
+ }
+ };
+ abstract trait Y extends scala.AnyRef {
+ def $init$() = {
+ ()
+ };
+ def y = {
+ {
+ new _root_.scala.xml.Elem(null, "a", _root_.scala.xml.Null, $scope, false, ({
+ val $buf = new _root_.scala.xml.NodeBuffer();
+ $buf.$amp$plus({
+ {
+ new _root_.scala.xml.Elem(null, "b", _root_.scala.xml.Null, $scope, true)
+ }
+ });
+ $buf.$amp$plus(new _root_.scala.xml.Text("start"));
+ $buf.$amp$plus(new _root_.scala.xml.PCData("hi & bye"));
+ $buf.$amp$plus({
+ {
+ new _root_.scala.xml.Elem(null, "c", _root_.scala.xml.Null, $scope, true)
+ }
+ });
+ $buf.$amp$plus(new _root_.scala.xml.Text("world"));
+ $buf.$amp$plus({
+ {
+ new _root_.scala.xml.Elem(null, "d", _root_.scala.xml.Null, $scope, true)
+ }
+ });
+ $buf.$amp$plus(new _root_.scala.xml.Text("stuff"));
+ $buf.$amp$plus(new _root_.scala.xml.PCData("red & black"));
+ $buf
+ }: _*))
+ }
+ }
+ };
+ abstract trait Z extends scala.AnyRef {
+ def $init$() = {
+ ()
+ };
+ def d = new _root_.scala.xml.PCData("hello, world");
+ def e = {
+ val $buf = new _root_.scala.xml.NodeBuffer();
+ $buf.$amp$plus(new _root_.scala.xml.PCData("hello, world"));
+ $buf.$amp$plus(new _root_.scala.xml.PCData("hello, world"));
+ $buf
+ };
+ def f = {
+ {
+ new _root_.scala.xml.Elem(null, "foo", _root_.scala.xml.Null, $scope, false, ({
+ val $buf = new _root_.scala.xml.NodeBuffer();
+ $buf.$amp$plus(new _root_.scala.xml.Text("x"));
+ $buf.$amp$plus(new _root_.scala.xml.PCData("hello, world"));
+ $buf
+ }: _*))
+ }
+ };
+ def g = {
+ {
+ new _root_.scala.xml.Elem(null, "foo", _root_.scala.xml.Null, $scope, false, ({
+ val $buf = new _root_.scala.xml.NodeBuffer();
+ $buf.$amp$plus(new _root_.scala.xml.PCData("hello, world"));
+ $buf
+ }: _*))
+ }
+ };
+ def h = {
+ {
+ new _root_.scala.xml.Elem(null, "foo", _root_.scala.xml.Null, $scope, false, ({
+ val $buf = new _root_.scala.xml.NodeBuffer();
+ $buf.$amp$plus(new _root_.scala.xml.PCData("hello, world"));
+ $buf.$amp$plus(new _root_.scala.xml.PCData("hello, world"));
+ $buf
+ }: _*))
+ }
+ }
+ }
+}
+
diff --git a/test/files/run/t3368-b.scala b/test/files/run/t3368-b.scala
new file mode 100644
index 0000000000..108cb9a5ee
--- /dev/null
+++ b/test/files/run/t3368-b.scala
@@ -0,0 +1,26 @@
+
+import scala.tools.partest.ParserTest
+
+
+object Test extends ParserTest {
+
+ override def code = """
+ trait X {
+ // error: in XML literal: name expected, but char '!' cannot start a name
+ def x = <![CDATA[hi & bye]]> <![CDATA[red & black]]>
+ }
+ trait Y {
+ def y = <a><b/>start<![CDATA[hi & bye]]><c/>world<d/>stuff<![CDATA[red & black]]></a>
+ }
+ trait Z {
+ def d = <![CDATA[hello, world]]>
+ def e = <![CDATA[hello, world]]><![CDATA[hello, world]]> // top level not coalesced
+ def f = <foo>x<![CDATA[hello, world]]></foo> // adjoining text
+ def g = <foo><![CDATA[hello, world]]></foo> // text node when coalescing
+ def h = <foo><![CDATA[hello, world]]><![CDATA[hello, world]]></foo>
+ }
+ """
+
+ // not coalescing
+ override def extraSettings = s"${super.extraSettings} -Xxml:-coalescing"
+}
diff --git a/test/files/run/t3368-c.check b/test/files/run/t3368-c.check
new file mode 100644
index 0000000000..e0c10cc0dd
--- /dev/null
+++ b/test/files/run/t3368-c.check
@@ -0,0 +1,85 @@
+[[syntax trees at end of parser]] // newSource1.scala
+package <empty> {
+ abstract trait X extends scala.AnyRef {
+ def $init$() = {
+ ()
+ };
+ def x = {
+ val $buf = new _root_.scala.xml.NodeBuffer();
+ $buf.$amp$plus(new _root_.scala.xml.Text("hi & bye"));
+ $buf.$amp$plus(new _root_.scala.xml.Text("red & black"));
+ $buf
+ }
+ };
+ abstract trait Y extends scala.AnyRef {
+ def $init$() = {
+ ()
+ };
+ def y = {
+ {
+ new _root_.scala.xml.Elem(null, "a", _root_.scala.xml.Null, $scope, false, ({
+ val $buf = new _root_.scala.xml.NodeBuffer();
+ $buf.$amp$plus({
+ {
+ new _root_.scala.xml.Elem(null, "b", _root_.scala.xml.Null, $scope, true)
+ }
+ });
+ $buf.$amp$plus(new _root_.scala.xml.Text("starthi & bye"));
+ $buf.$amp$plus({
+ {
+ new _root_.scala.xml.Elem(null, "c", _root_.scala.xml.Null, $scope, true)
+ }
+ });
+ $buf.$amp$plus(new _root_.scala.xml.Text("world"));
+ $buf.$amp$plus({
+ {
+ new _root_.scala.xml.Elem(null, "d", _root_.scala.xml.Null, $scope, true)
+ }
+ });
+ $buf.$amp$plus(new _root_.scala.xml.Text("stuffred & black"));
+ $buf
+ }: _*))
+ }
+ }
+ };
+ abstract trait Z extends scala.AnyRef {
+ def $init$() = {
+ ()
+ };
+ def d = new _root_.scala.xml.Text("hello, world");
+ def e = {
+ val $buf = new _root_.scala.xml.NodeBuffer();
+ $buf.$amp$plus(new _root_.scala.xml.Text("hello, world"));
+ $buf.$amp$plus(new _root_.scala.xml.Text("hello, world"));
+ $buf
+ };
+ def f = {
+ {
+ new _root_.scala.xml.Elem(null, "foo", _root_.scala.xml.Null, $scope, false, ({
+ val $buf = new _root_.scala.xml.NodeBuffer();
+ $buf.$amp$plus(new _root_.scala.xml.Text("xhello, world"));
+ $buf
+ }: _*))
+ }
+ };
+ def g = {
+ {
+ new _root_.scala.xml.Elem(null, "foo", _root_.scala.xml.Null, $scope, false, ({
+ val $buf = new _root_.scala.xml.NodeBuffer();
+ $buf.$amp$plus(new _root_.scala.xml.Text("hello, world"));
+ $buf
+ }: _*))
+ }
+ };
+ def h = {
+ {
+ new _root_.scala.xml.Elem(null, "foo", _root_.scala.xml.Null, $scope, false, ({
+ val $buf = new _root_.scala.xml.NodeBuffer();
+ $buf.$amp$plus(new _root_.scala.xml.Text("hello, worldhello, world"));
+ $buf
+ }: _*))
+ }
+ }
+ }
+}
+
diff --git a/test/files/run/t3368-c.scala b/test/files/run/t3368-c.scala
new file mode 100644
index 0000000000..5121794463
--- /dev/null
+++ b/test/files/run/t3368-c.scala
@@ -0,0 +1,26 @@
+
+import scala.tools.partest.ParserTest
+
+
+object Test extends ParserTest {
+
+ override def code = """
+ trait X {
+ // error: in XML literal: name expected, but char '!' cannot start a name
+ def x = <![CDATA[hi & bye]]> <![CDATA[red & black]]>
+ }
+ trait Y {
+ def y = <a><b/>start<![CDATA[hi & bye]]><c/>world<d/>stuff<![CDATA[red & black]]></a>
+ }
+ trait Z {
+ def d = <![CDATA[hello, world]]>
+ def e = <![CDATA[hello, world]]><![CDATA[hello, world]]> // top level not coalesced
+ def f = <foo>x<![CDATA[hello, world]]></foo> // adjoining text
+ def g = <foo><![CDATA[hello, world]]></foo> // text node when coalescing
+ def h = <foo><![CDATA[hello, world]]><![CDATA[hello, world]]></foo>
+ }
+ """
+
+ // default coalescing behavior, whatever that is today.
+ //override def extraSettings = s"${super.extraSettings} -Xxml:coalescing"
+}
diff --git a/test/files/run/t3368-d.check b/test/files/run/t3368-d.check
new file mode 100644
index 0000000000..4cbe98c577
--- /dev/null
+++ b/test/files/run/t3368-d.check
@@ -0,0 +1,89 @@
+[[syntax trees at end of parser]] // newSource1.scala
+package <empty> {
+ abstract trait X extends scala.AnyRef {
+ def $init$() = {
+ ()
+ };
+ def x = {
+ val $buf = new _root_.scala.xml.NodeBuffer();
+ $buf.$amp$plus(new _root_.scala.xml.PCData("hi & bye"));
+ $buf.$amp$plus(new _root_.scala.xml.PCData("red & black"));
+ $buf
+ }
+ };
+ abstract trait Y extends scala.AnyRef {
+ def $init$() = {
+ ()
+ };
+ def y = {
+ {
+ new _root_.scala.xml.Elem(null, "a", _root_.scala.xml.Null, $scope, false, ({
+ val $buf = new _root_.scala.xml.NodeBuffer();
+ $buf.$amp$plus({
+ {
+ new _root_.scala.xml.Elem(null, "b", _root_.scala.xml.Null, $scope, true)
+ }
+ });
+ $buf.$amp$plus(new _root_.scala.xml.Text("start"));
+ $buf.$amp$plus(new _root_.scala.xml.PCData("hi & bye"));
+ $buf.$amp$plus({
+ {
+ new _root_.scala.xml.Elem(null, "c", _root_.scala.xml.Null, $scope, true)
+ }
+ });
+ $buf.$amp$plus(new _root_.scala.xml.Text("world"));
+ $buf.$amp$plus({
+ {
+ new _root_.scala.xml.Elem(null, "d", _root_.scala.xml.Null, $scope, true)
+ }
+ });
+ $buf.$amp$plus(new _root_.scala.xml.Text("stuff"));
+ $buf.$amp$plus(new _root_.scala.xml.PCData("red & black"));
+ $buf
+ }: _*))
+ }
+ }
+ };
+ abstract trait Z extends scala.AnyRef {
+ def $init$() = {
+ ()
+ };
+ def d = new _root_.scala.xml.PCData("hello, world");
+ def e = {
+ val $buf = new _root_.scala.xml.NodeBuffer();
+ $buf.$amp$plus(new _root_.scala.xml.PCData("hello, world"));
+ $buf.$amp$plus(new _root_.scala.xml.PCData("hello, world"));
+ $buf
+ };
+ def f = {
+ {
+ new _root_.scala.xml.Elem(null, "foo", _root_.scala.xml.Null, $scope, false, ({
+ val $buf = new _root_.scala.xml.NodeBuffer();
+ $buf.$amp$plus(new _root_.scala.xml.Text("x"));
+ $buf.$amp$plus(new _root_.scala.xml.PCData("hello, world"));
+ $buf
+ }: _*))
+ }
+ };
+ def g = {
+ {
+ new _root_.scala.xml.Elem(null, "foo", _root_.scala.xml.Null, $scope, false, ({
+ val $buf = new _root_.scala.xml.NodeBuffer();
+ $buf.$amp$plus(new _root_.scala.xml.PCData("hello, world"));
+ $buf
+ }: _*))
+ }
+ };
+ def h = {
+ {
+ new _root_.scala.xml.Elem(null, "foo", _root_.scala.xml.Null, $scope, false, ({
+ val $buf = new _root_.scala.xml.NodeBuffer();
+ $buf.$amp$plus(new _root_.scala.xml.PCData("hello, world"));
+ $buf.$amp$plus(new _root_.scala.xml.PCData("hello, world"));
+ $buf
+ }: _*))
+ }
+ }
+ }
+}
+
diff --git a/test/files/run/t3368-d.scala b/test/files/run/t3368-d.scala
new file mode 100644
index 0000000000..5777c1a81e
--- /dev/null
+++ b/test/files/run/t3368-d.scala
@@ -0,0 +1,26 @@
+
+import scala.tools.partest.ParserTest
+
+
+object Test extends ParserTest {
+
+ override def code = """
+ trait X {
+ // error: in XML literal: name expected, but char '!' cannot start a name
+ def x = <![CDATA[hi & bye]]> <![CDATA[red & black]]>
+ }
+ trait Y {
+ def y = <a><b/>start<![CDATA[hi & bye]]><c/>world<d/>stuff<![CDATA[red & black]]></a>
+ }
+ trait Z {
+ def d = <![CDATA[hello, world]]>
+ def e = <![CDATA[hello, world]]><![CDATA[hello, world]]> // top level not coalesced
+ def f = <foo>x<![CDATA[hello, world]]></foo> // adjoining text
+ def g = <foo><![CDATA[hello, world]]></foo> // text node when coalescing
+ def h = <foo><![CDATA[hello, world]]><![CDATA[hello, world]]></foo>
+ }
+ """
+
+ // default under 2.12 is not coalescing
+ override def extraSettings = s"${super.extraSettings} -Xsource:212"
+}
diff --git a/test/files/run/t3368.check b/test/files/run/t3368.check
new file mode 100644
index 0000000000..e0c10cc0dd
--- /dev/null
+++ b/test/files/run/t3368.check
@@ -0,0 +1,85 @@
+[[syntax trees at end of parser]] // newSource1.scala
+package <empty> {
+ abstract trait X extends scala.AnyRef {
+ def $init$() = {
+ ()
+ };
+ def x = {
+ val $buf = new _root_.scala.xml.NodeBuffer();
+ $buf.$amp$plus(new _root_.scala.xml.Text("hi & bye"));
+ $buf.$amp$plus(new _root_.scala.xml.Text("red & black"));
+ $buf
+ }
+ };
+ abstract trait Y extends scala.AnyRef {
+ def $init$() = {
+ ()
+ };
+ def y = {
+ {
+ new _root_.scala.xml.Elem(null, "a", _root_.scala.xml.Null, $scope, false, ({
+ val $buf = new _root_.scala.xml.NodeBuffer();
+ $buf.$amp$plus({
+ {
+ new _root_.scala.xml.Elem(null, "b", _root_.scala.xml.Null, $scope, true)
+ }
+ });
+ $buf.$amp$plus(new _root_.scala.xml.Text("starthi & bye"));
+ $buf.$amp$plus({
+ {
+ new _root_.scala.xml.Elem(null, "c", _root_.scala.xml.Null, $scope, true)
+ }
+ });
+ $buf.$amp$plus(new _root_.scala.xml.Text("world"));
+ $buf.$amp$plus({
+ {
+ new _root_.scala.xml.Elem(null, "d", _root_.scala.xml.Null, $scope, true)
+ }
+ });
+ $buf.$amp$plus(new _root_.scala.xml.Text("stuffred & black"));
+ $buf
+ }: _*))
+ }
+ }
+ };
+ abstract trait Z extends scala.AnyRef {
+ def $init$() = {
+ ()
+ };
+ def d = new _root_.scala.xml.Text("hello, world");
+ def e = {
+ val $buf = new _root_.scala.xml.NodeBuffer();
+ $buf.$amp$plus(new _root_.scala.xml.Text("hello, world"));
+ $buf.$amp$plus(new _root_.scala.xml.Text("hello, world"));
+ $buf
+ };
+ def f = {
+ {
+ new _root_.scala.xml.Elem(null, "foo", _root_.scala.xml.Null, $scope, false, ({
+ val $buf = new _root_.scala.xml.NodeBuffer();
+ $buf.$amp$plus(new _root_.scala.xml.Text("xhello, world"));
+ $buf
+ }: _*))
+ }
+ };
+ def g = {
+ {
+ new _root_.scala.xml.Elem(null, "foo", _root_.scala.xml.Null, $scope, false, ({
+ val $buf = new _root_.scala.xml.NodeBuffer();
+ $buf.$amp$plus(new _root_.scala.xml.Text("hello, world"));
+ $buf
+ }: _*))
+ }
+ };
+ def h = {
+ {
+ new _root_.scala.xml.Elem(null, "foo", _root_.scala.xml.Null, $scope, false, ({
+ val $buf = new _root_.scala.xml.NodeBuffer();
+ $buf.$amp$plus(new _root_.scala.xml.Text("hello, worldhello, world"));
+ $buf
+ }: _*))
+ }
+ }
+ }
+}
+
diff --git a/test/files/run/t3368.scala b/test/files/run/t3368.scala
new file mode 100644
index 0000000000..284fed0784
--- /dev/null
+++ b/test/files/run/t3368.scala
@@ -0,0 +1,26 @@
+
+import scala.tools.partest.ParserTest
+
+
+object Test extends ParserTest {
+
+ override def code = """
+ trait X {
+ // error: in XML literal: name expected, but char '!' cannot start a name
+ def x = <![CDATA[hi & bye]]> <![CDATA[red & black]]>
+ }
+ trait Y {
+ def y = <a><b/>start<![CDATA[hi & bye]]><c/>world<d/>stuff<![CDATA[red & black]]></a>
+ }
+ trait Z {
+ def d = <![CDATA[hello, world]]>
+ def e = <![CDATA[hello, world]]><![CDATA[hello, world]]> // top level not coalesced
+ def f = <foo>x<![CDATA[hello, world]]></foo> // adjoining text
+ def g = <foo><![CDATA[hello, world]]></foo> // text node when coalescing
+ def h = <foo><![CDATA[hello, world]]><![CDATA[hello, world]]></foo>
+ }
+ """
+
+ // coalescing
+ override def extraSettings = s"${super.extraSettings} -Xxml:coalescing"
+}
diff --git a/test/files/run/t5699.scala b/test/files/run/t5699.scala
index ec3b1d26b4..409bcd250c 100755
--- a/test/files/run/t5699.scala
+++ b/test/files/run/t5699.scala
@@ -1,21 +1,13 @@
-import scala.tools.partest.DirectTest
+import scala.tools.partest.ParserTest
import scala.reflect.internal.util.BatchSourceFile
-object Test extends DirectTest {
+object Test extends ParserTest {
// Java code
override def code = """
|public @interface MyAnnotation { String value(); }
""".stripMargin
- override def extraSettings: String = "-usejavacp -Ystop-after:typer -Xprint:parser"
-
- override def show(): Unit = {
- // redirect err to out, for logging
- val prevErr = System.err
- System.setErr(System.out)
- compile()
- System.setErr(prevErr)
- }
+ override def extraSettings: String = "-usejavacp -Ystop-after:namer -Xprint:parser"
override def newSources(sourceCodes: String*) = {
assert(sourceCodes.size == 1)
diff --git a/test/files/run/t7407.flags b/test/files/run/t7407.flags
index be4ef0798a..ffc65f4b81 100644
--- a/test/files/run/t7407.flags
+++ b/test/files/run/t7407.flags
@@ -1 +1 @@
--Ynooptimise -Yopt:l:none -Ybackend:GenBCode
+-Yopt:l:none -Ybackend:GenBCode
diff --git a/test/files/run/t7407b.flags b/test/files/run/t7407b.flags
index c8547a27dc..c30091d3de 100644
--- a/test/files/run/t7407b.flags
+++ b/test/files/run/t7407b.flags
@@ -1 +1 @@
--Ynooptimise -Ybackend:GenBCode
+-Ybackend:GenBCode
diff --git a/test/files/run/t7741a/GroovyInterface$1Dump.java b/test/files/run/t7741a/GroovyInterface$1Dump.java
new file mode 100644
index 0000000000..0c0eab3f1b
--- /dev/null
+++ b/test/files/run/t7741a/GroovyInterface$1Dump.java
@@ -0,0 +1,222 @@
+import java.util.*;
+import scala.tools.asm.*;
+
+// generated with
+// git clone alewando/scala_groovy_interop
+// SCALA_HOME=... GROOVY_HOME=... ant
+// cd /code/scala2
+// java -classpath build/asm/classes:/Users/jason/code/scala_groovy_interop/classes:/code/scala2/build/pack/lib/scala-library.jar:/usr/local/Cellar/groovy/2.4.1/libexec/embeddable/groovy-all-2.4.1.jar scala.tools.asm.util.ASMifier 'GroovyInterface$1'
+// java -classpath build/asm/classes:/Users/jason/code/scala_groovy_interop/classes:/code/scala2/build/pack/lib/scala-library.jar:/usr/local/Cellar/groovy/2.4.1/libexec/embeddable/groovy-all-2.4.1.jar scala.tools.asm.util.ASMifier 'GroovyInterface$1'
+public class GroovyInterface$1Dump implements Opcodes {
+
+ public static byte[] dump () throws Exception {
+
+ ClassWriter cw = new ClassWriter(0);
+ FieldVisitor fv;
+ MethodVisitor mv;
+ AnnotationVisitor av0;
+
+ cw.visit(V1_5, ACC_SUPER + ACC_SYNTHETIC, "GroovyInterface$1", null, "java/lang/Object", new String[] {});
+
+ cw.visitInnerClass("GroovyInterface$1", "GroovyInterface", "1", ACC_SYNTHETIC);
+
+ {
+ fv = cw.visitField(ACC_STATIC + ACC_SYNTHETIC, "$class$GroovyInterface", "Ljava/lang/Class;", null, null);
+ fv.visitEnd();
+ }
+ {
+ fv = cw.visitField(ACC_PRIVATE + ACC_STATIC + ACC_SYNTHETIC, "$staticClassInfo", "Lorg/codehaus/groovy/reflection/ClassInfo;", null, null);
+ fv.visitEnd();
+ }
+ {
+ fv = cw.visitField(ACC_PUBLIC + ACC_STATIC + ACC_TRANSIENT + ACC_SYNTHETIC, "__$stMC", "Z", null, null);
+ fv.visitEnd();
+ }
+ {
+ fv = cw.visitField(ACC_PRIVATE + ACC_TRANSIENT + ACC_SYNTHETIC, "metaClass", "Lgroovy/lang/MetaClass;", null, null);
+ fv.visitEnd();
+ }
+ {
+ fv = cw.visitField(ACC_PRIVATE + ACC_STATIC + ACC_SYNTHETIC, "$callSiteArray", "Ljava/lang/ref/SoftReference;", null, null);
+ fv.visitEnd();
+ }
+ {
+ mv = cw.visitMethod(ACC_PUBLIC, "<init>", "()V", null, null);
+ mv.visitCode();
+ mv.visitVarInsn(ALOAD, 0);
+ mv.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "<init>", "()V", false);
+ mv.visitMethodInsn(INVOKESTATIC, "GroovyInterface$1", "$getCallSiteArray", "()[Lorg/codehaus/groovy/runtime/callsite/CallSite;", false);
+ mv.visitVarInsn(ASTORE, 1);
+ mv.visitVarInsn(ALOAD, 0);
+ mv.visitMethodInsn(INVOKEVIRTUAL, "GroovyInterface$1", "$getStaticMetaClass", "()Lgroovy/lang/MetaClass;", false);
+ mv.visitVarInsn(ASTORE, 2);
+ mv.visitVarInsn(ALOAD, 2);
+ mv.visitVarInsn(ALOAD, 0);
+ mv.visitInsn(SWAP);
+ mv.visitFieldInsn(PUTFIELD, "GroovyInterface$1", "metaClass", "Lgroovy/lang/MetaClass;");
+ mv.visitVarInsn(ALOAD, 2);
+ mv.visitInsn(POP);
+ mv.visitInsn(RETURN);
+ mv.visitMaxs(2, 3);
+ mv.visitEnd();
+ }
+ {
+ mv = cw.visitMethod(ACC_PROTECTED + ACC_SYNTHETIC, "$getStaticMetaClass", "()Lgroovy/lang/MetaClass;", null, null);
+ mv.visitCode();
+ mv.visitVarInsn(ALOAD, 0);
+ mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Object", "getClass", "()Ljava/lang/Class;", false);
+ mv.visitLdcInsn(Type.getType("LGroovyInterface$1;"));
+ Label l0 = new Label();
+ mv.visitJumpInsn(IF_ACMPEQ, l0);
+ mv.visitVarInsn(ALOAD, 0);
+ mv.visitMethodInsn(INVOKESTATIC, "org/codehaus/groovy/runtime/ScriptBytecodeAdapter", "initMetaClass", "(Ljava/lang/Object;)Lgroovy/lang/MetaClass;", false);
+ mv.visitInsn(ARETURN);
+ mv.visitLabel(l0);
+ mv.visitFieldInsn(GETSTATIC, "GroovyInterface$1", "$staticClassInfo", "Lorg/codehaus/groovy/reflection/ClassInfo;");
+ mv.visitVarInsn(ASTORE, 1);
+ mv.visitVarInsn(ALOAD, 1);
+ Label l1 = new Label();
+ mv.visitJumpInsn(IFNONNULL, l1);
+ mv.visitVarInsn(ALOAD, 0);
+ mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Object", "getClass", "()Ljava/lang/Class;", false);
+ mv.visitMethodInsn(INVOKESTATIC, "org/codehaus/groovy/reflection/ClassInfo", "getClassInfo", "(Ljava/lang/Class;)Lorg/codehaus/groovy/reflection/ClassInfo;", false);
+ mv.visitInsn(DUP);
+ mv.visitVarInsn(ASTORE, 1);
+ mv.visitFieldInsn(PUTSTATIC, "GroovyInterface$1", "$staticClassInfo", "Lorg/codehaus/groovy/reflection/ClassInfo;");
+ mv.visitLabel(l1);
+ mv.visitVarInsn(ALOAD, 1);
+ mv.visitMethodInsn(INVOKEVIRTUAL, "org/codehaus/groovy/reflection/ClassInfo", "getMetaClass", "()Lgroovy/lang/MetaClass;", false);
+ mv.visitInsn(ARETURN);
+ mv.visitMaxs(2, 2);
+ mv.visitEnd();
+ }
+ {
+ mv = cw.visitMethod(ACC_PUBLIC + ACC_SYNTHETIC, "getMetaClass", "()Lgroovy/lang/MetaClass;", null, null);
+ mv.visitCode();
+ mv.visitVarInsn(ALOAD, 0);
+ mv.visitFieldInsn(GETFIELD, "GroovyInterface$1", "metaClass", "Lgroovy/lang/MetaClass;");
+ mv.visitInsn(DUP);
+ Label l0 = new Label();
+ mv.visitJumpInsn(IFNULL, l0);
+ mv.visitInsn(ARETURN);
+ mv.visitLabel(l0);
+ mv.visitInsn(POP);
+ mv.visitVarInsn(ALOAD, 0);
+ mv.visitInsn(DUP);
+ mv.visitMethodInsn(INVOKEVIRTUAL, "GroovyInterface$1", "$getStaticMetaClass", "()Lgroovy/lang/MetaClass;", false);
+ mv.visitFieldInsn(PUTFIELD, "GroovyInterface$1", "metaClass", "Lgroovy/lang/MetaClass;");
+ mv.visitVarInsn(ALOAD, 0);
+ mv.visitFieldInsn(GETFIELD, "GroovyInterface$1", "metaClass", "Lgroovy/lang/MetaClass;");
+ mv.visitInsn(ARETURN);
+ mv.visitMaxs(2, 1);
+ mv.visitEnd();
+ }
+ {
+ mv = cw.visitMethod(ACC_PUBLIC + ACC_SYNTHETIC, "setMetaClass", "(Lgroovy/lang/MetaClass;)V", null, null);
+ mv.visitCode();
+ mv.visitVarInsn(ALOAD, 0);
+ mv.visitVarInsn(ALOAD, 1);
+ mv.visitFieldInsn(PUTFIELD, "GroovyInterface$1", "metaClass", "Lgroovy/lang/MetaClass;");
+ mv.visitInsn(RETURN);
+ mv.visitMaxs(2, 2);
+ mv.visitEnd();
+ }
+ {
+ mv = cw.visitMethod(ACC_PUBLIC + ACC_SYNTHETIC, "invokeMethod", "(Ljava/lang/String;Ljava/lang/Object;)Ljava/lang/Object;", null, null);
+ mv.visitCode();
+ mv.visitVarInsn(ALOAD, 0);
+ mv.visitMethodInsn(INVOKEVIRTUAL, "GroovyInterface$1", "getMetaClass", "()Lgroovy/lang/MetaClass;", false);
+ mv.visitVarInsn(ALOAD, 0);
+ mv.visitVarInsn(ALOAD, 1);
+ mv.visitVarInsn(ALOAD, 2);
+ mv.visitMethodInsn(INVOKEINTERFACE, "groovy/lang/MetaClass", "invokeMethod", "(Ljava/lang/Object;Ljava/lang/String;Ljava/lang/Object;)Ljava/lang/Object;", true);
+ mv.visitInsn(ARETURN);
+ mv.visitMaxs(4, 3);
+ mv.visitEnd();
+ }
+ {
+ mv = cw.visitMethod(ACC_PUBLIC + ACC_SYNTHETIC, "getProperty", "(Ljava/lang/String;)Ljava/lang/Object;", null, null);
+ mv.visitCode();
+ mv.visitVarInsn(ALOAD, 0);
+ mv.visitMethodInsn(INVOKEVIRTUAL, "GroovyInterface$1", "getMetaClass", "()Lgroovy/lang/MetaClass;", false);
+ mv.visitVarInsn(ALOAD, 0);
+ mv.visitVarInsn(ALOAD, 1);
+ mv.visitMethodInsn(INVOKEINTERFACE, "groovy/lang/MetaClass", "getProperty", "(Ljava/lang/Object;Ljava/lang/String;)Ljava/lang/Object;", true);
+ mv.visitInsn(ARETURN);
+ mv.visitMaxs(3, 2);
+ mv.visitEnd();
+ }
+ {
+ mv = cw.visitMethod(ACC_PUBLIC + ACC_SYNTHETIC, "setProperty", "(Ljava/lang/String;Ljava/lang/Object;)V", null, null);
+ mv.visitCode();
+ mv.visitVarInsn(ALOAD, 0);
+ mv.visitMethodInsn(INVOKEVIRTUAL, "GroovyInterface$1", "getMetaClass", "()Lgroovy/lang/MetaClass;", false);
+ mv.visitVarInsn(ALOAD, 0);
+ mv.visitVarInsn(ALOAD, 1);
+ mv.visitVarInsn(ALOAD, 2);
+ mv.visitMethodInsn(INVOKEINTERFACE, "groovy/lang/MetaClass", "setProperty", "(Ljava/lang/Object;Ljava/lang/String;Ljava/lang/Object;)V", true);
+ mv.visitInsn(RETURN);
+ mv.visitMaxs(4, 3);
+ mv.visitEnd();
+ }
+ {
+ mv = cw.visitMethod(ACC_STATIC, "<clinit>", "()V", null, null);
+ mv.visitCode();
+ mv.visitLdcInsn(Type.getType("LGroovyInterface;"));
+ mv.visitVarInsn(ASTORE, 0);
+ mv.visitVarInsn(ALOAD, 0);
+ mv.visitFieldInsn(PUTSTATIC, "GroovyInterface$1", "$class$GroovyInterface", "Ljava/lang/Class;");
+ mv.visitVarInsn(ALOAD, 0);
+ mv.visitInsn(POP);
+ mv.visitInsn(RETURN);
+ mv.visitMaxs(1, 1);
+ mv.visitEnd();
+ }
+ {
+ mv = cw.visitMethod(ACC_PRIVATE + ACC_STATIC + ACC_SYNTHETIC, "$createCallSiteArray", "()Lorg/codehaus/groovy/runtime/callsite/CallSiteArray;", null, null);
+ mv.visitCode();
+ mv.visitLdcInsn(new Integer(0));
+ mv.visitTypeInsn(ANEWARRAY, "java/lang/String");
+ mv.visitVarInsn(ASTORE, 0);
+ mv.visitTypeInsn(NEW, "org/codehaus/groovy/runtime/callsite/CallSiteArray");
+ mv.visitInsn(DUP);
+ mv.visitLdcInsn(Type.getType("LGroovyInterface$1;"));
+ mv.visitVarInsn(ALOAD, 0);
+ mv.visitMethodInsn(INVOKESPECIAL, "org/codehaus/groovy/runtime/callsite/CallSiteArray", "<init>", "(Ljava/lang/Class;[Ljava/lang/String;)V", false);
+ mv.visitInsn(ARETURN);
+ mv.visitMaxs(4, 1);
+ mv.visitEnd();
+ }
+ {
+ mv = cw.visitMethod(ACC_PUBLIC + ACC_STATIC + ACC_SYNTHETIC, "$getCallSiteArray", "()[Lorg/codehaus/groovy/runtime/callsite/CallSite;", null, null);
+ mv.visitCode();
+ mv.visitFieldInsn(GETSTATIC, "GroovyInterface$1", "$callSiteArray", "Ljava/lang/ref/SoftReference;");
+ Label l0 = new Label();
+ mv.visitJumpInsn(IFNULL, l0);
+ mv.visitFieldInsn(GETSTATIC, "GroovyInterface$1", "$callSiteArray", "Ljava/lang/ref/SoftReference;");
+ mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/ref/SoftReference", "get", "()Ljava/lang/Object;", false);
+ mv.visitTypeInsn(CHECKCAST, "org/codehaus/groovy/runtime/callsite/CallSiteArray");
+ mv.visitInsn(DUP);
+ mv.visitVarInsn(ASTORE, 0);
+ Label l1 = new Label();
+ mv.visitJumpInsn(IFNONNULL, l1);
+ mv.visitLabel(l0);
+ mv.visitMethodInsn(INVOKESTATIC, "GroovyInterface$1", "$createCallSiteArray", "()Lorg/codehaus/groovy/runtime/callsite/CallSiteArray;", false);
+ mv.visitVarInsn(ASTORE, 0);
+ mv.visitTypeInsn(NEW, "java/lang/ref/SoftReference");
+ mv.visitInsn(DUP);
+ mv.visitVarInsn(ALOAD, 0);
+ mv.visitMethodInsn(INVOKESPECIAL, "java/lang/ref/SoftReference", "<init>", "(Ljava/lang/Object;)V", false);
+ mv.visitFieldInsn(PUTSTATIC, "GroovyInterface$1", "$callSiteArray", "Ljava/lang/ref/SoftReference;");
+ mv.visitLabel(l1);
+ mv.visitVarInsn(ALOAD, 0);
+ mv.visitFieldInsn(GETFIELD, "org/codehaus/groovy/runtime/callsite/CallSiteArray", "array", "[Lorg/codehaus/groovy/runtime/callsite/CallSite;");
+ mv.visitInsn(ARETURN);
+ mv.visitMaxs(3, 1);
+ mv.visitEnd();
+ }
+ cw.visitEnd();
+
+ return cw.toByteArray();
+ }
+}
diff --git a/test/files/run/t7741a/GroovyInterfaceDump.java b/test/files/run/t7741a/GroovyInterfaceDump.java
new file mode 100644
index 0000000000..87c09e272f
--- /dev/null
+++ b/test/files/run/t7741a/GroovyInterfaceDump.java
@@ -0,0 +1,51 @@
+import java.util.*;
+import scala.tools.asm.*;
+
+// generated with
+// git clone alewando/scala_groovy_interop
+// SCALA_HOME=... GROOVY_HOME=... ant
+// cd /code/scala2
+// java -classpath build/asm/classes:/Users/jason/code/scala_groovy_interop/classes:/code/scala2/build/pack/lib/scala-library.jar:/usr/local/Cellar/groovy/2.4.1/libexec/embeddable/groovy-all-2.4.1.jar scala.tools.asm.util.ASMifier 'GroovyInterface$1'
+// java -classpath build/asm/classes:/Users/jason/code/scala_groovy_interop/classes:/code/scala2/build/pack/lib/scala-library.jar:/usr/local/Cellar/groovy/2.4.1/libexec/embeddable/groovy-all-2.4.1.jar scala.tools.asm.util.ASMifier 'GroovyInterface$1'
+public class GroovyInterfaceDump implements Opcodes {
+
+ public static byte[] dump () throws Exception {
+
+ ClassWriter cw = new ClassWriter(0);
+ FieldVisitor fv;
+ MethodVisitor mv;
+ AnnotationVisitor av0;
+
+ cw.visit(V1_5, ACC_PUBLIC + ACC_ABSTRACT + ACC_INTERFACE, "GroovyInterface", null, "java/lang/Object", null);
+
+ cw.visitInnerClass("GroovyInterface$1", "GroovyInterface", "1", ACC_SYNTHETIC);
+
+ cw.visitInnerClass("GroovyInterface$__clinit__closure1", null, null, 0);
+
+ {
+ fv = cw.visitField(ACC_PUBLIC + ACC_FINAL + ACC_STATIC, "closure", "Ljava/lang/Object;", null, null);
+ fv.visitEnd();
+ }
+ {
+ mv = cw.visitMethod(ACC_STATIC, "<clinit>", "()V", null, null);
+ mv.visitCode();
+ mv.visitTypeInsn(NEW, "GroovyInterface$__clinit__closure1");
+ mv.visitInsn(DUP);
+ mv.visitFieldInsn(GETSTATIC, "GroovyInterface$1", "$class$GroovyInterface", "Ljava/lang/Class;");
+ mv.visitFieldInsn(GETSTATIC, "GroovyInterface$1", "$class$GroovyInterface", "Ljava/lang/Class;");
+ mv.visitMethodInsn(INVOKESPECIAL, "GroovyInterface$__clinit__closure1", "<init>", "(Ljava/lang/Object;Ljava/lang/Object;)V", false);
+ mv.visitVarInsn(ASTORE, 0);
+ mv.visitVarInsn(ALOAD, 0);
+ mv.visitFieldInsn(PUTSTATIC, "GroovyInterface", "closure", "Ljava/lang/Object;");
+ mv.visitVarInsn(ALOAD, 0);
+ mv.visitInsn(POP);
+ mv.visitInsn(RETURN);
+ mv.visitMaxs(4, 1);
+ mv.visitEnd();
+ }
+ cw.visitEnd();
+
+ return cw.toByteArray();
+ }
+}
+
diff --git a/test/files/run/t7741a/Test.scala b/test/files/run/t7741a/Test.scala
new file mode 100644
index 0000000000..cdba1cccf8
--- /dev/null
+++ b/test/files/run/t7741a/Test.scala
@@ -0,0 +1,47 @@
+import java.io.{ByteArrayInputStream, FileOutputStream, BufferedOutputStream}
+import java.util
+
+import java.io.File
+
+import scala.tools.partest.DirectTest
+
+object Test extends DirectTest {
+
+ def code = ""
+
+ override def show(): Unit = {
+
+ val class1: Array[Byte] = GroovyInterfaceDump.dump()
+ val class2: Array[Byte] = GroovyInterface$1Dump.dump()
+ def writeFile(contents: Array[Byte], f: java.io.File): Unit = {
+ val out = new BufferedOutputStream(new FileOutputStream(f))
+ try {
+ out.write(contents)
+ } finally out.close()
+ }
+
+ val outdir = testOutput.jfile
+
+ // interface GroovyInterface {
+ //
+ // // This is the line that causes scalac to choke.
+ // // It results in a GroovyInterface$1 class, which is a non-static inner class but its constructor does not
+ // // include the implicit parameter that is the immediate enclosing instance.
+ // // See http://jira.codehaus.org/browse/GROOVY-7312
+ // //
+ // // Scalac error:
+ // // [scalac] error: error while loading 1, class file '..../scala_groovy_interop/classes/com/example/groovy/GroovyInterface$1.class' is broken
+ // // [scalac] (class java.util.NoSuchElementException/head of empty list)
+ // final static def closure = { x -> "banana" }
+ //
+ // }
+ writeFile(GroovyInterfaceDump.dump(), new File(outdir, "GroovyInterface.class"))
+ writeFile(GroovyInterface$1Dump.dump(), new File(outdir, "GroovyInterface$1.class"))
+ compileCode("object Test { def foo(g: GroovyInterface) = g.toString }")
+ }
+
+ def compileCode(code: String) = {
+ val classpath = List(sys.props("partest.lib"), testOutput.path) mkString sys.props("path.separator")
+ compileString(newCompiler("-cp", classpath, "-d", testOutput.path))(code)
+ }
+}
diff --git a/test/files/run/t7741b.check b/test/files/run/t7741b.check
new file mode 100644
index 0000000000..a19e54aa3a
--- /dev/null
+++ b/test/files/run/t7741b.check
@@ -0,0 +1,3 @@
+1. Don't refer to Inner
+2. Refering to Inner
+pos: NoPosition Class file for HasInner$Inner not found ERROR
diff --git a/test/files/run/t7741b/HasInner.java b/test/files/run/t7741b/HasInner.java
new file mode 100644
index 0000000000..a1d0d0d81a
--- /dev/null
+++ b/test/files/run/t7741b/HasInner.java
@@ -0,0 +1,3 @@
+class HasInner {
+ class Inner {}
+}
diff --git a/test/files/run/t7741b/Test.scala b/test/files/run/t7741b/Test.scala
new file mode 100644
index 0000000000..569ae6b679
--- /dev/null
+++ b/test/files/run/t7741b/Test.scala
@@ -0,0 +1,29 @@
+import java.io.File
+
+import scala.tools.partest.StoreReporterDirectTest
+
+object Test extends StoreReporterDirectTest {
+
+ def code = ""
+
+ override def show(): Unit = {
+ deleteClass("HasInner$Inner")
+ println("1. Don't refer to Inner")
+ compileCode("class Test { def test(x: HasInner) = x }")
+ assert(filteredInfos.isEmpty, filteredInfos)
+ println("2. Refering to Inner")
+ compileCode("class Test { def test(x: HasInner#Inner) = x }")
+ println(filteredInfos.mkString("\n"))
+ }
+
+ def deleteClass(name: String) {
+ val classFile = new File(testOutput.path, name + ".class")
+ assert(classFile.exists)
+ assert(classFile.delete())
+ }
+
+ def compileCode(code: String) = {
+ val classpath = List(sys.props("partest.lib"), testOutput.path) mkString sys.props("path.separator")
+ compileString(newCompiler("-cp", classpath, "-d", testOutput.path))(code)
+ }
+}
diff --git a/test/files/run/t8845.flags b/test/files/run/t8845.flags
index aada25f80d..c30091d3de 100644
--- a/test/files/run/t8845.flags
+++ b/test/files/run/t8845.flags
@@ -1 +1 @@
--Ybackend:GenBCode -Ynooptimize
+-Ybackend:GenBCode
diff --git a/test/files/run/t8925.flags b/test/files/run/t8925.flags
index be4ef0798a..ffc65f4b81 100644
--- a/test/files/run/t8925.flags
+++ b/test/files/run/t8925.flags
@@ -1 +1 @@
--Ynooptimise -Yopt:l:none -Ybackend:GenBCode
+-Yopt:l:none -Ybackend:GenBCode
diff --git a/test/files/run/t9097.scala b/test/files/run/t9097.scala
index d2bf55fc44..aa2b23bbac 100644
--- a/test/files/run/t9097.scala
+++ b/test/files/run/t9097.scala
@@ -15,7 +15,7 @@ object Test extends StoreReporterDirectTest {
override def code = """package o
|package a {
| class C {
- | def hihi = List(1,2).map(_ * 2)
+ | def hihi = List(1,2).map(_ => "")
| }
|}
|package object a {
diff --git a/test/files/run/t9252.check b/test/files/run/t9252.check
new file mode 100644
index 0000000000..b00d748f7f
--- /dev/null
+++ b/test/files/run/t9252.check
@@ -0,0 +1 @@
+class [Lscala.runtime.BoxedUnit;
diff --git a/test/files/run/t9252.scala b/test/files/run/t9252.scala
new file mode 100644
index 0000000000..da698948e1
--- /dev/null
+++ b/test/files/run/t9252.scala
@@ -0,0 +1,5 @@
+import scala.reflect.runtime.universe._
+
+object Test extends App {
+ println(rootMirror.runtimeClass(typeOf[Array[Unit]]))
+} \ No newline at end of file
diff --git a/test/files/run/t9268.check b/test/files/run/t9268.check
new file mode 100644
index 0000000000..90ef940eb3
--- /dev/null
+++ b/test/files/run/t9268.check
@@ -0,0 +1,5 @@
+Compiling Client1
+pos: NoPosition Class Waiter not found - continuing with a stub. WARNING
+Compiling Client2
+pos: NoPosition Class Waiter not found - continuing with a stub. WARNING
+pos: NoPosition Unable to locate class corresponding to inner class entry for Predicate in owner Waiter ERROR
diff --git a/test/files/run/t9268/Java.java b/test/files/run/t9268/Java.java
new file mode 100644
index 0000000000..c9a0bec3ff
--- /dev/null
+++ b/test/files/run/t9268/Java.java
@@ -0,0 +1,12 @@
+public class Java {
+}
+
+class Partial {
+ public <E extends java.lang.Exception> long waitFor(long l, Waiter.Predicate<E> pred) throws E {
+ return 0L;
+ }
+}
+
+class Waiter {
+ interface Predicate<E> {}
+}
diff --git a/test/files/run/t9268/Test.scala b/test/files/run/t9268/Test.scala
new file mode 100644
index 0000000000..813cbe7b60
--- /dev/null
+++ b/test/files/run/t9268/Test.scala
@@ -0,0 +1,40 @@
+import scala.tools.partest._
+import java.io.File
+
+object Test extends StoreReporterDirectTest {
+ def code = ???
+
+ def compileCode(code: String) = {
+ val classpath = List(sys.props("partest.lib"), testOutput.path) mkString sys.props("path.separator")
+ compileString(newCompiler("-cp", classpath, "-d", testOutput.path))(code)
+ }
+
+ def client1 = """
+ class Client1 { def p(p: Partial) = p.toString }
+ """
+
+ def client2 = """
+ class Client2 { def p(p: Partial) = p.waitFor() }
+ """
+
+ def deleteClass(s: String) = {
+ val f = new File(testOutput.path, s + ".class")
+ assert(f.exists)
+ f.delete()
+ }
+
+ def show(): Unit = {
+ deleteClass("Waiter")
+ deleteClass("Waiter$Predicate")
+
+ // Used to crash in Java Generic Signature parsing
+ println("Compiling Client1")
+ compileCode(client1)
+ println(storeReporter.infos.mkString("\n"))
+ storeReporter.reset()
+ println("Compiling Client2")
+ compileCode(client2)
+ println(storeReporter.infos.mkString("\n"))
+ }
+}
+
diff --git a/test/files/run/valueClassSelfType.scala b/test/files/run/valueClassSelfType.scala
new file mode 100644
index 0000000000..47a3764b0a
--- /dev/null
+++ b/test/files/run/valueClassSelfType.scala
@@ -0,0 +1,52 @@
+trait T
+
+class V1(val l: Long) extends AnyVal { self: T =>
+ def foo: V1 = self
+ def bar: T = self
+}
+
+class V2(val l: Long) extends AnyVal { self =>
+ def foo: V2 = self
+}
+
+class V3(val l: Long) extends AnyVal { self: Long =>
+ def foo: V3 = self
+ def bar: Long = self
+}
+
+// non-value classes
+
+class C1(val l: Long) { self: T =>
+ def foo: C1 = self
+ def bar: T = self
+}
+
+class C2(val l: Long) { self =>
+ def foo: C2 = self
+}
+
+class C3(val l: Long) { self: Long =>
+ def foo: C3 = self
+ def bar: Long = self
+}
+
+object Test extends App {
+ // Rejected: superclass V1 is not a subclass of the superclass Object of the mixin trait T
+ // new V1(1l) with T
+
+ assert(new V2(1l).foo.l == 1l)
+
+ // Rejected: V3 does not conform to its self-type V3 with Long
+ // new V3(1l)
+
+ val c2 = new C1(2l) with T
+ assert(c2.foo.l + c2.bar.asInstanceOf[C1].l == 4l)
+
+ assert(new C2(3l).foo.l == 3l)
+
+ // Rejected: C3 does not conform to its self-type C3 with Long
+ // new C3(4l)
+
+ // Rejected: class Long needs to be a trait to be mixed in
+ // new C3(4l) with Long
+}
diff --git a/test/junit/scala/collection/mutable/VectorTest.scala b/test/junit/scala/collection/mutable/VectorTest.scala
index e9c4d44a72..b3219d1b02 100644
--- a/test/junit/scala/collection/mutable/VectorTest.scala
+++ b/test/junit/scala/collection/mutable/VectorTest.scala
@@ -38,7 +38,6 @@ class VectorTest {
def iteratorCat() {
def its = vecs.map(_.toList.toIterator)
val cats = vecs.map(a => its.map(a ++ _))
- println(cats)
assert( cats == ans )
}
diff --git a/test/junit/scala/concurrent/duration/SerializationTest.scala b/test/junit/scala/concurrent/duration/SerializationTest.scala
new file mode 100644
index 0000000000..af90a10984
--- /dev/null
+++ b/test/junit/scala/concurrent/duration/SerializationTest.scala
@@ -0,0 +1,24 @@
+package scala.concurrent.duration
+
+import org.junit.runner.RunWith
+import org.junit.runners.JUnit4
+import org.junit.Test
+
+
+@RunWith(classOf[JUnit4])
+class SerializationTest {
+ @Test
+ def test_SI9197 {
+ def ser(a: AnyRef): Array[Byte] = {
+ val bais = new java.io.ByteArrayOutputStream
+ (new java.io.ObjectOutputStream(bais)).writeObject(a)
+ bais.toByteArray
+ }
+ def des(ab: Array[Byte]): AnyRef =
+ (new java.io.ObjectInputStream(new java.io.ByteArrayInputStream(ab))).readObject
+
+ assert(Duration.Undefined eq des(ser(Duration.Undefined)))
+ assert(Duration.Inf eq des(ser(Duration.Inf)))
+ assert(Duration.MinusInf eq des(ser(Duration.MinusInf)))
+ }
+}
diff --git a/test/junit/scala/tools/nsc/backend/jvm/CodeGenTools.scala b/test/junit/scala/tools/nsc/backend/jvm/CodeGenTools.scala
index 5d5215d887..d0ffd06b01 100644
--- a/test/junit/scala/tools/nsc/backend/jvm/CodeGenTools.scala
+++ b/test/junit/scala/tools/nsc/backend/jvm/CodeGenTools.scala
@@ -8,7 +8,6 @@ import scala.reflect.io.VirtualDirectory
import scala.tools.asm.Opcodes
import scala.tools.asm.tree.{ClassNode, MethodNode}
import scala.tools.cmd.CommandLineParser
-import scala.tools.nsc.backend.jvm.opt.LocalOpt
import scala.tools.nsc.io.AbstractFile
import scala.tools.nsc.reporters.StoreReporter
import scala.tools.nsc.settings.MutableSettings
@@ -157,12 +156,6 @@ object CodeGenTools {
assertTrue(h.start == insVec(startIndex) && h.end == insVec(endIndex) && h.handler == insVec(handlerIndex))
}
- val localOpt = {
- val settings = new MutableSettings(msg => throw new IllegalArgumentException(msg))
- settings.processArguments(List("-Yopt:l:method"), processAll = true)
- new LocalOpt(settings)
- }
-
import scala.language.implicitConversions
implicit def aliveInstruction(ins: Instruction): (Instruction, Boolean) = (ins, true)
diff --git a/test/junit/scala/tools/nsc/backend/jvm/opt/EmptyExceptionHandlersTest.scala b/test/junit/scala/tools/nsc/backend/jvm/opt/EmptyExceptionHandlersTest.scala
index 7b0504fec0..cb01f3d164 100644
--- a/test/junit/scala/tools/nsc/backend/jvm/opt/EmptyExceptionHandlersTest.scala
+++ b/test/junit/scala/tools/nsc/backend/jvm/opt/EmptyExceptionHandlersTest.scala
@@ -40,7 +40,7 @@ class EmptyExceptionHandlersTest extends ClearAfterClass {
Op(RETURN)
)
assertTrue(convertMethod(asmMethod).handlers.length == 1)
- localOpt.removeEmptyExceptionHandlers(asmMethod)
+ LocalOptImpls.removeEmptyExceptionHandlers(asmMethod)
assertTrue(convertMethod(asmMethod).handlers.isEmpty)
}
@@ -61,7 +61,7 @@ class EmptyExceptionHandlersTest extends ClearAfterClass {
Op(RETURN)
)
assertTrue(convertMethod(asmMethod).handlers.length == 1)
- localOpt.removeEmptyExceptionHandlers(asmMethod)
+ LocalOptImpls.removeEmptyExceptionHandlers(asmMethod)
assertTrue(convertMethod(asmMethod).handlers.isEmpty)
}
diff --git a/test/junit/scala/tools/nsc/backend/jvm/opt/EmptyLabelsAndLineNumbersTest.scala b/test/junit/scala/tools/nsc/backend/jvm/opt/EmptyLabelsAndLineNumbersTest.scala
index 8c0168826e..7283e20745 100644
--- a/test/junit/scala/tools/nsc/backend/jvm/opt/EmptyLabelsAndLineNumbersTest.scala
+++ b/test/junit/scala/tools/nsc/backend/jvm/opt/EmptyLabelsAndLineNumbersTest.scala
@@ -42,14 +42,14 @@ class EmptyLabelsAndLineNumbersTest {
)
val method = genMethod()(ops.map(_._1): _*)
- assertTrue(localOpt.removeEmptyLineNumbers(method))
+ assertTrue(LocalOptImpls.removeEmptyLineNumbers(method))
assertSameCode(instructionsFromMethod(method), ops.filter(_._2).map(_._1))
}
@Test
def badlyLocatedLineNumbers(): Unit = {
def t(ops: Instruction*) =
- assertThrows[AssertionError](localOpt.removeEmptyLineNumbers(genMethod()(ops: _*)))
+ assertThrows[AssertionError](LocalOptImpls.removeEmptyLineNumbers(genMethod()(ops: _*)))
// line numbers have to be right after their referenced label node
t(LineNumber(0, Label(1)), Label(1))
@@ -88,7 +88,7 @@ class EmptyLabelsAndLineNumbersTest {
)
val method = genMethod(handlers = handler)(ops(2, 3, 8, 8, 9, 11).map(_._1): _*)
- assertTrue(localOpt.removeEmptyLabelNodes(method))
+ assertTrue(LocalOptImpls.removeEmptyLabelNodes(method))
val m = convertMethod(method)
assertSameCode(m.instructions, ops(1, 1, 7, 7, 7, 10).filter(_._2).map(_._1))
assertTrue(m.handlers match {
diff --git a/test/junit/scala/tools/nsc/backend/jvm/opt/InlineWarningTest.scala b/test/junit/scala/tools/nsc/backend/jvm/opt/InlineWarningTest.scala
index fedc074a15..029caa995c 100644
--- a/test/junit/scala/tools/nsc/backend/jvm/opt/InlineWarningTest.scala
+++ b/test/junit/scala/tools/nsc/backend/jvm/opt/InlineWarningTest.scala
@@ -143,4 +143,52 @@ class InlineWarningTest extends ClearAfterClass {
compileClasses(newCompiler(extraArgs = InlineWarningTest.argsNoWarn + " -Yopt-warnings:no-inline-mixed"))(scalaCode, List((javaCode, "A.java")), allowMessage = i => {c += 1; warns.exists(i.msg contains _)})
assert(c == 2, c)
}
+
+ @Test
+ def cannotInlinePrivateCallIntoDifferentClass(): Unit = {
+ val code =
+ """class M {
+ | @inline final def f = {
+ | @noinline def nested = 0
+ | nested
+ | }
+ |
+ | def t = f // ok
+ |}
+ |
+ |class N {
+ | def t(a: M) = a.f // not possible
+ |}
+ """.stripMargin
+
+ val warn =
+ """M::f()I is annotated @inline but could not be inlined:
+ |The callee M::f()I contains the instruction INVOKESPECIAL M.nested$1 ()I
+ |that would cause an IllegalAccessError when inlined into class N""".stripMargin
+
+ var c = 0
+ compile(code, allowMessage = i => { c += 1; i.msg contains warn })
+ assert(c == 1, c)
+ }
+
+ @Test
+ def cannotMixStrictfp(): Unit = {
+ val code =
+ """import annotation.strictfp
+ |class C {
+ | @strictfp @inline final def f = 0
+ | @strictfp def t1 = f
+ | def t2 = f
+ |}
+ """.stripMargin
+
+ val warn =
+ """C::f()I is annotated @inline but could not be inlined:
+ |The callsite method C::t2()I
+ |does not have the same strictfp mode as the callee C::f()I.""".stripMargin
+
+ var c = 0
+ compile(code, allowMessage = i => { c += 1; i.msg contains warn })
+ assert(c == 1, c)
+ }
}
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 39fb28570e..0fc3601603 100644
--- a/test/junit/scala/tools/nsc/backend/jvm/opt/InlinerTest.scala
+++ b/test/junit/scala/tools/nsc/backend/jvm/opt/InlinerTest.scala
@@ -152,7 +152,7 @@ class InlinerTest extends ClearAfterClass {
assertSameCode(convertMethod(g).instructions.dropNonOp.take(4), expectedInlined)
- localOpt.methodOptimizations(g, "C")
+ compiler.genBCode.bTypes.localOpt.methodOptimizations(g, "C")
assertSameCode(convertMethod(g).instructions.dropNonOp,
expectedInlined ++ List(VarOp(ASTORE, 2), VarOp(ALOAD, 2), Op(ATHROW)))
}
@@ -720,7 +720,7 @@ class InlinerTest extends ClearAfterClass {
|final class D extends C
|object E extends C
|class T {
- | def t1(d: D) = d.f + d.g + E.f + E.g // d.f can be inlined because the reciever type is D, which is final.
+ | def t1(d: D) = d.f + d.g + E.f + E.g // d.f can be inlined because the receiver type is D, which is final.
|} // so d.f can be resolved statically. same for E.f
""".stripMargin
val List(c, d, e, eModule, t) = compile(code)
@@ -950,4 +950,29 @@ class InlinerTest extends ClearAfterClass {
assertInvoke(getSingleMethod(t, "t3"), "B", "<init>")
assertInvoke(getSingleMethod(t, "t4"), "B", "<init>")
}
+
+ @Test
+ def dontInlineNative(): Unit = {
+ val code =
+ """class C {
+ | def t = System.arraycopy(null, 0, null, 0, 0)
+ |}
+ """.stripMargin
+ val List(c) = compileClasses(newCompiler(extraArgs = InlinerTest.args + " -Yopt-inline-heuristics:everything"))(code)
+ assertInvoke(getSingleMethod(c, "t"), "java/lang/System", "arraycopy")
+ }
+
+ @Test
+ def inlineMayRenderCodeDead(): Unit = {
+ val code =
+ """class C {
+ | @inline final def f: String = throw new Error("")
+ | @inline final def g: String = "a" + f + "b" // after inlining f, need to run DCE, because the rest of g becomes dead.
+ | def t = g // the inliner requires no dead code when inlining g (uses an Analyzer).
+ |}
+ """.stripMargin
+
+ val List(c) = compile(code)
+ assertInvoke(getSingleMethod(c, "t"), "java/lang/Error", "<init>")
+ }
}
diff --git a/test/junit/scala/tools/nsc/backend/jvm/opt/SimplifyJumpsTest.scala b/test/junit/scala/tools/nsc/backend/jvm/opt/SimplifyJumpsTest.scala
index 360fa1d23d..a685ae7dd5 100644
--- a/test/junit/scala/tools/nsc/backend/jvm/opt/SimplifyJumpsTest.scala
+++ b/test/junit/scala/tools/nsc/backend/jvm/opt/SimplifyJumpsTest.scala
@@ -26,7 +26,7 @@ class SimplifyJumpsTest {
Op(RETURN)
)
val method = genMethod()(ops: _*)
- assertTrue(localOpt.simplifyJumps(method))
+ assertTrue(LocalOptImpls.simplifyJumps(method))
assertSameCode(instructionsFromMethod(method), Op(RETURN) :: ops.tail)
}
@@ -45,7 +45,7 @@ class SimplifyJumpsTest {
Jump(GOTO, Label(2)) :: // replaced by ATHROW
rest: _*
)
- assertTrue(localOpt.simplifyJumps(method))
+ assertTrue(LocalOptImpls.simplifyJumps(method))
assertSameCode(instructionsFromMethod(method), Op(ACONST_NULL) :: Op(ATHROW) :: rest)
}
@@ -66,11 +66,11 @@ class SimplifyJumpsTest {
Op(RETURN)
)
val method = genMethod(handlers = handler)(initialInstrs: _*)
- assertFalse(localOpt.simplifyJumps(method))
+ assertFalse(LocalOptImpls.simplifyJumps(method))
assertSameCode(instructionsFromMethod(method), initialInstrs)
val optMethod = genMethod()(initialInstrs: _*) // no handler
- assertTrue(localOpt.simplifyJumps(optMethod))
+ assertTrue(LocalOptImpls.simplifyJumps(optMethod))
assertSameCode(instructionsFromMethod(optMethod).take(3), List(Label(1), Op(ACONST_NULL), Op(ATHROW)))
}
@@ -91,7 +91,7 @@ class SimplifyJumpsTest {
Op(IRETURN)
)
val method = genMethod()(begin ::: rest: _*)
- assertTrue(localOpt.simplifyJumps(method))
+ assertTrue(LocalOptImpls.simplifyJumps(method))
assertSameCode(
instructionsFromMethod(method),
List(VarOp(ILOAD, 1), Jump(IFLT, Label(3))) ::: rest.tail )
@@ -99,7 +99,7 @@ class SimplifyJumpsTest {
// no label allowed between begin and rest. if there's another label, then there could be a
// branch that label. eliminating the GOTO would change the behavior.
val nonOptMethod = genMethod()(begin ::: Label(22) :: rest: _*)
- assertFalse(localOpt.simplifyJumps(nonOptMethod))
+ assertFalse(LocalOptImpls.simplifyJumps(nonOptMethod))
}
@Test
@@ -116,7 +116,7 @@ class SimplifyJumpsTest {
// ensures that the goto is safely removed. ASM supports removing while iterating, but not the
// next element of the current. Here, the current is the IFGE, the next is the GOTO.
val method = genMethod()(code(Jump(IFGE, Label(2)), Jump(GOTO, Label(3))): _*)
- assertTrue(localOpt.simplifyJumps(method))
+ assertTrue(LocalOptImpls.simplifyJumps(method))
assertSameCode(instructionsFromMethod(method), code(Jump(IFLT, Label(3))))
}
@@ -131,7 +131,7 @@ class SimplifyJumpsTest {
Op(IRETURN)
)
val method = genMethod()(ops: _*)
- assertTrue(localOpt.simplifyJumps(method))
+ assertTrue(LocalOptImpls.simplifyJumps(method))
assertSameCode(instructionsFromMethod(method), ops.tail)
}
@@ -157,7 +157,7 @@ class SimplifyJumpsTest {
Op(IRETURN)
)
val method = genMethod()(ops(1, 2, 3): _*)
- assertTrue(localOpt.simplifyJumps(method))
+ assertTrue(LocalOptImpls.simplifyJumps(method))
assertSameCode(instructionsFromMethod(method), ops(3, 3, 3))
}
@@ -181,7 +181,7 @@ class SimplifyJumpsTest {
)
val method = genMethod()(ops(2): _*)
- assertTrue(localOpt.simplifyJumps(method))
+ assertTrue(LocalOptImpls.simplifyJumps(method))
assertSameCode(instructionsFromMethod(method), ops(3))
}
@@ -202,7 +202,7 @@ class SimplifyJumpsTest {
)
val method = genMethod()(ops(Jump(IFGE, Label(1))): _*)
- assertTrue(localOpt.simplifyJumps(method))
+ assertTrue(LocalOptImpls.simplifyJumps(method))
assertSameCode(instructionsFromMethod(method), ops(Op(POP)))
}
@@ -215,7 +215,7 @@ class SimplifyJumpsTest {
Jump(GOTO, Label(1))
)
val method = genMethod()(ops(List(Jump(IF_ICMPGE, Label(1)))): _*)
- assertTrue(localOpt.simplifyJumps(method))
+ assertTrue(LocalOptImpls.simplifyJumps(method))
assertSameCode(instructionsFromMethod(method), ops(List(Op(POP), Op(POP))))
}
}
diff --git a/test/junit/scala/tools/nsc/backend/jvm/opt/UnreachableCodeTest.scala b/test/junit/scala/tools/nsc/backend/jvm/opt/UnreachableCodeTest.scala
index da9853148b..902af7b7fa 100644
--- a/test/junit/scala/tools/nsc/backend/jvm/opt/UnreachableCodeTest.scala
+++ b/test/junit/scala/tools/nsc/backend/jvm/opt/UnreachableCodeTest.scala
@@ -44,7 +44,7 @@ class UnreachableCodeTest extends ClearAfterClass {
def assertEliminateDead(code: (Instruction, Boolean)*): Unit = {
val method = genMethod()(code.map(_._1): _*)
- localOpt.removeUnreachableCodeImpl(method, "C")
+ LocalOptImpls.removeUnreachableCodeImpl(method, "C")
val nonEliminated = instructionsFromMethod(method)
val expectedLive = code.filter(_._2).map(_._1).toList
assertSameCode(nonEliminated, expectedLive)
diff --git a/test/junit/scala/tools/nsc/interpreter/TabulatorTest.scala b/test/junit/scala/tools/nsc/interpreter/TabulatorTest.scala
index 21e338eac0..263265026a 100644
--- a/test/junit/scala/tools/nsc/interpreter/TabulatorTest.scala
+++ b/test/junit/scala/tools/nsc/interpreter/TabulatorTest.scala
@@ -82,4 +82,24 @@ class TabulatorTest {
assert(rows(0).size == 1)
assert(rows(0)(0).size == "efg".length + sut.marginSize) // 6
}
+ @Test def badFit() = {
+ val sut = VTabby(isAcross = true)
+ val items = ('a' until 'z').map(_.toString).toList
+ val rows = sut tabulate items
+ assert(rows.size == 2)
+ assert(rows(0).size == 20) // 20 * 4 = 80
+ assert(rows(1)(0).dropRight(sut.marginSize) == "u")
+ }
+ @Test def badFitter() = {
+ val sut = VTabby(isAcross = true)
+ val items = List (
+ "%", "&", "*", "+", "-", "/", ">", ">=", ">>", ">>>", "^",
+ "asInstanceOf", "isInstanceOf", "toByte", "toChar", "toDouble", "toFloat",
+ "toInt", "toLong", "toShort", "toString", "unary_+", "unary_-", "unary_~", "|"
+ )
+ val rows = sut tabulate items
+ assert(rows.size == 4)
+ assert(rows(3).size == 4) // 7 cols
+ assert(rows(3)(0).dropRight(sut.marginSize) == "unary_+")
+ }
}
diff --git a/test/junit/scala/tools/nsc/transform/patmat/SolvingTest.scala b/test/junit/scala/tools/nsc/transform/patmat/SolvingTest.scala
index 1fff9c9a32..7bcb90a2ee 100644
--- a/test/junit/scala/tools/nsc/transform/patmat/SolvingTest.scala
+++ b/test/junit/scala/tools/nsc/transform/patmat/SolvingTest.scala
@@ -6,6 +6,7 @@ import org.junit.runner.RunWith
import org.junit.runners.JUnit4
import scala.collection.mutable
+import scala.reflect.internal.util.Position
import scala.tools.nsc.{Global, Settings}
object TestSolver extends Logic with Solving {
@@ -51,6 +52,8 @@ object TestSolver extends Logic with Solving {
def domainSyms = None
+ def groupedDomains: List[Set[TestSolver.Sym]] = Nil
+
def implications = Nil
def mayBeNull = false
@@ -72,6 +75,8 @@ object TestSolver extends Logic with Solving {
def prepareNewAnalysis() = {}
+ def uncheckedWarning(pos: Position, msg: String) = sys.error(msg)
+
def reportWarning(msg: String) = sys.error(msg)
/**
@@ -204,11 +209,44 @@ class SolvingTest {
import scala.tools.nsc.transform.patmat.TestSolver.TestSolver._
- implicit val Ord: Ordering[TestSolver.TestSolver.Model] = Ordering.by {
- _.toSeq.sortBy(_.toString()).toIterable
+ object SymName {
+ def unapply(s: Sym): Option[String] = {
+ val Var(Tree(name)) = s.variable
+ Some(name)
+ }
+ }
+
+ implicit val ModelOrd: Ordering[TestSolver.TestSolver.Model] = Ordering.by {
+ _.toSeq.sortWith {
+ case ((sym1, v1), (sym2, v2)) =>
+ val SymName(name1) = sym1
+ val SymName(name2) = sym2
+ if (name1 < name2)
+ true
+ else if (name1 > name2)
+ false
+ else
+ v1 < v2
+ }.toIterable
}
- private def sym(name: String) = Sym(Var(Tree(name)), NullConst)
+ implicit val SolutionOrd: Ordering[TestSolver.TestSolver.Solution] =
+ Ordering.by(_.model)
+
+ def formatSolution(solution: Solution): String = {
+ formatModel(solution.model)
+ }
+
+ def formatModel(model: Model): String = {
+ (for {
+ (SymName(name), value) <- model
+ } yield {
+ val v = if (value) "T" else "F"
+ s"$name -> $v"
+ }).mkString(", ")
+ }
+
+ def sym(name: String) = Sym(Var(Tree(name)), NullConst)
@Test
def testSymCreation() {
@@ -550,6 +588,23 @@ class SolvingTest {
assertEquals(tseitinNoUnassigned, expansionNoUnassigned)
}
}
+
+ def pairWiseEncoding(ops: List[Sym]) = {
+ And(ops.combinations(2).collect {
+ case a :: b :: Nil => Or(Not(a), Not(b))
+ }.toSet[TestSolver.TestSolver.Prop])
+ }
+
+ @Test
+ def testAtMostOne() {
+ val dummySym = sym("dummy")
+ val syms = "pqrstu".map(c => sym(c.toString)).toList
+ // expand unassigned variables
+ // (otherwise solutions can not be compared)
+ val expected = TestSolver.TestSolver.findAllModelsFor(propToSolvable(And(dummySym, pairWiseEncoding(syms)))).flatMap(expandUnassigned)
+ val actual = TestSolver.TestSolver.findAllModelsFor(propToSolvable(And(dummySym, AtMostOne(syms)))).flatMap(expandUnassigned)
+ assertEquals(expected.toSet, actual.toSet)
+ }
}
diff --git a/test/pending/jvm/javasigs.scala b/test/pending/jvm/javasigs.scala
index 8da59ab0a0..d18a4e6fb5 100644
--- a/test/pending/jvm/javasigs.scala
+++ b/test/pending/jvm/javasigs.scala
@@ -32,7 +32,7 @@ object Scalatest {
}
- /** Execute cmd, wait for the process to end and pipe it's output to stdout */
+ /** Execute cmd, wait for the process to end and pipe its output to stdout */
def exec(cmd: String) {
val proc = Runtime.getRuntime().exec(cmd)
val inp = new BufferedReader(new InputStreamReader(proc.getInputStream))
diff --git a/test/pending/run/delambdafy-lambdametafactory.scala b/test/pending/run/delambdafy-lambdametafactory.scala
new file mode 100644
index 0000000000..daea8a39fe
--- /dev/null
+++ b/test/pending/run/delambdafy-lambdametafactory.scala
@@ -0,0 +1,50 @@
+//
+// Tests that the static accessor method for lambda bodies
+// (generated under -Ydelambdafy:method) are compatible with
+// Java 8's LambdaMetafactory.
+//
+import java.lang.invoke._
+
+class C {
+ def test1: Unit = {
+ (x: String) => x.reverse
+ }
+ def test2: Unit = {
+ val capture1 = "capture1"
+ (x: String) => capture1 + " " + x.reverse
+ }
+ def test3: Unit = {
+ (x: String) => C.this + " " + x.reverse
+ }
+}
+trait T {
+ def test4: Unit = {
+ (x: String) => x.reverse
+ }
+}
+
+// A functional interface. Function1 contains abstract methods that are filled in by mixin
+trait Function1ish[A, B] {
+ def apply(a: A): B
+}
+
+object Test {
+ def lambdaFactory[A, B](hostClass: Class[_], instantiatedParam: Class[A], instantiatedRet: Class[B], accessorName: String,
+ capturedParams: Array[(Class[_], AnyRef)] = Array()) = {
+ val caller = MethodHandles.lookup
+ val methodType = MethodType.methodType(classOf[AnyRef], Array[Class[_]](classOf[AnyRef]))
+ val instantiatedMethodType = MethodType.methodType(instantiatedRet, Array[Class[_]](instantiatedParam))
+ val (capturedParamTypes, captured) = capturedParams.unzip
+ val targetMethodType = MethodType.methodType(instantiatedRet, capturedParamTypes :+ instantiatedParam)
+ val invokedType = MethodType.methodType(classOf[Function1ish[_, _]], capturedParamTypes)
+ val target = caller.findStatic(hostClass, accessorName, targetMethodType)
+ val site = LambdaMetafactory.metafactory(caller, "apply", invokedType, methodType, target, instantiatedMethodType)
+ site.getTarget.invokeWithArguments(captured: _*).asInstanceOf[Function1ish[A, B]]
+ }
+ def main(args: Array[String]) {
+ println(lambdaFactory(classOf[C], classOf[String], classOf[String], "accessor$1").apply("abc"))
+ println(lambdaFactory(classOf[C], classOf[String], classOf[String], "accessor$2", Array(classOf[String] -> "capture1")).apply("abc"))
+ println(lambdaFactory(classOf[C], classOf[String], classOf[String], "accessor$3", Array(classOf[C] -> new C)).apply("abc"))
+ println(lambdaFactory(Class.forName("T$class"), classOf[String], classOf[String], "accessor$4", Array(classOf[T] -> new T{})).apply("abc"))
+ }
+}
diff --git a/test/scaladoc/resources/SI-4476.scala b/test/scaladoc/resources/SI-4476.scala
new file mode 100644
index 0000000000..eb35ef45e7
--- /dev/null
+++ b/test/scaladoc/resources/SI-4476.scala
@@ -0,0 +1,9 @@
+package foo
+
+@deprecated("","")
+class A
+
+class B {
+ @deprecated("","")
+ def bar = 1
+}
diff --git a/test/scaladoc/resources/Trac4420.scala b/test/scaladoc/resources/Trac4420.scala
index dbe053f3da..d8e207876b 100644
--- a/test/scaladoc/resources/Trac4420.scala
+++ b/test/scaladoc/resources/Trac4420.scala
@@ -1,7 +1,7 @@
import java.io.File
/**
- * @define PP This class is an instance of XXX so it's members are not called directly.
+ * @define PP This class is an instance of XXX so its members are not called directly.
* Instead these classes are instantiated via a driver's ''process''. See YYY for more details. */
abstract class test
diff --git a/test/scaladoc/run/t5795.check b/test/scaladoc/run/t5795.check
new file mode 100644
index 0000000000..d08ab619ed
--- /dev/null
+++ b/test/scaladoc/run/t5795.check
@@ -0,0 +1,4 @@
+newSource:16: warning: Could not find any member to link for "Exception".
+ /**
+ ^
+Done.
diff --git a/test/scaladoc/run/t5795.scala b/test/scaladoc/run/t5795.scala
new file mode 100644
index 0000000000..767e4f1a72
--- /dev/null
+++ b/test/scaladoc/run/t5795.scala
@@ -0,0 +1,63 @@
+import scala.tools.nsc.doc.model._
+import scala.tools.partest.ScaladocModelTest
+
+object Test extends ScaladocModelTest {
+
+ override def code = """
+/**
+ * Only the 'deprecated' tag should stay.
+ *
+ * @author
+ * @since
+ * @todo
+ * @note
+ * @see
+ * @version
+ * @deprecated
+ * @example
+ * @constructor
+ */
+object Test {
+ /**
+ * Only the 'throws' tag should stay.
+ * @param foo
+ * @param bar
+ * @param baz
+ * @return
+ * @throws Exception
+ * @tparam T
+ */
+ def foo[T](foo: Any, bar: Any, baz: Any): Int = 1
+}
+ """
+
+ def scaladocSettings = ""
+
+ def test(b: Boolean, text: => String): Unit = if (!b) println(text)
+
+ def testModel(root: Package) = {
+ import access._
+ val obj = root._object("Test")
+ val c = obj.comment.get
+
+ test(c.authors.isEmpty, s"expected no authors, found: ${c.authors}")
+ test(!c.since.isDefined, s"expected no since tag, found: ${c.since}")
+ test(c.todo.isEmpty, s"expected no todos, found: ${c.todo}")
+ test(c.note.isEmpty, s"expected no note, found: ${c.note}")
+ test(c.see.isEmpty, s"expected no see, found: ${c.see}")
+ test(!c.version.isDefined, s"expected no version tag, found: ${c.version}")
+ // deprecated stays
+ test(c.deprecated.isDefined, s"expected deprecated tag, found none")
+ test(c.example.isEmpty, s"expected no example, found: ${c.example}")
+ test(!c.constructor.isDefined, s"expected no constructor tag, found: ${c.constructor}")
+
+ val method = obj._method("foo")
+ val mc = method.comment.get
+
+ test(mc.valueParams.isEmpty, s"expected empty value params, found: ${mc.valueParams}")
+ test(mc.typeParams.isEmpty, s"expected empty type params, found: ${mc.typeParams}")
+ test(!mc.result.isDefined, s"expected no result tag, found: ${mc.result}")
+ // throws stay
+ test(!mc.throws.isEmpty, s"expected an exception tag, found: ${mc.throws}")
+ }
+}
diff --git a/test/scaladoc/scalacheck/CommentFactoryTest.scala b/test/scaladoc/scalacheck/CommentFactoryTest.scala
index ff64a25602..d30b78087c 100644
--- a/test/scaladoc/scalacheck/CommentFactoryTest.scala
+++ b/test/scaladoc/scalacheck/CommentFactoryTest.scala
@@ -24,8 +24,11 @@ class Factory(val g: Global, val s: doc.Settings)
}
}
+ def getComment(s: String): Comment =
+ parse(s, "", scala.tools.nsc.util.NoPosition, null)
+
def parseComment(s: String): Option[Inline] =
- strip(parse(s, "", scala.tools.nsc.util.NoPosition, null))
+ strip(getComment(s))
def createBody(s: String) =
parse(s, "", scala.tools.nsc.util.NoPosition, null).body
@@ -166,4 +169,19 @@ object Test extends Properties("CommentFactory") {
}
}
+ property("Empty parameter text should be empty") = {
+ // used to fail with
+ // body == Body(List(Paragraph(Chain(List(Summary(Text('\n')))))))
+ factory.getComment(
+ """
+/**
+ * @deprecated
+ */
+ """).deprecated match {
+ case Some(Body(l)) if l.isEmpty => true
+ case other =>
+ println(other)
+ false
+ }
+ }
}
diff --git a/test/scaladoc/scalacheck/DeprecatedIndexTest.scala b/test/scaladoc/scalacheck/DeprecatedIndexTest.scala
new file mode 100644
index 0000000000..4a5a2001d4
--- /dev/null
+++ b/test/scaladoc/scalacheck/DeprecatedIndexTest.scala
@@ -0,0 +1,50 @@
+import org.scalacheck._
+import org.scalacheck.Prop._
+
+import scala.tools.nsc.doc
+import scala.tools.nsc.doc.html.page.DeprecatedIndex
+import java.net.{URLClassLoader, URLDecoder}
+
+object Test extends Properties("IndexScript") {
+
+ def getClasspath = {
+ // these things can be tricky
+ // this test previously relied on the assumption that the current thread's classloader is an url classloader and contains all the classpaths
+ // does partest actually guarantee this? to quote Leonard Nimoy: The answer, of course, is no.
+ // this test _will_ fail again some time in the future.
+ // Footnote: java.lang.ClassCastException: org.apache.tools.ant.loader.AntClassLoader5 cannot be cast to java.net.URLClassLoader
+ val loader = Thread.currentThread.getContextClassLoader.asInstanceOf[URLClassLoader]
+ val paths = loader.getURLs.map(u => URLDecoder.decode(u.getPath))
+ paths mkString java.io.File.pathSeparator
+ }
+
+ val docFactory = {
+ val settings = new doc.Settings({Console.err.println(_)})
+ settings.scaladocQuietRun = true
+ settings.nowarn.value = true
+ settings.classpath.value = getClasspath
+ val reporter = new scala.tools.nsc.reporters.ConsoleReporter(settings)
+ new doc.DocFactory(reporter, settings)
+ }
+
+ val indexModelFactory = doc.model.IndexModelFactory
+
+ def createDeprecatedScript(path: String) =
+ docFactory.makeUniverse(Left(List(path))) match {
+ case Some(universe) => {
+ val index = new DeprecatedIndex(universe, indexModelFactory.makeIndex(universe))
+ Some(index)
+ }
+ case _ =>
+ None
+ }
+
+ property("deprecated-list page lists deprecated members") = {
+ createDeprecatedScript("test/scaladoc/resources/SI-4476.scala") match {
+ case Some(p) =>
+ p.deprecatedEntries.find(_._1 == "A").isDefined &&
+ p.deprecatedEntries.find(_._1 == "bar").isDefined
+ case None => false
+ }
+ }
+}
diff --git a/test/scaladoc/scalacheck/HtmlFactoryTest.scala b/test/scaladoc/scalacheck/HtmlFactoryTest.scala
index 51633be440..6a6b1f8901 100644
--- a/test/scaladoc/scalacheck/HtmlFactoryTest.scala
+++ b/test/scaladoc/scalacheck/HtmlFactoryTest.scala
@@ -685,7 +685,7 @@ object Test extends Properties("HtmlFactory") {
case node: scala.xml.Node => {
val s = node.toString
s.contains("<h6>Author:</h6>") &&
- s.contains("<p>The Only Author\n</p>")
+ s.contains("<p>The Only Author</p>")
}
case _ => false
}
@@ -699,7 +699,7 @@ object Test extends Properties("HtmlFactory") {
val s = node.toString
s.contains("<h6>Authors:</h6>") &&
s.contains("<p>The First Author</p>") &&
- s.contains("<p>The Second Author\n</p>")
+ s.contains("<p>The Second Author</p>")
}
case _ => false
}
diff --git a/test/scaladoc/scalacheck/IndexTest.scala b/test/scaladoc/scalacheck/IndexTest.scala
index abc0e5da01..7dbd2103a6 100644
--- a/test/scaladoc/scalacheck/IndexTest.scala
+++ b/test/scaladoc/scalacheck/IndexTest.scala
@@ -71,7 +71,7 @@ object Test extends Properties("Index") {
case None => false
}
}
- property("browser contants a script element") = {
+ property("browser contains a script element") = {
createIndex("src/scaladoc/scala/tools/nsc/doc/html/page/Index.scala") match {
case Some(index) =>
(index.browser \ "script").size == 1
@@ -86,4 +86,10 @@ object Test extends Properties("Index") {
case None => false
}
}
+ property("index should report if there are deprecated members") = {
+ createIndex("test/scaladoc/resources/SI-4476.scala") match {
+ case Some(indexPage) => indexPage.index.hasDeprecatedMembers
+ case None => false
+ }
+ }
}
diff --git a/tools/scaladoc-compare b/tools/scaladoc-compare
index 74fbfd1dd4..46e1b75a19 100755
--- a/tools/scaladoc-compare
+++ b/tools/scaladoc-compare
@@ -7,7 +7,7 @@ if [ $# -ne 2 ]
then
echo
echo "scaladoc-compare will compare the scaladoc-generated pages in two different locations and output the diff"
- echo "it's main purpose is to track changes to scaladoc and prevent updates that break things."
+ echo "its main purpose is to track changes to scaladoc and prevent updates that break things."
echo
echo "This script is meant to be used with the scaladoc -raw-output option, as it compares .html.raw files "
echo "instead of markup-heavy .html files."
diff --git a/versions.properties b/versions.properties
index 096108a21f..2ecfd23800 100644
--- a/versions.properties
+++ b/versions.properties
@@ -27,7 +27,7 @@ actors-migration.version.number=1.1.0
jline.version=2.12.1
# external modules, used internally (not shipped)
-partest.version.number=1.0.5
+partest.version.number=1.0.6
scalacheck.version.number=1.11.4
# TODO: modularize the compiler