summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--build.xml672
-rw-r--r--src/compiler/scala/reflect/reify/utils/Extractors.scala65
-rw-r--r--src/compiler/scala/tools/nsc/backend/icode/Members.scala1
-rw-r--r--src/compiler/scala/tools/nsc/backend/icode/Opcodes.scala19
-rw-r--r--src/compiler/scala/tools/nsc/backend/jvm/GenASM.scala18
-rw-r--r--src/compiler/scala/tools/nsc/backend/opt/Inliners.scala1
-rw-r--r--src/compiler/scala/tools/nsc/javac/JavaParsers.scala8
-rw-r--r--src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala7
-rw-r--r--src/compiler/scala/tools/nsc/symtab/classfile/ICodeReader.scala9
-rw-r--r--src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala64
-rw-r--r--src/compiler/scala/tools/nsc/transform/UnCurry.scala6
-rw-r--r--src/compiler/scala/tools/nsc/transform/patmat/Logic.scala1
-rw-r--r--src/compiler/scala/tools/nsc/transform/patmat/MatchOptimization.scala18
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/NamesDefaults.scala2
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Typers.scala15
-rw-r--r--src/compiler/scala/tools/nsc/util/SimpleTracer.scala2
-rw-r--r--src/library/scala/collection/parallel/package.scala7
-rw-r--r--src/partest/scala/tools/partest/nest/Diff.java873
-rw-r--r--src/partest/scala/tools/partest/nest/DiffPrint.java606
-rw-r--r--src/partest/scala/tools/partest/nest/FileManager.scala41
-rw-r--r--src/partest/scala/tools/partest/nest/PathSettings.scala3
-rw-r--r--src/partest/scala/tools/partest/nest/ReflectiveRunner.scala7
-rw-r--r--src/partest/scala/tools/partest/nest/RunnerManager.scala1
-rw-r--r--src/reflect/scala/reflect/internal/ClassfileConstants.scala5
-rw-r--r--src/reflect/scala/reflect/internal/Symbols.scala34
-rw-r--r--src/reflect/scala/reflect/internal/Types.scala7
-rw-r--r--src/reflect/scala/reflect/internal/util/Collections.scala13
-rw-r--r--src/reflect/scala/reflect/runtime/JavaUniverse.scala2
-rwxr-xr-xsrc/scaladoc/scala/tools/nsc/doc/base/comment/Body.scala18
-rw-r--r--src/scaladoc/scala/tools/nsc/doc/html/SyntaxHigh.scala6
-rw-r--r--starr.number1
-rw-r--r--test/files/jvm/t7253.check1
-rw-r--r--test/files/jvm/t7253/Base_1.scala5
-rw-r--r--test/files/jvm/t7253/JavaClient_1.java9
-rw-r--r--test/files/jvm/t7253/ScalaClient_1.scala9
-rw-r--r--test/files/jvm/t7253/test.scala28
-rw-r--r--test/files/neg/t7285.check15
-rw-r--r--test/files/neg/t7285.flags1
-rw-r--r--test/files/neg/t7285.scala55
-rw-r--r--test/files/neg/t7290.check12
-rw-r--r--test/files/neg/t7290.flags1
-rw-r--r--test/files/neg/t7290.scala10
-rw-r--r--test/files/neg/t7299.check7
-rw-r--r--test/files/neg/t7299.scala6
-rw-r--r--test/files/pos/t6210.flags1
-rw-r--r--test/files/pos/t6210.scala21
-rw-r--r--test/files/pos/t6921.scala11
-rw-r--r--test/files/pos/t7239.scala38
-rw-r--r--test/files/pos/t7285a.flags1
-rw-r--r--test/files/pos/t7285a.scala83
-rw-r--r--test/files/run/classfile-format-51.scala126
-rw-r--r--test/files/run/inline-ex-handlers.check919
-rw-r--r--test/files/run/outertest.scala47
-rw-r--r--test/files/run/t3994.scala20
-rwxr-xr-xtest/files/run/t5699.check11
-rwxr-xr-xtest/files/run/t5699.scala24
-rw-r--r--test/files/run/t6146b.check11
-rw-r--r--test/files/run/t6146b.scala3
-rw-r--r--test/files/run/t6223.scala4
-rw-r--r--test/files/run/t6387.check1
-rw-r--r--test/files/run/t6387.scala16
-rw-r--r--test/files/run/t7242.scala71
-rwxr-xr-xtest/files/run/t7246.check1
-rwxr-xr-xtest/files/run/t7246/Outer.java4
-rwxr-xr-xtest/files/run/t7246/Test.scala16
-rwxr-xr-xtest/files/run/t7246b.check2
-rwxr-xr-xtest/files/run/t7246b/Base.scala7
-rwxr-xr-xtest/files/run/t7246b/Outer.java4
-rwxr-xr-xtest/files/run/t7246b/Test.scala14
-rw-r--r--test/files/run/t7249.check1
-rw-r--r--test/files/run/t7249.scala7
-rw-r--r--test/files/run/t7290.scala9
-rw-r--r--test/files/run/test-cpp.check146
-rwxr-xr-xtest/partest4
-rw-r--r--test/scaladoc/run/SI-6580.check11
-rw-r--r--test/scaladoc/run/SI-6580.scala32
76 files changed, 1862 insertions, 2495 deletions
diff --git a/build.xml b/build.xml
index 9c98c34b32..3fe890c2fd 100644
--- a/build.xml
+++ b/build.xml
@@ -44,8 +44,8 @@ targets exercised:
<target name="distpack-maven" depends="dist.done, docs.done">
<ant antfile="${src.dir}/build/pack.xml" target="pack-maven.done" inheritall="yes" inheritrefs="yes"/></target>
- <target name="distpack-opt" description="Builds an optimised distribution."> <optimize name="distpack"/></target>
- <target name="distpack-maven-opt" description="Builds an optimised maven distribution."><optimize name="distpack-maven"/></target>
+ <target name="distpack-opt" description="Builds an optimised distribution."> <optimized name="distpack"/></target>
+ <target name="distpack-maven-opt" description="Builds an optimised maven distribution."><optimized name="distpack-maven"/></target>
<target name="all.done" depends="dist.done, test.done"/>
@@ -57,8 +57,8 @@ targets exercised:
<target name="nightly.checkall">
<antcall target="nightly-nopt"> <param name="partest.scalac_opts" value="-Ycheck:all"/></antcall></target>
- <target name="clean" depends="locker.clean" description="Removes binaries of compiler and library. Distributions are untouched."/>
- <target name="docsclean" depends="docs.clean" description="Removes generated documentation. Distributions are untouched."/>
+ <target name="clean" depends="quick.clean" description="Removes binaries of compiler and library. Locker and distributions are untouched."/>
+ <target name="docsclean" depends="docs.clean" description="Removes generated documentation. Distributions are untouched."/>
<target name="distclean" depends="dist.clean" description="Removes all distributions. Binaries and documentation are untouched."/>
<macrodef name="optimized" >
@@ -74,18 +74,18 @@ targets exercised:
<property environment="env"/>
<!-- Prevents system classpath from being used -->
- <property name="build.sysclasspath" value="ignore"/>
+ <property name="build.sysclasspath" value="ignore"/>
<!-- Defines the repository layout -->
- <property name="docs.dir" value="${basedir}/docs"/>
- <property name="lib.dir" value="${basedir}/lib"/>
- <property name="src.dir" value="${basedir}/src"/>
- <property name="partest.dir" value="${basedir}/test"/>
+ <property name="docs.dir" value="${basedir}/docs"/>
+ <property name="lib.dir" value="${basedir}/lib"/>
+ <property name="src.dir" value="${basedir}/src"/>
+ <property name="partest.dir" value="${basedir}/test"/>
- <property name="lib-ant.dir" value="${lib.dir}/ant"/>
+ <property name="lib-ant.dir" value="${lib.dir}/ant"/>
<!-- For developers: any jars placed in this dir will be added to the classpath
of all targets and copied into quick/pack/etc builds. -->
- <property name="lib-extra.dir" value="${lib.dir}/extra"/>
+ <property name="lib-extra.dir" value="${lib.dir}/extra"/>
<!-- Loads custom properties definitions -->
<property file="${basedir}/build.properties"/>
@@ -93,44 +93,45 @@ targets exercised:
<property file="${basedir}/build.number"/>
<!-- Sets location of pre-compiled libraries -->
- <property name="library.starr.jar" value="${lib.dir}/scala-library.jar"/>
- <property name="reflect.starr.jar" value="${lib.dir}/scala-reflect.jar"/>
- <property name="compiler.starr.jar" value="${lib.dir}/scala-compiler.jar"/>
- <property name="jline.jar" value="${lib.dir}/jline.jar"/>
- <property name="ant.jar" value="${ant.home}/lib/ant.jar"/>
- <property name="scalacheck.jar" value="${lib.dir}/scalacheck.jar"/>
+ <property name="library.starr.jar" value="${lib.dir}/scala-library.jar"/>
+ <property name="reflect.starr.jar" value="${lib.dir}/scala-reflect.jar"/>
+ <property name="compiler.starr.jar" value="${lib.dir}/scala-compiler.jar"/>
+ <property name="jline.jar" value="${lib.dir}/jline.jar"/>
+ <property name="ant.jar" value="${ant.home}/lib/ant.jar"/>
+ <property name="scalacheck.jar" value="${lib.dir}/scalacheck.jar"/>
<!-- Sets location of build folders -->
- <property name="build.dir" value="${basedir}/build"/>
- <property name="build-asm.dir" value="${build.dir}/asm"/>
- <property name="build-locker.dir" value="${build.dir}/locker"/>
- <property name="build-palo.dir" value="${build.dir}/palo"/>
- <property name="build-quick.dir" value="${build.dir}/quick"/>
- <property name="build-pack.dir" value="${build.dir}/pack"/>
- <property name="build-osgi.dir" value="${build.dir}/osgi"/>
- <property name="build-strap.dir" value="${build.dir}/strap"/>
- <property name="build-docs.dir" value="${build.dir}/scaladoc"/>
- <property name="build-libs.dir" value="${build.dir}/libs"/>
- <property name="build-sbt.dir" value="${build.dir}/sbt-interface"/>
-
- <property name="test.osgi.src" value="${partest.dir}/osgi/src"/>
- <property name="test.osgi.classes" value="${build-osgi.dir}/classes"/>
-
- <property name="dists.dir" value="${basedir}/dists"/>
-
- <property name="copyright.string" value="Copyright 2002-2013, LAMP/EPFL"/>
- <property name="partest.version.number" value="0.9.2"/>
+ <property name="build.dir" value="${basedir}/build"/>
+ <property name="build-libs.dir" value="${build.dir}/libs"/>
+ <property name="build-asm.dir" value="${build.dir}/asm"/>
+ <property name="build-forkjoin.dir" value="${build-libs.dir}"/>
+ <property name="build-locker.dir" value="${build.dir}/locker"/>
+ <property name="build-palo.dir" value="${build.dir}/palo"/>
+ <property name="build-quick.dir" value="${build.dir}/quick"/>
+ <property name="build-pack.dir" value="${build.dir}/pack"/>
+ <property name="build-osgi.dir" value="${build.dir}/osgi"/>
+ <property name="build-strap.dir" value="${build.dir}/strap"/>
+ <property name="build-docs.dir" value="${build.dir}/scaladoc"/>
+ <property name="build-sbt.dir" value="${build.dir}/sbt-interface"/>
+
+ <property name="test.osgi.src" value="${partest.dir}/osgi/src"/>
+ <property name="test.osgi.classes" value="${build-osgi.dir}/classes"/>
+
+ <property name="dists.dir" value="${basedir}/dists"/>
+
+ <property name="copyright.string" value="Copyright 2002-2013, LAMP/EPFL"/>
+ <property name="partest.version.number" value="0.9.2"/>
<!-- These are NOT the flags used to run SuperSabbus, but the ones written
into the script runners created with scala.tools.ant.ScalaTool -->
- <property name="java.flags" value="-Xmx256M -Xms32M"/>
- <property name="jvm.opts" value=""/>
+ <property name="java.flags" value="-Xmx256M -Xms32M"/>
+ <property name="jvm.opts" value=""/>
<!-- if ANT_OPTS is already set by the environment, it will be unaltered,
but if it is unset it will take this default value. -->
- <property name="env.ANT_OPTS" value="-Xms1536M -Xmx1536M -Xss1M -XX:MaxPermSize=192M -XX:+UseParallelGC" />
+ <property name="env.ANT_OPTS" value="-Xms1536M -Xmx1536M -Xss1M -XX:MaxPermSize=192M -XX:+UseParallelGC" />
- <property name="scalacfork.jvmargs" value="${env.ANT_OPTS} ${jvm.opts}"/>
+ <property name="scalacfork.jvmargs" value="${env.ANT_OPTS} ${jvm.opts}"/>
<!-- ===========================================================================
INITIALIZATION
@@ -167,11 +168,15 @@ targets exercised:
<path id="maven-ant-tasks.classpath" path="${lib-ant.dir}/maven-ant-tasks-2.1.1.jar" />
<typedef resource="org/apache/maven/artifact/ant/antlib.xml" uri="urn:maven-artifact-ant" classpathref="maven-ant-tasks.classpath" />
+ <!-- Resolve maven dependencies -->
+
<!-- work around http://jira.codehaus.org/browse/MANTTASKS-203:
java.lang.ClassCastException: org.codehaus.plexus.DefaultPlexusContainer cannot be cast to org.codehaus.plexus.PlexusContainer
on repeated use of artifact:dependencies
-->
<if><not><isset property="maven-deps-done"></isset></not><then>
+ <mkdir dir="${user.home}/.m2/repository"/>
+ <!-- This task has an issue where if the user directory does not exist, so we create it above. UGH. -->
<artifact:dependencies pathId="extra.tasks.classpath" filesetId="extra.tasks.fileset">
<dependency groupId="biz.aQute" artifactId="bnd" version="1.50.0"/>
</artifact:dependencies>
@@ -190,16 +195,15 @@ targets exercised:
<dependency groupId="org.apache.felix" artifactId="org.apache.felix.framework" version="3.2.2"/>
</artifact:dependencies>
+ <artifact:dependencies pathId="partest.extras.classpath" filesetId="partest.extras.fileset" versionsId="partest.extras.versions">
+ <dependency groupId="com.googlecode.java-diff-utils" artifactId="diffutils" version="1.3.0"/>
+ </artifact:dependencies>
+
<!-- BND support -->
<typedef resource="aQute/bnd/ant/taskdef.properties" classpathref="extra.tasks.classpath" />
- <!-- Resolve maven dependencies -->
- <mkdir dir="${user.home}/.m2/repository"/>
- <!-- This task has an issue where if the user directory does not exist, so we create it above. UGH. -->
- <artifact:dependencies pathId="dependency.classpath" filesetId="dependency.fileset">
- <!--<dependency groupId="com.typesafe" artifactId="config" version="0.4.0"/>-->
- </artifact:dependencies>
-
+ <!-- Download STARR via maven if `starr.version` is specified.
+ Want to slow down STARR changes, using only released versions. -->
<if><isset property="starr.version"/><then>
<artifact:dependencies pathId="starr.core.path">
<dependency groupId="org.scala-lang" artifactId="scala-library" version="${starr.version}"/>
@@ -208,7 +212,7 @@ targets exercised:
</artifact:dependencies>
</then></if>
- <property name="maven-deps-done" value="yep!"/>
+ <property name="maven-deps-done" value="yep!"/>
</then></if>
@@ -226,30 +230,30 @@ targets exercised:
- `version.suffix == maven.version.suffix == ""`
-->
<if><not><equals arg1="${version.bnum}" arg2="0"/></not><then>
- <property name="version.suffix" value="-${version.bnum}"/>
+ <property name="version.suffix" value="-${version.bnum}"/>
</then></if>
<if><or><not><isset property="version.suffix"/></not><equals arg1="${version.suffix}" arg2=""/></or><then>
<if><isset property="build.release"/><then>
- <property name="maven.version.suffix" value=""/>
- <property name="version.suffix" value="${maven.version.suffix}"/>
+ <property name="maven.version.suffix" value=""/>
+ <property name="version.suffix" value="${maven.version.suffix}"/>
<if><equals arg1="${maven.version.suffix}" arg2=""/><then>
<property name="osgi.version.suffix" value="-VFINAL"/></then>
<else>
<property name="osgi.version.suffix" value="${maven.version.suffix}"/></else></if></then></if></then>
<else> <!-- version.suffix set and not empty -->
- <property name="maven.version.suffix" value="${version.suffix}"/>
- <property name="osgi.version.suffix" value="${version.suffix}"/></else></if>
+ <property name="maven.version.suffix" value="${version.suffix}"/>
+ <property name="osgi.version.suffix" value="${version.suffix}"/></else></if>
<!-- not building a release and no version.suffix specified -->
- <property name="maven.version.suffix" value="-SNAPSHOT"/>
+ <property name="maven.version.suffix" value="-SNAPSHOT"/>
<if><equals arg1="${maven.version.suffix}" arg2="-SNAPSHOT"/><then>
- <property name="osgi.version.suffix" value=""/>
- <property name="version.suffix" value=""/></then>
+ <property name="osgi.version.suffix" value=""/>
+ <property name="version.suffix" value=""/></then>
<else>
- <property name="osgi.version.suffix" value="${maven.version.suffix}"/>
- <property name="version.suffix" value="${maven.version.suffix}"/></else></if>
+ <property name="osgi.version.suffix" value="${maven.version.suffix}"/>
+ <property name="version.suffix" value="${maven.version.suffix}"/></else></if>
<exec osfamily="unix" executable="tools/get-scala-commit-sha" outputproperty="git.commit.sha" failifexecutionfails="false" />
@@ -266,8 +270,8 @@ targets exercised:
</exec>
<!-- some default in case something went wrong getting the revision -->
- <property name="git.commit.sha" value="unknown"/>
- <property name="git.commit.date" value="unknown"/>
+ <property name="git.commit.sha" value="unknown"/>
+ <property name="git.commit.date" value="unknown"/>
<!-- We use the git describe to determine the OSGi modifier for our build. -->
<property name="maven.version.number"
@@ -276,9 +280,9 @@ targets exercised:
value="${version.major}.${version.minor}.${version.patch}.v${git.commit.date}${osgi.version.suffix}-${git.commit.sha}"/>
<if><isset property="build.release"/><then>
- <property name="version.number" value="${maven.version.number}"/>
+ <property name="version.number" value="${maven.version.number}"/>
</then><else>
- <property name="version.number" value="${version.major}.${version.minor}.${version.patch}${version.suffix}-${git.commit.date}-${git.commit.sha}"/>
+ <property name="version.number" value="${version.major}.${version.minor}.${version.patch}${version.suffix}-${git.commit.date}-${git.commit.sha}"/>
</else></if>
<condition property="has.java6">
@@ -304,27 +308,27 @@ targets exercised:
</then></if>
<!-- Allow this to be overridden simply -->
- <property name="sbt.latest.version" value="0.12.2"/>
+ <property name="sbt.latest.version" value="0.12.2"/>
- <property name="sbt.src.dir" value="${build-sbt.dir}/${sbt.latest.version}/src"/>
- <property name="sbt.lib.dir" value="${build-sbt.dir}/${sbt.latest.version}/lib"/>
+ <property name="sbt.src.dir" value="${build-sbt.dir}/${sbt.latest.version}/src"/>
+ <property name="sbt.lib.dir" value="${build-sbt.dir}/${sbt.latest.version}/lib"/>
- <property name="sbt.interface.jar" value="${sbt.lib.dir}/interface.jar"/>
- <property name="sbt.interface.url" value="http://typesafe.artifactoryonline.com/typesafe/ivy-releases/org.scala-sbt/interface/${sbt.latest.version}/jars/interface.jar"/>
+ <property name="sbt.interface.jar" value="${sbt.lib.dir}/interface.jar"/>
+ <property name="sbt.interface.url" value="http://typesafe.artifactoryonline.com/typesafe/ivy-releases/org.scala-sbt/interface/${sbt.latest.version}/jars/interface.jar"/>
<property name="sbt.interface.src.jar" value="${sbt.src.dir}/compiler-interface-src.jar"/>
<property name="sbt.interface.src.url" value="http://typesafe.artifactoryonline.com/typesafe/ivy-releases/org.scala-sbt/compiler-interface/${sbt.latest.version}/jars/compiler-interface-src.jar"/>
<!-- Additional command line arguments for scalac. They are added to all build targets -->
- <property name="scalac.args" value=""/>
- <property name="javac.args" value=""/>
+ <property name="scalac.args" value=""/>
+ <property name="javac.args" value=""/>
- <property name="scalac.args.always" value="" />
- <property name="scalac.args.optimise" value=""/> <!-- scalac.args.optimise is selectively overridden in certain antcall tasks. -->
- <property name="scalac.args.all" value="${scalac.args.always} ${scalac.args} ${scalac.args.optimise}"/>
- <property name="scalac.args.locker" value="${scalac.args.all}"/>
- <property name="scalac.args.quick" value="${scalac.args.all}"/>
- <property name="scalac.args.strap" value="${scalac.args.quick}"/>
+ <property name="scalac.args.always" value="" />
+ <property name="scalac.args.optimise" value=""/> <!-- scalac.args.optimise is selectively overridden in certain antcall tasks. -->
+ <property name="scalac.args.all" value="${scalac.args.always} ${scalac.args} ${scalac.args.optimise}"/>
+ <property name="scalac.args.locker" value="${scalac.args.all}"/>
+ <property name="scalac.args.quick" value="${scalac.args.all}"/>
+ <property name="scalac.args.strap" value="${scalac.args.quick}"/>
<!-- This is the start time for the distribution -->
<tstamp prefix="time">
@@ -333,8 +337,8 @@ targets exercised:
</tstamp>
<!-- some default in case something went wrong getting the revision -->
- <property name="version.number" value="-unknown-"/>
- <property name="init.avail" value="yes"/>
+ <property name="version.number" value="-unknown-"/>
+ <property name="init.avail" value="yes"/>
<!-- Local libs (developer use.) -->
<mkdir dir="${lib-extra.dir}"/>
@@ -347,7 +351,6 @@ targets exercised:
<fileset dir="${lib-extra.dir}">
<include name="**/*.jar"/>
</fileset>
- <path refid="dependency.classpath"/>
</path>
<!-- And print-out what we are building -->
@@ -387,7 +390,9 @@ targets exercised:
<fail unless="version.suffixes.consistent" message="Version suffixes inconsistent!"/>
<path id="forkjoin.classpath" path="${build-libs.dir}/classes/forkjoin"/>
- <path id="asm.classpath" path="${build-asm.dir}/classes/"/>
+ <path id="asm.classpath" path="${build-asm.dir}/classes"/>
+ <property name="forkjoin-classes" refid="forkjoin.classpath"/>
+ <property name="asm-classes" refid="asm.classpath"/>
<!-- Compilers to use for the various stages.
@@ -500,7 +505,8 @@ targets exercised:
<path id="quick.partest.build.path">
<path refid="quick.scalap.build.path"/>
- <pathelement location="${build-quick.dir}/classes/repl"/>
+ <path refid="partest.extras.classpath"/>
+ <pathelement location="${build-quick.dir}/classes/repl"/>
<pathelement location="${scalacheck.jar}"/>
</path>
@@ -523,6 +529,7 @@ targets exercised:
</path>
<!-- PACK -->
+ <!-- also used for docs.* targets TODO: use separate paths for those -->
<path id="pack.compiler.path">
<pathelement location="${build-pack.dir}/lib/scala-library.jar"/>
<pathelement location="${build-pack.dir}/lib/scala-reflect.jar"/>
@@ -531,6 +538,7 @@ targets exercised:
<pathelement location="${build-pack.dir}/lib/scalap.jar"/>
<pathelement location="${build-pack.dir}/lib/scala-actors.jar"/>
<pathelement location="${ant.jar}"/>
+ <path refid="partest.extras.classpath"/>
<path refid="aux.libs"/>
</path>
@@ -543,6 +551,47 @@ targets exercised:
<path refid="aux.libs"/>
</path>
+ <path id="pack.library.files">
+ <fileset dir="${build-quick.dir}/classes/library">
+ <!-- <exclude name="scala/swing/**"/> -->
+ <exclude name="scala/actors/**"/>
+ </fileset>
+ <fileset dir="${build-quick.dir}/classes/continuations-library"/>
+ <fileset dir="${forkjoin-classes}"/>
+ </path>
+
+ <path id="pack.actors.files">
+ <fileset dir="${build-quick.dir}/classes/library">
+ <include name="scala/actors/**"/>
+ </fileset>
+ </path>
+
+ <path id="pack.compiler.files">
+ <fileset dir="${build-quick.dir}/classes/compiler"/>
+ <fileset dir="${build-quick.dir}/classes/repl"/>
+ <fileset dir="${build-quick.dir}/classes/scaladoc"/>
+ <fileset dir="${build-quick.dir}/classes/interactive"/>
+ <fileset dir="${asm-classes}"/>
+ </path>
+
+ <path id="pack.swing.files"> <fileset dir="${build-quick.dir}/classes/swing"/> </path>
+ <path id="pack.reflect.files"> <fileset dir="${build-quick.dir}/classes/reflect"/> </path>
+ <path id="pack.plugins.files"> <fileset dir="${build-quick.dir}/classes/continuations-plugin"/> </path>
+ <path id="pack.scalacheck.files"> <fileset dir="${build-quick.dir}/classes/scalacheck"/> </path>
+ <path id="pack.scalap.files"> <fileset dir="${build-quick.dir}/classes/scalap"/>
+ <fileset file="${src.dir}/scalap/decoder.properties"/> </path>
+
+ <path id="pack.partest.files">
+ <fileset dir="${build-quick.dir}/classes/partest">
+ <exclude name="scala/tools/partest/javaagent/**"/>
+ </fileset>
+ </path>
+
+ <path id="pack.partest-javaagent.files">
+ <fileset dir="${build-quick.dir}/classes/partest">
+ <include name="scala/tools/partest/javaagent/**"/>
+ </fileset>
+ </path>
<!-- STRAP -->
<path id="strap.library.build.path">
@@ -579,6 +628,11 @@ targets exercised:
<path id="partest.classpath">
<path refid="pack.compiler.path"/>
+ <path refid="partest.extras.classpath"/>
+ </path>
+
+ <path id="partest.build.path">
+ <path refid="pack.compiler.path"/>
<fileset dir="${partest.dir}/files/lib" includes="*.jar" />
<pathelement location="${pack.dir}/lib/scala-swing.jar"/> <!-- TODO - segregate swing tests (there can't be many) -->
</path>
@@ -660,53 +714,39 @@ targets exercised:
<delete dir="${build-@{build}.dir}" includeemptydirs="yes" quiet="yes" failonerror="no"/>
</sequential>
</macrodef>
-
<!-- ===========================================================================
- LOCAL DEPENDENCY (Adapted ASM)
+ LOCAL DEPENDENCIES
============================================================================ -->
- <target name="asm.done" depends="init">
- <available file="${build-asm.dir}/asm.complete" property="asm.available"/>
- <if><not><isset property="asm.available"/></not><then>
- <stopwatch name="asm.lib.timer"/>
- <mkdir dir="${build-asm.dir}/classes/"/>
- <javac
- srcdir="${src.dir}/asm"
- destdir="${build-asm.dir}/classes"
- classpath="${build-asm.dir}/classes"
- includes="**/*.java"
- target="1.6" source="1.5">
- <compilerarg line="${javac.args} -XDignore.symbol.file"/>
- </javac>
- <stopwatch name="asm.lib.timer" action="total"/>
- <touch file="${build-asm.dir}/asm.complete" verbose="no"/>
- </then></if>
- </target>
-
-<!-- ===========================================================================
- LOCAL DEPENDENCY (FORKJOIN)
-============================================================================ -->
- <target name="forkjoin.done" depends="init">
- <uptodate property="forkjoin.available" targetfile="${build-libs.dir}/forkjoin.complete">
- <srcfiles dir="${src.dir}/forkjoin"/></uptodate>
- <if><not><isset property="forkjoin.available"/></not><then>
- <stopwatch name="forkjoin.lib.timer"/>
- <mkdir dir="${build-libs.dir}/classes/forkjoin"/>
- <javac
- fork="yes"
- compiler="javac1.6"
- srcdir="${src.dir}/forkjoin"
- destdir="${build-libs.dir}/classes/forkjoin"
- classpath="${build-libs.dir}/classes/forkjoin"
- includes="**/*.java"
- debug="true"
- target="1.6" source="1.5">
- <compilerarg line="${javac.args} -XDignore.symbol.file"/>
- </javac>
- <jar whenmanifestonly="fail" destfile="${build-libs.dir}/forkjoin.jar" basedir="${build-libs.dir}/classes/forkjoin"/>
- <stopwatch name="forkjoin.lib.timer" action="total"/>
- <touch file="${build-libs.dir}/forkjoin.complete" verbose="no"/>
- </then></if>
- </target>
+ <macrodef name="simple-javac" >
+ <attribute name="project"/> <!-- project: asm/forkjoin -->
+ <attribute name="args" default=""/>
+ <attribute name="jar" default="yes"/>
+ <sequential>
+ <uptodate property="@{project}.available" targetfile="${build-libs.dir}/@{project}.complete">
+ <srcfiles dir="${src.dir}/@{project}"/></uptodate>
+ <if><not><isset property="@{project}.available"/></not><then>
+ <stopwatch name="@{project}.timer"/>
+ <mkdir dir="${@{project}-classes}"/>
+ <javac
+ srcdir="${src.dir}/@{project}"
+ destdir="${@{project}-classes}"
+ classpath="${@{project}-classes}"
+ includes="**/*.java"
+ target="1.6" source="1.5"
+ compiler="javac1.6">
+ <compilerarg line="${javac.args} @{args}"/>
+ </javac>
+ <if><equals arg1="@{jar}" arg2="yes"/><then>
+ <jar whenmanifestonly="fail" destfile="${build-libs.dir}/@{project}.jar" basedir="${@{project}-classes}"/></then></if>
+ <stopwatch name="@{project}.timer" action="total"/>
+ <mkdir dir="${build-libs.dir}"/>
+ <touch file="${build-libs.dir}/@{project}.complete" verbose="no"/>
+ </then></if>
+ </sequential>
+ </macrodef>
+
+ <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>
<!-- ===========================================================================
STAGED COMPILATION MACROS
@@ -871,15 +911,33 @@ targets exercised:
<attribute name="project"/>
<attribute name="targetdir" default="lib"/>
<attribute name="targetjar" default="scala-@{project}.jar"/>
- <element name="do" implicit="true"/>
+ <attribute name="destfile" default="${build-pack.dir}/@{targetdir}/@{targetjar}"/>
+ <attribute name="manifest" default=""/>
+ <element name="pre" optional="true"/>
+ <element name="jar-opts" optional="true"/>
<sequential>
- <uptodate property="pack.@{project}.available"
- targetfile="${build-pack.dir}/@{targetdir}/@{targetjar}"
- srcfile="${build-quick.dir}/@{project}.complete"/>
+ <uptodate property="pack.@{project}.available" targetfile="@{destfile}">
+ <srcresources>
+ <resources refid="pack.@{project}.files"/>
+ <!-- <path><pathelement location="${build-quick.dir}/@{project}.complete"/></path> -->
+ </srcresources>
+ </uptodate>
<if><not><isset property="pack.@{project}.available"/></not><then>
<mkdir dir="${build-pack.dir}/@{targetdir}"/>
- <do/>
+ <pre/>
+
+ <if><not><equals arg1="@{manifest}" arg2=""/></not><then>
+ <jar whenmanifestonly="fail" destfile="@{destfile}" manifest="@{manifest}"> <!-- update="true" makes no difference on my machine, so starting from scratch-->
+ <jar-opts/>
+ <path refid="pack.@{project}.files"/>
+ </jar></then>
+ <else>
+ <jar whenmanifestonly="fail" destfile="@{destfile}">
+ <jar-opts/>
+ <path refid="pack.@{project}.files"/>
+ </jar>
+ </else></if>
</then></if>
</sequential>
</macrodef>
@@ -897,7 +955,8 @@ targets exercised:
<do>
<stopwatch name="docs.@{project}.timer"/>
<mkdir dir="${build-docs.dir}/@{project}"/>
- <if><equals arg1="@{classpathref}" arg2="NOT SET"/><then>
+ <if><equals arg1="@{docroot}" arg2="NOT SET"/><then>
+ <!-- TODO: introduce docs.@{project}.build.path for classpathref -->
<scaladoc
destdir="${build-docs.dir}/@{project}"
doctitle="@{title}"
@@ -1057,113 +1116,64 @@ targets exercised:
<!-- ===========================================================================
PACKED QUICK BUILD (PACK)
============================================================================ -->
- <target name="pack.lib" depends="quick.lib, quick.plugins, forkjoin.done">
- <staged-pack project="library">
- <!-- First copy maven dependencies -->
- <copy todir="${build-pack.dir}/lib">
- <fileset refid="dependency.fileset" />
- <mapper type="flatten" />
- </copy>
- <jar whenmanifestonly="fail" destfile="${build-pack.dir}/lib/scala-library.jar">
- <fileset dir="${build-quick.dir}/classes/library">
- <exclude name="scala/swing/**"/>
- <exclude name="scala/actors/**"/>
- </fileset>
- <fileset dir="${build-quick.dir}/classes/continuations-library"/>
- <fileset dir="${build-libs.dir}/classes/forkjoin"/>
- </jar>
- <jar whenmanifestonly="fail" destfile="${build-pack.dir}/lib/scala-actors.jar">
- <fileset dir="${build-quick.dir}/classes/library">
- <include name="scala/actors/**"/>
- </fileset>
- </jar>
- </staged-pack>
- </target>
-
- <target name="pack.swing" depends="quick.swing" if="has.java6">
- <staged-pack project="swing’">
- <jar whenmanifestonly="fail" destfile="${build-pack.dir}/lib/scala-swing.jar" basedir="${build-quick.dir}/classes/swing"/>
- </staged-pack>
- </target>
-
- <target name="pack.reflect" depends="quick.reflect">
- <staged-pack project="reflect’">
- <jar whenmanifestonly="fail" destfile="${build-pack.dir}/lib/scala-reflect.jar" basedir="${build-quick.dir}/classes/reflect"/>
- </staged-pack>
- </target>
-
- <target name="pack.comp" depends="quick.comp, quick.scaladoc, quick.interactive, quick.repl, asm.done">
- <staged-pack project="compiler">
- <mkdir dir="${build-pack.dir}/META-INF"/>
- <copy file="META-INF/MANIFEST.MF" toDir="${build-pack.dir}/META-INF"/>
- <manifest file="${build-pack.dir}/META-INF/MANIFEST.MF" mode="update">
- <attribute name="Bundle-Version" value="${version.number}"/>
- <attribute name="Class-Path" value="scala-reflect.jar scala-library.jar"/>
- </manifest>
- <jar whenmanifestonly="fail" destfile="${build-pack.dir}/lib/scala-compiler.jar" manifest="${build-pack.dir}/META-INF/MANIFEST.MF">
- <service type="javax.script.ScriptEngineFactory" provider="scala.tools.nsc.interpreter.IMain$Factory"/>
- <fileset dir="${build-quick.dir}/classes/compiler"/>
+ <target name="pack.lib" depends="quick.lib, quick.plugins, forkjoin.done">
+ <staged-pack project="library"/></target>
+
+ <target name="pack.actors" depends="quick.lib"> <staged-pack project="actors"/> </target>
+ <target name="pack.swing" if="has.java6" depends="quick.swing"> <staged-pack project="swing"/> </target>
+ <target name="pack.reflect" depends="quick.reflect"> <staged-pack project="reflect"/> </target>
+
+ <target name="pack.comp" depends="quick.comp, quick.scaladoc, quick.interactive, quick.repl, asm.done">
+ <staged-pack project="compiler" manifest="${build-pack.dir}/META-INF/MANIFEST.MF">
+ <pre> <!-- TODO the files copied here do not influence actuality of this target (nor does the manifest) -->
+ <copy file="${jline.jar}" toDir="${build-pack.dir}/lib"/>
+ <copy todir="${build-pack.dir}/lib">
+ <fileset dir="${lib-extra.dir}">
+ <include name="**/*.jar"/>
+ </fileset>
+ </copy>
+ <mkdir dir="${build-pack.dir}/META-INF"/>
+ <copy file="${basedir}/META-INF/MANIFEST.MF" toDir="${build-pack.dir}/META-INF"/>
+ <manifest file="${build-pack.dir}/META-INF/MANIFEST.MF" mode="update">
+ <attribute name="Bundle-Version" value="${version.number}"/>
+ <attribute name="Class-Path" value="scala-reflect.jar scala-library.jar"/>
+ </manifest>
+ </pre>
+ <jar-opts>
<fileset dir="${build-quick.dir}/classes/scaladoc"/>
<fileset dir="${build-quick.dir}/classes/interactive"/>
<fileset dir="${build-quick.dir}/classes/repl"/>
- <fileset dir="${build-asm.dir}/classes"/>
- </jar>
- <copy file="${jline.jar}" toDir="${build-pack.dir}/lib"/>
- <copy todir="${build-pack.dir}/lib">
- <fileset dir="${lib-extra.dir}">
- <include name="**/*.jar"/>
- </fileset>
- </copy>
- </staged-pack>
- </target>
-
- <target name="pack.plugins" depends="quick.plugins">
- <staged-pack project="plugins" targetdir="misc/scala-devel/plugins" targetjar="continuations.jar">
- <jar whenmanifestonly="fail" destfile="${build-pack.dir}/misc/scala-devel/plugins/continuations.jar" basedir="${build-quick.dir}/classes/continuations-plugin"/>
+ <service type="javax.script.ScriptEngineFactory" provider="scala.tools.nsc.interpreter.IMain$Factory"/>
+ </jar-opts>
</staged-pack>
</target>
- <target name="pack.scalacheck" depends="quick.scalacheck">
- <uptodate property="pack.scalacheck.available"
- targetfile="${build-pack.dir}/lib/scalacheck.jar">
- <srcfiles dir="${build-quick.dir}/classes/scalacheck"/></uptodate>
- <if><not><isset property="pack.scalacheck.available"/></not><then>
- <jar whenmanifestonly="fail" destfile="${build-pack.dir}/lib/scalacheck.jar" basedir="${build-quick.dir}/classes/scalacheck"/>
- </then></if>
- </target>
+ <target name="pack.plugins" depends="quick.plugins"> <staged-pack project="plugins" targetdir="misc/scala-devel/plugins" targetjar="continuations.jar"/> </target>
+ <target name="pack.scalacheck" depends="quick.scalacheck"> <staged-pack project="scalacheck" targetjar="scalacheck.jar"/> </target>
<target name="pack.partest" depends="quick.partest">
- <staged-pack project="partest">
- <jar whenmanifestonly="fail" destfile="${build-pack.dir}/lib/scala-partest.jar">
- <fileset dir="${build-quick.dir}/classes/partest">
- <exclude name="scala/tools/partest/javaagent/**"/>
- </fileset>
- </jar>
- <jar whenmanifestonly="fail" destfile = "${build-pack.dir}/lib/scala-partest-javaagent.jar"
- manifest = "${src.dir}/partest/scala/tools/partest/javaagent/MANIFEST.MF">
- <fileset dir = "${build-quick.dir}/classes/partest">
- <include name = "scala/tools/partest/javaagent/**"/>
- </fileset>
- </jar>
- </staged-pack>
+ <staged-pack project="partest"/>
+ <!-- TODO the manifest should influence actuality of this target -->
+ <staged-pack project="partest-javaagent" manifest="${src.dir}/partest/scala/tools/partest/javaagent/MANIFEST.MF"/>
</target>
- <target name="pack.scalap" depends="quick.scalap">
- <staged-pack project="plugins" targetjar="scalap.jar">
- <jar whenmanifestonly="fail" destfile="${build-pack.dir}/lib/scalap.jar">
- <fileset dir="${build-quick.dir}/classes/scalap"/>
- <fileset file="${src.dir}/scalap/decoder.properties"/>
- </jar>
- </staged-pack>
- </target>
+ <target name="pack.scalap" depends="quick.scalap"> <staged-pack project="scalap" targetjar="scalap.jar"/> </target>
- <target name="pack.bin" depends="pack.comp, pack.lib, pack.partest, pack.plugins, pack.reflect, pack.scalacheck, pack.scalap, pack.swing">
+ <target name="pack.bin" depends="pack.comp, pack.lib, pack.actors, pack.partest, pack.plugins, pack.reflect, pack.scalacheck, pack.scalap, pack.swing">
<staged-bin stage="pack"/>
</target>
- <target name="pack.done" depends="pack.bin">
+ <!-- depend on quick.done so quick.bin is run when pack.done is -->
+ <target name="pack.done" depends="quick.done, pack.bin">
+ <!-- copy dependencies to build/pack/lib, it only takes a second so don't bother with uptodate checks -->
+ <copy todir="${build-pack.dir}/lib">
+ <resources refid="partest.extras.fileset"/>
+ <mapper classpathref="maven-ant-tasks.classpath" classname="org.apache.maven.artifact.ant.VersionMapper"
+ from="${partest.extras.versions}" to="flatten"/>
+ </copy>
+
<taskdef resource="scala/tools/ant/antlib.xml" classpathref="pack.compiler.path"/>
- <taskdef resource="scala/tools/partest/antlib.xml" classpathref="pack.compiler.path"/>
+ <taskdef resource="scala/tools/partest/antlib.xml" classpathref="partest.classpath"/>
</target>
@@ -1195,13 +1205,13 @@ targets exercised:
<mkdir dir="${build-palo.dir}/lib"/>
<jar whenmanifestonly="fail" destfile="${build-palo.dir}/lib/scala-library.jar">
<fileset dir="${build-locker.dir}/classes/library"/>
- <fileset dir="${build-libs.dir}/classes/forkjoin"/>
+ <fileset dir="${forkjoin-classes}"/>
</jar>
<jar whenmanifestonly="fail" destfile="${build-palo.dir}/lib/scala-reflect.jar" manifest="${basedir}/META-INF/MANIFEST.MF"
basedir="${build-locker.dir}/classes/reflect"/>
<jar whenmanifestonly="fail" destfile="${build-palo.dir}/lib/scala-compiler.jar" manifest="${basedir}/META-INF/MANIFEST.MF">
<fileset dir="${build-locker.dir}/classes/compiler"/>
- <fileset dir="${build-asm.dir}/classes/"/>
+ <fileset dir="${asm-classes}"/>
</jar>
<copy file="${jline.jar}" toDir="${build-palo.dir}/lib"/>
</target>
@@ -1369,7 +1379,7 @@ targets exercised:
srcdir="${partest.srcdir}"
scalacopts="${scalac.args.optimise}">
- <compilationpath refid="partest.classpath"/>
+ <compilationpath refid="partest.build.path"/>
<runtests dir="${partest.dir}/${partest.srcdir}/run" includes="*.scala"/>
<jvmtests dir="${partest.dir}/${partest.srcdir}/jvm" includes="*.scala"/>
</partest>
@@ -1380,7 +1390,7 @@ targets exercised:
timeout="2400000"
srcdir="${partest.srcdir}"
scalacopts="${scalac.args.optimise}">
- <compilationpath refid="partest.classpath"/>
+ <compilationpath refid="partest.build.path"/>
<postests dir="${partest.dir}/${partest.srcdir}/pos" includes="*.scala"/>
<negtests dir="${partest.dir}/${partest.srcdir}/neg" includes="*.scala"/>
<runtests dir="${partest.dir}/${partest.srcdir}/run" includes="*.scala"/>
@@ -1406,7 +1416,7 @@ targets exercised:
scalacopts="${scalac.args.optimise} -Xplugin-require:continuations -P:continuations:enable">
<compilerarg value="-Xpluginsdir"/>
<compilerarg file="${build-quick.dir}/misc/scala-devel/plugins"/>
- <compilationpath refid="partest.classpath"/>
+ <compilationpath refid="partest.build.path"/>
<negtests dir="${partest.dir}/${partest.srcdir}/continuations-neg" includes="*.scala"/>
<runtests dir="${partest.dir}/${partest.srcdir}/continuations-run" includes="*.scala"/>
</partest>
@@ -1414,7 +1424,7 @@ targets exercised:
<target name="test.scaladoc" depends="pack.done">
<partest erroronfailed="yes" scalacopts="${scalac.args.optimise}" showlog="yes">
- <compilationpath refid="partest.classpath"/>
+ <compilationpath refid="partest.build.path"/>
<runtests dir="${partest.dir}/scaladoc/run" includes="*.scala" />
<scalachecktests dir="${partest.dir}/scaladoc/scalacheck" includes="*.scala" />
</partest>
@@ -1422,60 +1432,89 @@ targets exercised:
<target name="test.interactive" depends="pack.done">
<partest erroronfailed="yes" scalacopts="${scalac.args.optimise}" showlog="yes">
- <compilationpath refid="partest.classpath"/>
+ <compilationpath refid="partest.build.path"/>
<presentationtests dir="${partest.dir}/${partest.srcdir}/presentation">
<include name="*/*.scala"/>
</presentationtests>
</partest>
</target>
-<!-- currently disabled: test.ant, test.bc, test.positions, test.classload -->
- <target name="test.done" depends="test.osgi, test.sbt, test.interactive, test.continuations.suite, test.suite, test.scaladoc, test.stability"/>
+ <!-- for use in PR validation, where stability is rarely broken, so we're going to use starr for locker,
+ and skip test.stability (which requires locker == quick) -->
+ <target name="test.core" depends="test.osgi, test.sbt, test.bc, test.interactive, test.continuations.suite, test.scaladoc, test.suite"/>
+ <target name="test.done" depends="test.core, test.stability"/>
<!-- ===========================================================================
BINARY COMPATIBILITY TESTING
============================================================================ -->
<target name="bc.init" depends="init" unless="maven-deps-done-mima">
+ <property name="bc-reference-version" value="2.11.0"/>
+
<property name="bc-build.dir" value="${build.dir}/bc"/>
<!-- Obtain mima -->
<mkdir dir="${bc-build.dir}"/>
<!-- Pull down MIMA -->
<artifact:dependencies pathId="mima.classpath">
- <dependency groupId="com.typesafe" artifactId="mima-reporter_2.9.2" version="0.1.4"/>
+ <dependency groupId="com.typesafe" artifactId="mima-reporter_2.9.2" version="0.1.5"/>
</artifact:dependencies>
<artifact:dependencies pathId="old.bc.classpath">
- <dependency groupId="org.scala-lang" artifactId="scala-library" version="2.10.0-RC2"/>
- <dependency groupId="org.scala-lang" artifactId="scala-reflect" version="2.10.0-RC2"/>
+ <dependency groupId="org.scala-lang" artifactId="scala-swing" version="${bc-reference-version}"/>
+ <dependency groupId="org.scala-lang" artifactId="scala-library" version="${bc-reference-version}"/>
+ <dependency groupId="org.scala-lang" artifactId="scala-reflect" version="${bc-reference-version}"/>
</artifact:dependencies>
<property name="maven-deps-done-mima" value="true"/>
</target>
- <target name="test.bc" depends="bc.init, pack.lib">
- <java
- fork="true"
- failonerror="true"
- classname="com.typesafe.tools.mima.cli.Main">
- <arg value="--prev"/>
- <arg value="${org.scala-lang:scala-library:jar}"/>
- <arg value="--curr"/>
- <arg value="${build-pack.dir}/lib/scala-library.jar"/>
- <classpath>
- <path refid="mima.classpath"/>
- </classpath>
- </java>
- <java
- fork="true"
- failonerror="true"
- classname="com.typesafe.tools.mima.cli.Main">
- <arg value="--prev"/>
- <arg value="${org.scala-lang:scala-reflect:jar}"/>
- <arg value="--curr"/>
- <arg value="${build-pack.dir}/lib/scala-reflect.jar"/>
- <classpath>
- <path refid="mima.classpath"/>
- </classpath>
- </java>
+ <macrodef name="bc.run-mima">
+ <attribute name="jar-name"/>
+ <attribute name="prev"/>
+ <attribute name="curr"/>
+ <attribute name="direction"/>
+ <sequential>
+ <echo message="Checking @{direction} binary compatibility for @{jar-name} (against ${bc-reference-version})"/>
+ <java taskname="mima"
+ fork="true"
+ failonerror="true"
+ classname="com.typesafe.tools.mima.cli.Main">
+ <arg value="--prev"/>
+ <arg value="@{prev}"/>
+ <arg value="--curr"/>
+ <arg value="@{curr}"/>
+ <arg value="--filters"/>
+ <arg value="${basedir}/bincompat-@{direction}.whitelist.conf"/>
+ <arg value="--generate-filters"/>
+ <classpath>
+ <path refid="mima.classpath"/>
+ </classpath>
+ </java>
+ </sequential>
+ </macrodef>
+
+ <macrodef name="bc.check">
+ <attribute name="jar-name"/>
+ <sequential>
+ <bc.run-mima
+ jar-name="@{jar-name}"
+ prev="${org.scala-lang:@{jar-name}:jar}"
+ curr="${build-pack.dir}/lib/@{jar-name}.jar"
+ direction="backward"/>
+ <bc.run-mima
+ jar-name="@{jar-name}"
+ prev="${build-pack.dir}/lib/@{jar-name}.jar"
+ curr="${org.scala-lang:@{jar-name}:jar}"
+ direction="forward"/>
+ </sequential>
+ </macrodef>
+
+ <target name="test.bc-opt" description="Optimized version of test.bc."> <optimized name="test.bc"/></target>
+
+ <!-- Enable after the release of the 2.11.0 or a prior RC that estabilishes the new baseline. -->
+ <target name="test.bc"></target>
+ <target name="test.bc.disabled" depends="bc.init, pack.lib, pack.reflect, pack.swing">
+ <bc.check jar-name="scala-library"/>
+ <bc.check jar-name="scala-reflect"/>
+ <bc.check jar-name="scala-swing"/>
</target>
<!-- ===========================================================================
@@ -1509,6 +1548,7 @@ targets exercised:
<include name="swing/**"/>
<include name="actors/**"/>
<include name="reflect/**"/>
+ <include name="continuations/library/**"/>
</srcfiles></check>
<do>
<stopwatch name="docs.lib.timer"/>
@@ -1656,6 +1696,13 @@ targets exercised:
<include name="scalap.jar"/>
</fileset>
</copy>
+
+ <copy todir="${dist.dir}/lib">
+ <resources refid="partest.extras.fileset"/>
+ <mapper classpathref="maven-ant-tasks.classpath" classname="org.apache.maven.artifact.ant.VersionMapper"
+ from="${partest.extras.versions}" to="flatten"/>
+ </copy>
+
<mkdir dir="${dist.dir}/bin"/>
<!-- TODO - Stop being inefficient and don't copy OSGi bundles overtop other jars. -->
<copy-bundle name="scala-library"/>
@@ -1804,7 +1851,7 @@ targets exercised:
</target>
<target name="replacestarr-opt" description="Replaces the Starr compiler and library by fresh, optimised ones built from current sources and tests them.">
- <optimize name="replacestarr"/></target>
+ <optimized name="replacestarr"/></target>
<!-- Ant on Windows is not able to delete jar files that are referenced in any <path>.
See ticket 1290 on trac. -->
@@ -1821,13 +1868,13 @@ targets exercised:
</target>
<target name="replacestarrwin-opt" description="Creates a new Starr on Windows. Manually execute 'ant locker.clean build' first!">
- <optimize name="replacestarrwin"/></target>
+ <optimized name="replacestarrwin"/></target>
<target name="replacelocker" description="Replaces the Locker compiler and library by fresh ones built from current sources."
depends="palo.clean, locker.unlock, palo.done"/>
<target name="replacelocker-opt" description="Replaces the Locker compiler and library by fresh, optimised ones built from current sources.">
- <optimize name="replacelocker"/></target>
+ <optimized name="replacelocker"/></target>
<target name="buildlocker" description="Does the same for locker as build does for quick." depends="locker.unlock, palo.bin"/>
<target name="unlocklocker" description="Same as buildlocker." depends="buildlocker"/> <!-- REMOVE -->
@@ -1846,105 +1893,6 @@ targets exercised:
<target name="fastlocker" description="Buildlocker without extra fuss" depends="fastlocker.comp"/>
-
-<!-- ===========================================================================
- TODO: FIX OR REMOVE
-============================================================================ -->
-
- <!-- not called by test target -->
- <target name="test.classload" depends="pack.done">
- <!-- TODO - Add actors + reflect to this -->
- <classloadVerify classpath="${build-pack.dir}/lib/scala-library.jar" />
- </target>
-
- <!-- not called by test target -->
- <target name="test.ant" depends="pack.done">
- <partest showlog="yes" erroronfailed="yes" javacmd="${java.home}/bin/java"
- srcdir="${partest.srcdir}"
- scalacopts="${scalac.args.optimise}">
- <compilationpath refid="partest.classpath"/>
- <anttests dir="${partest.dir}/${partest.srcdir}/ant" includes="*build.xml"/>
- </partest>
- </target>
-
- <!-- not called by test target -->
- <target name="test.positions" depends="quick.comp">
- <antcall target="test.positions.tests.sub" inheritRefs="true">
- <param name="test.tests.srcs" value="${partest.dir}/files/positions"/>
- </antcall>
- <antcall target="test.positions.sub" inheritRefs="true">
- <param name="test.srcs" value="${src.dir}/compiler"/>
- </antcall>
- <antcall target="test.positions.sub" inheritRefs="true">
- <param name="test.srcs" value="${src.dir}/library"/>
- </antcall>
- <antcall target="test.positions.sub" inheritRefs="true">
- <param name="test.srcs" value="${src.dir}/actors"/>
- </antcall>
- <antcall target="test.positions.sub" inheritRefs="true">
- <param name="test.srcs" value="${src.dir}/dbc"/>
- </antcall>
- <antcall target="test.positions.sub" inheritRefs="true">
- <param name="test.srcs" value="${src.dir}/swing"/>
- </antcall>
- <antcall target="test.positions.sub" inheritRefs="true">
- <param name="test.srcs" value="${src.dir}/partest"/>
- </antcall>
- <antcall target="test.positions.sub" inheritRefs="true">
- <param name="test.srcs" value="${src.dir}/scalap"/>
- </antcall>
- <antcall target="test.positions.tests.sub" inheritRefs="true">
- <param name="test.tests.srcs" value="${partest.dir}/files/pos"/>
- </antcall>
- <antcall target="test.positions.tests.sub" inheritRefs="true">
- <param name="test.tests.srcs" value="${partest.dir}/files/run"/>
- </antcall>
- <antcall target="test.positions.tests.sub" inheritRefs="true">
- <param name="test.tests.srcs" value="${partest.dir}/files/neg"/>
- </antcall>
- </target>
-
- <target name="test.positions.sub">
- <echo message="Validating positions for: ${test.srcs}"/>
- <if>
- <isfileselected file="${test.srcs}">
- <type type="dir"/>
- </isfileselected>
- <then>
- <property name="srcdir" value="${test.srcs}"/>
- <property name="srcs" value="**/*.scala"/>
- </then>
- <else>
- <dirname property="srcdir" file="${test.srcs}"/>
- <basename property="srcs" file="${test.srcs}"/>
- </else>
- </if>
- <scalacfork
- destdir=""
- compilerpathref="locker.compiler.path"
- srcpath="${srcdir}"
- params="-Xprint-pos -Yide-debug"
- srcdir="${srcdir}"
- jvmargs="${scalacfork.jvmargs}">
- <include name="${srcs}"/>
- <compilationpath refid="test.positions.sub.build.path"/>
- </scalacfork>
- </target>
-
- <target name="test.positions.tests.sub">
- <foreach target="test.positions.sub"
- inheritAll="true"
- inheritRefs="true"
- param="test.srcs">
- <path>
- <fileset dir="${test.tests.srcs}" includes="*.scala"/>
- <dirset dir="${test.tests.srcs}">
- <include name="*"/>
- </dirset>
- </path>
- </foreach>
- </target>
-
<!-- ===========================================================================
VISUALIZATION
============================================================================ -->
diff --git a/src/compiler/scala/reflect/reify/utils/Extractors.scala b/src/compiler/scala/reflect/reify/utils/Extractors.scala
index d57188bf6e..7338df1f72 100644
--- a/src/compiler/scala/reflect/reify/utils/Extractors.scala
+++ b/src/compiler/scala/reflect/reify/utils/Extractors.scala
@@ -164,51 +164,30 @@ trait Extractors {
}
}
- object FreeDef {
- def unapply(tree: Tree): Option[(Tree, TermName, Tree, Long, String)] = tree match {
- case FreeTermDef(uref, name, binding, flags, origin) =>
- Some((uref, name, binding, flags, origin))
- case FreeTypeDef(uref, name, binding, flags, origin) =>
- Some((uref, name, binding, flags, origin))
- case _ =>
- None
- }
- }
-
- object FreeTermDef {
- def unapply(tree: Tree): Option[(Tree, TermName, Tree, Long, String)] = tree match {
- case
- ValDef(_, name, _, Apply(
- Select(Select(uref1 @ Ident(_), build1), newFreeTerm),
- List(
- _,
- _,
- Apply(Select(Select(uref2 @ Ident(_), build2), flagsFromBits), List(Literal(Constant(flags: Long)))),
- Literal(Constant(origin: String)))))
- if uref1.name == nme.UNIVERSE_SHORT && build1 == nme.build && newFreeTerm == nme.newFreeTerm &&
- uref2.name == nme.UNIVERSE_SHORT && build2 == nme.build && flagsFromBits == nme.flagsFromBits =>
- Some((uref1, name, reifyBinding(tree), flags, origin))
- case _ =>
- None
- }
- }
-
- object FreeTypeDef {
- def unapply(tree: Tree): Option[(Tree, TermName, Tree, Long, String)] = tree match {
- case
- ValDef(_, name, _, Apply(
- Select(Select(uref1 @ Ident(_), build1), newFreeType),
- List(
- _,
- Apply(Select(Select(uref2 @ Ident(_), build2), flagsFromBits), List(Literal(Constant(flags: Long)))),
- Literal(Constant(origin: String)))))
- if uref1.name == nme.UNIVERSE_SHORT && build1 == nme.build && newFreeType == nme.newFreeType &&
- uref2.name == nme.UNIVERSE_SHORT && build2 == nme.build && flagsFromBits == nme.flagsFromBits =>
- Some((uref1, name, reifyBinding(tree), flags, origin))
- case _ =>
- None
+ sealed abstract class FreeDefExtractor(acceptTerms: Boolean, acceptTypes: Boolean) {
+ def unapply(tree: Tree): Option[(Tree, TermName, Tree, Long, String)] = {
+ def acceptFreeTermFactory(name: Name) = {
+ (acceptTerms && name == nme.newFreeTerm) ||
+ (acceptTypes && name == nme.newFreeType)
+ }
+ tree match {
+ case
+ ValDef(_, name, _, Apply(
+ Select(Select(uref1 @ Ident(_), build1), freeTermFactory),
+ _ :+
+ Apply(Select(Select(uref2 @ Ident(_), build2), flagsFromBits), List(Literal(Constant(flags: Long)))) :+
+ Literal(Constant(origin: String))))
+ if uref1.name == nme.UNIVERSE_SHORT && build1 == nme.build && acceptFreeTermFactory(freeTermFactory) &&
+ uref2.name == nme.UNIVERSE_SHORT && build2 == nme.build && flagsFromBits == nme.flagsFromBits =>
+ Some((uref1, name, reifyBinding(tree), flags, origin))
+ case _ =>
+ None
+ }
}
}
+ object FreeDef extends FreeDefExtractor(acceptTerms = true, acceptTypes = true)
+ object FreeTermDef extends FreeDefExtractor(acceptTerms = true, acceptTypes = false)
+ object FreeTypeDef extends FreeDefExtractor(acceptTerms = false, acceptTypes = true)
object FreeRef {
def unapply(tree: Tree): Option[(Tree, TermName)] = tree match {
diff --git a/src/compiler/scala/tools/nsc/backend/icode/Members.scala b/src/compiler/scala/tools/nsc/backend/icode/Members.scala
index e471f4256b..0a18adcf4f 100644
--- a/src/compiler/scala/tools/nsc/backend/icode/Members.scala
+++ b/src/compiler/scala/tools/nsc/backend/icode/Members.scala
@@ -172,6 +172,7 @@ trait Members {
var returnType: TypeKind = _
var recursive: Boolean = false
var bytecodeHasEHs = false // set by ICodeReader only, used by Inliner to prevent inlining (SI-6188)
+ var bytecodeHasInvokeDynamic = false // set by ICodeReader only, used by Inliner to prevent inlining until we have proper invoke dynamic support
/** local variables and method parameters */
var locals: List[Local] = Nil
diff --git a/src/compiler/scala/tools/nsc/backend/icode/Opcodes.scala b/src/compiler/scala/tools/nsc/backend/icode/Opcodes.scala
index d8aac8e9db..ff118be3c4 100644
--- a/src/compiler/scala/tools/nsc/backend/icode/Opcodes.scala
+++ b/src/compiler/scala/tools/nsc/backend/icode/Opcodes.scala
@@ -394,6 +394,25 @@ trait Opcodes { self: ICodes =>
override def category = mthdsCat
}
+
+ /**
+ * A place holder entry that allows us to parse class files with invoke dynamic
+ * instructions. Because the compiler doesn't yet really understand the
+ * behavior of invokeDynamic, this op acts as a poison pill. Any attempt to analyze
+ * this instruction will cause a failure. The only optimization that
+ * should ever look at non-Scala generated icode is the inliner, and it
+ * has been modified to not examine any method with invokeDynamic
+ * instructions. So if this poison pill ever causes problems then
+ * there's been a serious misunderstanding
+ */
+ // TODO do the real thing
+ case class INVOKE_DYNAMIC(poolEntry: Char) extends Instruction {
+ private def error = sys.error("INVOKE_DYNAMIC is not fully implemented and should not be analyzed")
+ override def consumed = error
+ override def produced = error
+ override def producedTypes = error
+ override def category = error
+ }
case class BOX(boxType: TypeKind) extends Instruction {
assert(boxType.isValueType && (boxType ne UNIT)) // documentation
diff --git a/src/compiler/scala/tools/nsc/backend/jvm/GenASM.scala b/src/compiler/scala/tools/nsc/backend/jvm/GenASM.scala
index 78fb109b42..0c098edf98 100644
--- a/src/compiler/scala/tools/nsc/backend/jvm/GenASM.scala
+++ b/src/compiler/scala/tools/nsc/backend/jvm/GenASM.scala
@@ -2251,16 +2251,16 @@ abstract class GenASM extends SubComponent with BytecodeWriters with GenJVMASM {
// info calls so that types are up to date; erasure may add lateINTERFACE to traits
hostSymbol.info ; methodOwner.info
- def isInterfaceCall(sym: Symbol) = (
- sym.isInterface && methodOwner != ObjectClass
+ def needsInterfaceCall(sym: Symbol) = (
+ sym.isInterface
|| sym.isJavaDefined && sym.isNonBottomSubClass(ClassfileAnnotationClass)
)
// whether to reference the type of the receiver or
- // the type of the method owner (if not an interface!)
+ // the type of the method owner
val useMethodOwner = (
style != Dynamic
- || !isInterfaceCall(hostSymbol) && isAccessibleFrom(methodOwner, siteSymbol)
|| hostSymbol.isBottomClass
+ || methodOwner == ObjectClass
)
val receiver = if (useMethodOwner) methodOwner else hostSymbol
val jowner = javaName(receiver)
@@ -2283,11 +2283,11 @@ abstract class GenASM extends SubComponent with BytecodeWriters with GenJVMASM {
}
style match {
- case Static(true) => dbg("invokespecial"); jcode.invokespecial (jowner, jname, jtype)
- case Static(false) => dbg("invokestatic"); jcode.invokestatic (jowner, jname, jtype)
- case Dynamic if isInterfaceCall(receiver) => dbg("invokinterface"); jcode.invokeinterface(jowner, jname, jtype)
- case Dynamic => dbg("invokevirtual"); jcode.invokevirtual (jowner, jname, jtype)
- case SuperCall(_) =>
+ case Static(true) => dbg("invokespecial"); jcode.invokespecial (jowner, jname, jtype)
+ case Static(false) => dbg("invokestatic"); jcode.invokestatic (jowner, jname, jtype)
+ case Dynamic if needsInterfaceCall(receiver) => dbg("invokinterface"); jcode.invokeinterface(jowner, jname, jtype)
+ case Dynamic => dbg("invokevirtual"); jcode.invokevirtual (jowner, jname, jtype)
+ case SuperCall(_) =>
dbg("invokespecial")
jcode.invokespecial(jowner, jname, jtype)
initModule()
diff --git a/src/compiler/scala/tools/nsc/backend/opt/Inliners.scala b/src/compiler/scala/tools/nsc/backend/opt/Inliners.scala
index 555c79e75e..557ef925a7 100644
--- a/src/compiler/scala/tools/nsc/backend/opt/Inliners.scala
+++ b/src/compiler/scala/tools/nsc/backend/opt/Inliners.scala
@@ -958,6 +958,7 @@ abstract class Inliners extends SubComponent {
if(isInlineForbidden) { rs ::= "is annotated @noinline" }
if(inc.isSynchronized) { rs ::= "is synchronized method" }
if(inc.m.bytecodeHasEHs) { rs ::= "bytecode contains exception handlers / finally clause" } // SI-6188
+ if(inc.m.bytecodeHasInvokeDynamic) { rs ::= "bytecode contains invoke dynamic" }
if(rs.isEmpty) null else rs.mkString("", ", and ", "")
}
diff --git a/src/compiler/scala/tools/nsc/javac/JavaParsers.scala b/src/compiler/scala/tools/nsc/javac/JavaParsers.scala
index cf40fe90fa..f1b1d1a9a7 100644
--- a/src/compiler/scala/tools/nsc/javac/JavaParsers.scala
+++ b/src/compiler/scala/tools/nsc/javac/JavaParsers.scala
@@ -755,13 +755,7 @@ trait JavaParsers extends ast.parser.ParsersCommon with JavaScanners {
val pos = in.currentPos
val name = identForType()
val (statics, body) = typeBody(AT, name)
- def getValueMethodType(tree: Tree) = tree match {
- case DefDef(_, nme.value, _, _, tpt, _) => Some(tpt.duplicate)
- case _ => None
- }
- var templ = makeTemplate(annotationParents, body)
- for (stat <- templ.body; tpt <- getValueMethodType(stat))
- templ = makeTemplate(annotationParents, makeConstructor(List(tpt)) :: templ.body)
+ val templ = makeTemplate(annotationParents, body)
addCompanionObject(statics, atPos(pos) {
ClassDef(mods, name, List(), templ)
})
diff --git a/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala b/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala
index 1206748b24..879320c016 100644
--- a/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala
+++ b/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala
@@ -136,10 +136,13 @@ abstract class ClassfileParser {
(in.nextByte.toInt: @switch) match {
case CONSTANT_UTF8 | CONSTANT_UNICODE =>
in.skip(in.nextChar)
- case CONSTANT_CLASS | CONSTANT_STRING =>
+ case CONSTANT_CLASS | CONSTANT_STRING | CONSTANT_METHODTYPE=>
in.skip(2)
+ case CONSTANT_METHODHANDLE =>
+ in.skip(3)
case CONSTANT_FIELDREF | CONSTANT_METHODREF | CONSTANT_INTFMETHODREF
- | CONSTANT_NAMEANDTYPE | CONSTANT_INTEGER | CONSTANT_FLOAT =>
+ | CONSTANT_NAMEANDTYPE | CONSTANT_INTEGER | CONSTANT_FLOAT
+ | CONSTANT_INVOKEDYNAMIC =>
in.skip(4)
case CONSTANT_LONG | CONSTANT_DOUBLE =>
in.skip(8)
diff --git a/src/compiler/scala/tools/nsc/symtab/classfile/ICodeReader.scala b/src/compiler/scala/tools/nsc/symtab/classfile/ICodeReader.scala
index 599823b408..80a810703c 100644
--- a/src/compiler/scala/tools/nsc/symtab/classfile/ICodeReader.scala
+++ b/src/compiler/scala/tools/nsc/symtab/classfile/ICodeReader.scala
@@ -501,6 +501,13 @@ abstract class ICodeReader extends ClassfileParser {
code.emit(UNBOX(toTypeKind(m.info.resultType)))
else
code.emit(CALL_METHOD(m, Static(onInstance = false)))
+ case JVM.invokedynamic =>
+ // TODO, this is just a place holder. A real implementation must parse the class constant entry
+ debuglog("Found JVM invokedynamic instructionm, inserting place holder ICode INVOKE_DYNAMIC.")
+ containsInvokeDynamic = true
+ val poolEntry = in.nextChar
+ in.skip(2)
+ code.emit(INVOKE_DYNAMIC(poolEntry))
case JVM.new_ =>
code.emit(NEW(REFERENCE(pool.getClassSymbol(in.nextChar))))
@@ -639,6 +646,7 @@ abstract class ICodeReader extends ClassfileParser {
var containsDUPX = false
var containsNEW = false
var containsEHs = false
+ var containsInvokeDynamic = false
def emit(i: Instruction) {
instrs += ((pc, i))
@@ -657,6 +665,7 @@ abstract class ICodeReader extends ClassfileParser {
val code = new Code(method)
method.setCode(code)
method.bytecodeHasEHs = containsEHs
+ method.bytecodeHasInvokeDynamic = containsInvokeDynamic
var bb = code.startBlock
def makeBasicBlocks: mutable.Map[Int, BasicBlock] =
diff --git a/src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala b/src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala
index 124dd6c995..367825c251 100644
--- a/src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala
+++ b/src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala
@@ -41,26 +41,24 @@ abstract class ExplicitOuter extends InfoTransform
private def isInner(clazz: Symbol) =
!clazz.isPackageClass && !clazz.outerClass.isStaticOwner
- private def haveSameOuter(parent: Type, clazz: Symbol) = parent match {
- case TypeRef(pre, sym, _) =>
- val owner = clazz.owner
+ private def haveSameOuter(parent: Type, clazz: Symbol) = {
+ val owner = clazz.owner
+ val parentSym = parent.typeSymbol
- //println(s"have same outer $parent $clazz $sym ${sym.owner} $owner $pre")
-
- sym.isClass && owner.isClass &&
- (owner isSubClass sym.owner) &&
- owner.thisType =:= pre
-
- case _ => false
+ parentSym.isClass && owner.isClass &&
+ (owner isSubClass parentSym.owner) &&
+ owner.thisType =:= parent.prefix
}
/** Does given clazz define an outer field? */
def hasOuterField(clazz: Symbol) = {
- val parents = clazz.info.parents
+ val parent = clazz.info.firstParent
- isInner(clazz) && !clazz.isTrait && {
- parents.isEmpty || !haveSameOuter(parents.head, clazz)
- }
+ // space optimization: inherit the $outer pointer from the parent class if
+ // we know that it will point to the correct instance.
+ def canReuseParentOuterField = !parent.typeSymbol.isJavaDefined && haveSameOuter(parent, clazz)
+
+ isInner(clazz) && !clazz.isTrait && !canReuseParentOuterField
}
private def outerField(clazz: Symbol): Symbol = {
@@ -100,6 +98,29 @@ abstract class ExplicitOuter extends InfoTransform
sym setInfo clazz.outerClass.thisType
}
+ /**
+ * Will the outer accessor of the `clazz` subsume the outer accessor of
+ * `mixin`?
+ *
+ * This arises when an inner object mixes in its companion trait.
+ *
+ * {{{
+ * class C {
+ * trait T { C.this } // C$T$$$outer$ : C
+ * object T extends T { C.this } // C$T$$$outer$ : C.this.type
+ * }
+ * }}}
+ *
+ * See SI-7242.
+ }}
+ */
+ private def skipMixinOuterAccessor(clazz: Symbol, mixin: Symbol) = {
+ // Reliant on the current scheme for name expansion, the expanded name
+ // of the outer accessors in a trait and its companion object are the same.
+ // If the assumption is one day falsified, run/t7424.scala will let us know.
+ clazz.fullName == mixin.fullName
+ }
+
/** <p>
* The type transformation method:
* </p>
@@ -162,10 +183,14 @@ abstract class ExplicitOuter extends InfoTransform
for (mc <- clazz.mixinClasses) {
val mixinOuterAcc: Symbol = exitingExplicitOuter(outerAccessor(mc))
if (mixinOuterAcc != NoSymbol) {
- if (decls1 eq decls) decls1 = decls.cloneScope
- val newAcc = mixinOuterAcc.cloneSymbol(clazz, mixinOuterAcc.flags & ~DEFERRED)
- newAcc setInfo (clazz.thisType memberType mixinOuterAcc)
- decls1 enter newAcc
+ if (skipMixinOuterAccessor(clazz, mc))
+ debuglog(s"Reusing outer accessor symbol of $clazz for the mixin outer accessor of $mc")
+ else {
+ if (decls1 eq decls) decls1 = decls.cloneScope
+ val newAcc = mixinOuterAcc.cloneSymbol(clazz, mixinOuterAcc.flags & ~DEFERRED)
+ newAcc setInfo (clazz.thisType memberType mixinOuterAcc)
+ decls1 enter newAcc
+ }
}
}
}
@@ -370,6 +395,7 @@ abstract class ExplicitOuter extends InfoTransform
val outerAcc = outerAccessor(mixinClass) overridingSymbol currentClass
def mixinPrefix = (currentClass.thisType baseType mixinClass).prefix
assert(outerAcc != NoSymbol, "No outer accessor for inner mixin " + mixinClass + " in " + currentClass)
+ assert(outerAcc.alternatives.size == 1, s"Multiple outer accessors match inner mixin $mixinClass in $currentClass : ${outerAcc.alternatives.map(_.defString)}")
// I added the mixinPrefix.typeArgs.nonEmpty condition to address the
// crash in SI-4970. I feel quite sure this can be improved.
val path = (
@@ -404,7 +430,7 @@ abstract class ExplicitOuter extends InfoTransform
}
if (!currentClass.isTrait)
for (mc <- currentClass.mixinClasses)
- if (outerAccessor(mc) != NoSymbol)
+ if (outerAccessor(mc) != NoSymbol && !skipMixinOuterAccessor(currentClass, mc))
newDefs += mixinOuterAccessorDef(mc)
}
}
diff --git a/src/compiler/scala/tools/nsc/transform/UnCurry.scala b/src/compiler/scala/tools/nsc/transform/UnCurry.scala
index 8fd1df7cea..11bd0665b1 100644
--- a/src/compiler/scala/tools/nsc/transform/UnCurry.scala
+++ b/src/compiler/scala/tools/nsc/transform/UnCurry.scala
@@ -347,10 +347,14 @@ abstract class UnCurry extends InfoTransform
}
else {
log(s"Argument '$arg' at line ${arg.pos.safeLine} is $formal from ${fun.fullName}")
+ def canUseDirectly(recv: Tree) = (
+ recv.tpe.typeSymbol.isSubClass(FunctionClass(0))
+ && treeInfo.isExprSafeToInline(recv)
+ )
arg match {
// don't add a thunk for by-name argument if argument already is an application of
// a Function0. We can then remove the application and use the existing Function0.
- case Apply(Select(recv, nme.apply), Nil) if recv.tpe.typeSymbol isSubClass FunctionClass(0) =>
+ case Apply(Select(recv, nme.apply), Nil) if canUseDirectly(recv) =>
recv
case _ =>
newFunction0(arg)
diff --git a/src/compiler/scala/tools/nsc/transform/patmat/Logic.scala b/src/compiler/scala/tools/nsc/transform/patmat/Logic.scala
index 0371df3b10..92b7700c04 100644
--- a/src/compiler/scala/tools/nsc/transform/patmat/Logic.scala
+++ b/src/compiler/scala/tools/nsc/transform/patmat/Logic.scala
@@ -573,6 +573,7 @@ trait ScalaLogic extends Interface with Logic with TreeAndTypeAnalysis {
assert(tp.isInstanceOf[SingletonType])
val toString = tp match {
case ConstantType(c) => c.escapedStringValue
+ case _ if tp.typeSymbol.isModuleClass => tp.typeSymbol.name.toString
case _ => tp.toString
}
Const.unique(tp, new ValueConst(tp, tp.widen, toString))
diff --git a/src/compiler/scala/tools/nsc/transform/patmat/MatchOptimization.scala b/src/compiler/scala/tools/nsc/transform/patmat/MatchOptimization.scala
index 125e9a3b65..31b04d0bd6 100644
--- a/src/compiler/scala/tools/nsc/transform/patmat/MatchOptimization.scala
+++ b/src/compiler/scala/tools/nsc/transform/patmat/MatchOptimization.scala
@@ -15,9 +15,9 @@ import scala.reflect.internal.util.Position
/** Optimize and analyze matches based on their TreeMaker-representation.
*
* The patmat translation doesn't rely on this, so it could be disabled in principle.
- *
- * TODO: split out match analysis
+ * - well, not quite: the backend crashes if we emit duplicates in switches (e.g. SI-7290)
*/
+// TODO: split out match analysis
trait MatchOptimization extends MatchTreeMaking with MatchAnalysis {
import global._
import global.definitions._
@@ -435,7 +435,7 @@ trait MatchOptimization extends MatchTreeMaking with MatchAnalysis {
case SwitchableTreeMaker(pattern) :: GuardAndBodyTreeMakers(guard, body) =>
Some(CaseDef(pattern, guard, body))
// alternatives
- case AlternativesTreeMaker(_, altss, _) :: GuardAndBodyTreeMakers(guard, body) if alternativesSupported =>
+ case AlternativesTreeMaker(_, altss, pos) :: GuardAndBodyTreeMakers(guard, body) if alternativesSupported =>
val switchableAlts = altss map {
case SwitchableTreeMaker(pattern) :: Nil =>
Some(pattern)
@@ -445,7 +445,17 @@ trait MatchOptimization extends MatchTreeMaking with MatchAnalysis {
// succeed if they were all switchable
sequence(switchableAlts) map { switchableAlts =>
- CaseDef(Alternative(switchableAlts), guard, body)
+ def extractConst(t: Tree) = t match {
+ case Literal(const) => const
+ case _ => t
+ }
+ // SI-7290 Discard duplicate alternatives that would crash the backend
+ val distinctAlts = distinctBy(switchableAlts)(extractConst)
+ if (distinctAlts.size < switchableAlts.size) {
+ val duplicated = switchableAlts.groupBy(extractConst).flatMap(_._2.drop(1).take(1)) // report the first duplicated
+ global.currentUnit.warning(pos, s"Pattern contains duplicate alternatives: ${duplicated.mkString(", ")}")
+ }
+ CaseDef(Alternative(distinctAlts), guard, body)
}
case _ =>
// debug.patmat("can't emit switch for "+ makers)
diff --git a/src/compiler/scala/tools/nsc/typechecker/NamesDefaults.scala b/src/compiler/scala/tools/nsc/typechecker/NamesDefaults.scala
index d5ecb687b0..6921f8ce27 100644
--- a/src/compiler/scala/tools/nsc/typechecker/NamesDefaults.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/NamesDefaults.scala
@@ -499,7 +499,7 @@ trait NamesDefaults { self: Analyzer =>
// disable conforms as a view...
val errsBefore = reporter.ERROR.count
try typer.silent { tpr =>
- val res = tpr.typed(arg, subst(paramtpe))
+ val res = tpr.typed(arg.duplicate, subst(paramtpe))
// better warning for SI-5044: if `silent` was not actually silent give a hint to the user
// [H]: the reason why `silent` is not silent is because the cyclic reference exception is
// thrown in a context completely different from `context` here. The exception happens while
diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
index 1f03a80008..7436a244bd 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
@@ -1332,8 +1332,7 @@ trait Typers extends Adaptations with Tags {
def adaptToMemberWithArgs(tree: Tree, qual: Tree, name: Name, mode: Mode, reportAmbiguous: Boolean, saveErrors: Boolean): Tree = {
def onError(reportError: => Tree): Tree = context.tree match {
case Apply(tree1, args) if (tree1 eq tree) && args.nonEmpty =>
- ( silent (_.typedArgs(args, mode))
- map (_.asInstanceOf[List[Tree]])
+ ( silent (_.typedArgs(args.map(_.duplicate), mode))
filter (xs => !(xs exists (_.isErrorTyped)))
map (xs => adaptToArguments(qual, name, xs, WildcardType, reportAmbiguous, saveErrors))
orElse ( _ => reportError)
@@ -4380,6 +4379,12 @@ trait Typers extends Adaptations with Tags {
treeCopy.New(tree, tpt1).setType(tp)
}
+ def functionTypeWildcard(tree: Tree, arity: Int): Type = {
+ val tp = functionType(List.fill(arity)(WildcardType), WildcardType)
+ if (tp == NoType) MaxFunctionArityError(tree)
+ tp
+ }
+
def typedEta(expr1: Tree): Tree = expr1.tpe match {
case TypeRef(_, ByNameParamClass, _) =>
val expr2 = Function(List(), expr1) setPos expr1.pos
@@ -4391,10 +4396,10 @@ trait Typers extends Adaptations with Tags {
typed1(expr2, mode, pt)
case PolyType(_, MethodType(formals, _)) =>
if (isFunctionType(pt)) expr1
- else adapt(expr1, mode, functionType(formals map (t => WildcardType), WildcardType))
+ else adapt(expr1, mode, functionTypeWildcard(expr1, formals.length))
case MethodType(formals, _) =>
if (isFunctionType(pt)) expr1
- else adapt(expr1, mode, functionType(formals map (t => WildcardType), WildcardType))
+ else adapt(expr1, mode, functionTypeWildcard(expr1, formals.length))
case ErrorType =>
expr1
case _ =>
@@ -4706,7 +4711,7 @@ trait Typers extends Adaptations with Tags {
atPos(tree.pos)(gen.convertToSelectFromType(qual, name)) match {
case EmptyTree => None
case tree1 => Some(typed1(tree1, mode, pt))
- }
+ }
}
else None
)
diff --git a/src/compiler/scala/tools/nsc/util/SimpleTracer.scala b/src/compiler/scala/tools/nsc/util/SimpleTracer.scala
index 6997dbd402..4e1cf02a6e 100644
--- a/src/compiler/scala/tools/nsc/util/SimpleTracer.scala
+++ b/src/compiler/scala/tools/nsc/util/SimpleTracer.scala
@@ -10,7 +10,7 @@ import java.io.PrintStream
* @param enabled: A condition that must be true for trace info to be produced.
*/
class SimpleTracer(out: PrintStream, enabled: Boolean = true) {
- def apply[T](msg: String)(value: T): T = {
+ def apply[T](msg: => String)(value: T): T = {
if (enabled) out.println(msg+value)
value
}
diff --git a/src/library/scala/collection/parallel/package.scala b/src/library/scala/collection/parallel/package.scala
index d91f70da75..85c620239a 100644
--- a/src/library/scala/collection/parallel/package.scala
+++ b/src/library/scala/collection/parallel/package.scala
@@ -42,11 +42,8 @@ package object parallel {
private[parallel] def outofbounds(idx: Int) = throw new IndexOutOfBoundsException(idx.toString)
private[parallel] def getTaskSupport: TaskSupport =
- if (scala.util.Properties.isJavaAtLeast("1.6")) {
- val vendor = scala.util.Properties.javaVmVendor
- if ((vendor contains "Oracle") || (vendor contains "Sun") || (vendor contains "Apple")) new ForkJoinTaskSupport
- else new ThreadPoolTaskSupport
- } else new ThreadPoolTaskSupport
+ if (scala.util.Properties.isJavaAtLeast("1.6")) new ForkJoinTaskSupport
+ else new ThreadPoolTaskSupport
val defaultTaskSupport: TaskSupport = getTaskSupport
diff --git a/src/partest/scala/tools/partest/nest/Diff.java b/src/partest/scala/tools/partest/nest/Diff.java
deleted file mode 100644
index f69fc6858b..0000000000
--- a/src/partest/scala/tools/partest/nest/Diff.java
+++ /dev/null
@@ -1,873 +0,0 @@
-
-package scala.tools.partest.nest;
-
-import java.util.Hashtable;
-
-/** A class to compare IndexedSeqs of objects. The result of comparison
- is a list of <code>change</code> objects which form an
- edit script. The objects compared are traditionally lines
- of text from two files. Comparison options such as "ignore
- whitespace" are implemented by modifying the <code>equals</code>
- and <code>hashcode</code> methods for the objects compared.
-<p>
- The basic algorithm is described in: </br>
- "An O(ND) Difference Algorithm and its Variations", Eugene Myers,
- Algorithmica Vol. 1 No. 2, 1986, p 251.
-<p>
- This class outputs different results from GNU diff 1.15 on some
- inputs. Our results are actually better (smaller change list, smaller
- total size of changes), but it would be nice to know why. Perhaps
- there is a memory overwrite bug in GNU diff 1.15.
-
- @author Stuart D. Gathman, translated from GNU diff 1.15
- Copyright (C) 2000 Business Management Systems, Inc.
-<p>
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 1, or (at your option)
- any later version.
-<p>
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-<p>
- You should have received a copy of the <a href=COPYING.txt>
- GNU General Public License</a>
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-
- */
-
-public class Diff {
-
- /** Prepare to find differences between two arrays. Each element of
- the arrays is translated to an "equivalence number" based on
- the result of <code>equals</code>. The original Object arrays
- are no longer needed for computing the differences. They will
- be needed again later to print the results of the comparison as
- an edit script, if desired.
- */
- public Diff(Object[] a,Object[] b) {
- Hashtable<Object, Integer> h = new Hashtable<Object, Integer>(a.length + b.length);
- filevec[0] = new file_data(a,h);
- filevec[1] = new file_data(b,h);
- }
-
- /** 1 more than the maximum equivalence value used for this or its
- sibling file. */
- private int equiv_max = 1;
-
- /** When set to true, the comparison uses a heuristic to speed it up.
- With this heuristic, for files with a constant small density
- of changes, the algorithm is linear in the file size. */
- public boolean heuristic = false;
-
- /** When set to true, the algorithm returns a guarranteed minimal
- set of changes. This makes things slower, sometimes much slower. */
- public boolean no_discards = false;
-
- private int[] xvec, yvec; /* IndexedSeqs being compared. */
- private int[] fdiag; /* IndexedSeq, indexed by diagonal, containing
- the X coordinate of the point furthest
- along the given diagonal in the forward
- search of the edit matrix. */
- private int[] bdiag; /* IndexedSeq, indexed by diagonal, containing
- the X coordinate of the point furthest
- along the given diagonal in the backward
- search of the edit matrix. */
- private int fdiagoff, bdiagoff;
- private final file_data[] filevec = new file_data[2];
- private int cost;
-
- /** Find the midpoint of the shortest edit script for a specified
- portion of the two files.
-
- We scan from the beginnings of the files, and simultaneously from the ends,
- doing a breadth-first search through the space of edit-sequence.
- When the two searches meet, we have found the midpoint of the shortest
- edit sequence.
-
- The value returned is the number of the diagonal on which the midpoint lies.
- The diagonal number equals the number of inserted lines minus the number
- of deleted lines (counting only lines before the midpoint).
- The edit cost is stored into COST; this is the total number of
- lines inserted or deleted (counting only lines before the midpoint).
-
- This function assumes that the first lines of the specified portions
- of the two files do not match, and likewise that the last lines do not
- match. The caller must trim matching lines from the beginning and end
- of the portions it is going to specify.
-
- Note that if we return the "wrong" diagonal value, or if
- the value of bdiag at that diagonal is "wrong",
- the worst this can do is cause suboptimal diff output.
- It cannot cause incorrect diff output. */
-
- private int diag (int xoff, int xlim, int yoff, int ylim) {
- final int[] fd = fdiag; // Give the compiler a chance.
- final int[] bd = bdiag; // Additional help for the compiler.
- final int[] xv = xvec; // Still more help for the compiler.
- final int[] yv = yvec; // And more and more . . .
- final int dmin = xoff - ylim; // Minimum valid diagonal.
- final int dmax = xlim - yoff; // Maximum valid diagonal.
- final int fmid = xoff - yoff; // Center diagonal of top-down search.
- final int bmid = xlim - ylim; // Center diagonal of bottom-up search.
- int fmin = fmid, fmax = fmid; // Limits of top-down search.
- int bmin = bmid, bmax = bmid; // Limits of bottom-up search.
- /* True if southeast corner is on an odd
- diagonal with respect to the northwest. */
- final boolean odd = (fmid - bmid & 1) != 0;
-
- fd[fdiagoff + fmid] = xoff;
- bd[bdiagoff + bmid] = xlim;
-
- for (int c = 1;; ++c)
- {
- int d; /* Active diagonal. */
- boolean big_snake = false;
-
- /* Extend the top-down search by an edit step in each diagonal. */
- if (fmin > dmin)
- fd[fdiagoff + --fmin - 1] = -1;
- else
- ++fmin;
- if (fmax < dmax)
- fd[fdiagoff + ++fmax + 1] = -1;
- else
- --fmax;
- for (d = fmax; d >= fmin; d -= 2)
- {
- int x, y, oldx, tlo = fd[fdiagoff + d - 1], thi = fd[fdiagoff + d + 1];
-
- if (tlo >= thi)
- x = tlo + 1;
- else
- x = thi;
- oldx = x;
- y = x - d;
- while (x < xlim && y < ylim && xv[x] == yv[y]) {
- ++x; ++y;
- }
- if (x - oldx > 20)
- big_snake = true;
- fd[fdiagoff + d] = x;
- if (odd && bmin <= d && d <= bmax && bd[bdiagoff + d] <= fd[fdiagoff + d])
- {
- cost = 2 * c - 1;
- return d;
- }
- }
-
- /* Similar extend the bottom-up search. */
- if (bmin > dmin)
- bd[bdiagoff + --bmin - 1] = Integer.MAX_VALUE;
- else
- ++bmin;
- if (bmax < dmax)
- bd[bdiagoff + ++bmax + 1] = Integer.MAX_VALUE;
- else
- --bmax;
- for (d = bmax; d >= bmin; d -= 2)
- {
- int x, y, oldx, tlo = bd[bdiagoff + d - 1], thi = bd[bdiagoff + d + 1];
-
- if (tlo < thi)
- x = tlo;
- else
- x = thi - 1;
- oldx = x;
- y = x - d;
- while (x > xoff && y > yoff && xv[x - 1] == yv[y - 1]) {
- --x; --y;
- }
- if (oldx - x > 20)
- big_snake = true;
- bd[bdiagoff + d] = x;
- if (!odd && fmin <= d && d <= fmax && bd[bdiagoff + d] <= fd[fdiagoff + d])
- {
- cost = 2 * c;
- return d;
- }
- }
-
- /* Heuristic: check occasionally for a diagonal that has made
- lots of progress compared with the edit distance.
- If we have any such, find the one that has made the most
- progress and return it as if it had succeeded.
-
- With this heuristic, for files with a constant small density
- of changes, the algorithm is linear in the file size. */
-
- if (c > 200 && big_snake && heuristic)
- {
- int best = 0;
- int bestpos = -1;
-
- for (d = fmax; d >= fmin; d -= 2)
- {
- int dd = d - fmid;
- if ((fd[fdiagoff + d] - xoff)*2 - dd > 12 * (c + (dd > 0 ? dd : -dd)))
- {
- if (fd[fdiagoff + d] * 2 - dd > best
- && fd[fdiagoff + d] - xoff > 20
- && fd[fdiagoff + d] - d - yoff > 20)
- {
- int k;
- int x = fd[fdiagoff + d];
-
- /* We have a good enough best diagonal;
- now insist that it end with a significant snake. */
- for (k = 1; k <= 20; k++)
- if (xvec[x - k] != yvec[x - d - k])
- break;
-
- if (k == 21)
- {
- best = fd[fdiagoff + d] * 2 - dd;
- bestpos = d;
- }
- }
- }
- }
- if (best > 0)
- {
- cost = 2 * c - 1;
- return bestpos;
- }
-
- best = 0;
- for (d = bmax; d >= bmin; d -= 2)
- {
- int dd = d - bmid;
- if ((xlim - bd[bdiagoff + d])*2 + dd > 12 * (c + (dd > 0 ? dd : -dd)))
- {
- if ((xlim - bd[bdiagoff + d]) * 2 + dd > best
- && xlim - bd[bdiagoff + d] > 20
- && ylim - (bd[bdiagoff + d] - d) > 20)
- {
- /* We have a good enough best diagonal;
- now insist that it end with a significant snake. */
- int k;
- int x = bd[bdiagoff + d];
-
- for (k = 0; k < 20; k++)
- if (xvec[x + k] != yvec[x - d + k])
- break;
- if (k == 20)
- {
- best = (xlim - bd[bdiagoff + d]) * 2 + dd;
- bestpos = d;
- }
- }
- }
- }
- if (best > 0)
- {
- cost = 2 * c - 1;
- return bestpos;
- }
- }
- }
- }
-
- /** Compare in detail contiguous subsequences of the two files
- which are known, as a whole, to match each other.
-
- The results are recorded in the IndexedSeqs filevec[N].changed_flag, by
- storing a 1 in the element for each line that is an insertion or deletion.
-
- The subsequence of file 0 is [XOFF, XLIM) and likewise for file 1.
-
- Note that XLIM, YLIM are exclusive bounds.
- All line numbers are origin-0 and discarded lines are not counted. */
-
- private void compareseq (int xoff, int xlim, int yoff, int ylim) {
- /* Slide down the bottom initial diagonal. */
- while (xoff < xlim && yoff < ylim && xvec[xoff] == yvec[yoff]) {
- ++xoff; ++yoff;
- }
- /* Slide up the top initial diagonal. */
- while (xlim > xoff && ylim > yoff && xvec[xlim - 1] == yvec[ylim - 1]) {
- --xlim; --ylim;
- }
-
- /* Handle simple cases. */
- if (xoff == xlim)
- while (yoff < ylim)
- filevec[1].changed_flag[1+filevec[1].realindexes[yoff++]] = true;
- else if (yoff == ylim)
- while (xoff < xlim)
- filevec[0].changed_flag[1+filevec[0].realindexes[xoff++]] = true;
- else
- {
- /* Find a point of correspondence in the middle of the files. */
-
- int d = diag (xoff, xlim, yoff, ylim);
- int c = cost;
- int f = fdiag[fdiagoff + d];
- int b = bdiag[bdiagoff + d];
-
- if (c == 1)
- {
- /* This should be impossible, because it implies that
- one of the two subsequences is empty,
- and that case was handled above without calling `diag'.
- Let's verify that this is true. */
- throw new IllegalArgumentException("Empty subsequence");
- }
- else
- {
- /* Use that point to split this problem into two subproblems. */
- compareseq (xoff, b, yoff, b - d);
- /* This used to use f instead of b,
- but that is incorrect!
- It is not necessarily the case that diagonal d
- has a snake from b to f. */
- compareseq (b, xlim, b - d, ylim);
- }
- }
- }
-
- /** Discard lines from one file that have no matches in the other file.
- */
-
- private void discard_confusing_lines() {
- filevec[0].discard_confusing_lines(filevec[1]);
- filevec[1].discard_confusing_lines(filevec[0]);
- }
-
- private boolean inhibit = false;
-
- /** Adjust inserts/deletes of blank lines to join changes
- as much as possible.
- */
-
- private void shift_boundaries() {
- if (inhibit)
- return;
- filevec[0].shift_boundaries(filevec[1]);
- filevec[1].shift_boundaries(filevec[0]);
- }
-
- public interface ScriptBuilder {
- /** Scan the tables of which lines are inserted and deleted,
- producing an edit script.
- @param changed0 true for lines in first file which do not match 2nd
- @param len0 number of lines in first file
- @param changed1 true for lines in 2nd file which do not match 1st
- @param len1 number of lines in 2nd file
- @return a linked list of changes - or null
- */
- public change build_script(
- boolean[] changed0,int len0,
- boolean[] changed1,int len1
- );
- }
-
- /** Scan the tables of which lines are inserted and deleted,
- producing an edit script in reverse order. */
-
- static class ReverseScript implements ScriptBuilder {
- public change build_script(
- final boolean[] changed0,int len0,
- final boolean[] changed1,int len1)
- {
- change script = null;
- int i0 = 0, i1 = 0;
- while (i0 < len0 || i1 < len1) {
- if (changed0[1+i0] || changed1[1+i1]) {
- int line0 = i0, line1 = i1;
-
- /* Find # lines changed here in each file. */
- while (changed0[1+i0]) ++i0;
- while (changed1[1+i1]) ++i1;
-
- /* Record this change. */
- script = new change(line0, line1, i0 - line0, i1 - line1, script);
- }
-
- /* We have reached lines in the two files that match each other. */
- i0++; i1++;
- }
-
- return script;
- }
- }
-
- static class ForwardScript implements ScriptBuilder {
- /** Scan the tables of which lines are inserted and deleted,
- producing an edit script in forward order. */
- public change build_script(
- final boolean[] changed0,int len0,
- final boolean[] changed1,int len1)
- {
- change script = null;
- int i0 = len0, i1 = len1;
-
- while (i0 >= 0 || i1 >= 0)
- {
- if (changed0[i0] || changed1[i1])
- {
- int line0 = i0, line1 = i1;
-
- /* Find # lines changed here in each file. */
- while (changed0[i0]) --i0;
- while (changed1[i1]) --i1;
-
- /* Record this change. */
- script = new change(i0, i1, line0 - i0, line1 - i1, script);
- }
-
- /* We have reached lines in the two files that match each other. */
- i0--; i1--;
- }
-
- return script;
- }
- }
-
- /** Standard ScriptBuilders. */
- public final static ScriptBuilder
- forwardScript = new ForwardScript(),
- reverseScript = new ReverseScript();
-
- /* Report the differences of two files. DEPTH is the current directory
- depth. */
- public final change diff_2(final boolean reverse) {
- return diff(reverse ? reverseScript : forwardScript);
- }
-
- /** Get the results of comparison as an edit script. The script
- is described by a list of changes. The standard ScriptBuilder
- implementations provide for forward and reverse edit scripts.
- Alternate implementations could, for instance, list common elements
- instead of differences.
- @param bld an object to build the script from change flags
- @return the head of a list of changes
- */
- public change diff(final ScriptBuilder bld) {
-
- /* Some lines are obviously insertions or deletions
- because they don't match anything. Detect them now,
- and avoid even thinking about them in the main comparison algorithm. */
-
- discard_confusing_lines ();
-
- /* Now do the main comparison algorithm, considering just the
- undiscarded lines. */
-
- xvec = filevec[0].undiscarded;
- yvec = filevec[1].undiscarded;
-
- int diags =
- filevec[0].nondiscarded_lines + filevec[1].nondiscarded_lines + 3;
- fdiag = new int[diags];
- fdiagoff = filevec[1].nondiscarded_lines + 1;
- bdiag = new int[diags];
- bdiagoff = filevec[1].nondiscarded_lines + 1;
-
- compareseq (0, filevec[0].nondiscarded_lines,
- 0, filevec[1].nondiscarded_lines);
- fdiag = null;
- bdiag = null;
-
- /* Modify the results slightly to make them prettier
- in cases where that can validly be done. */
-
- shift_boundaries ();
-
- /* Get the results of comparison in the form of a chain
- of `struct change's -- an edit script. */
- return bld.build_script(
- filevec[0].changed_flag,
- filevec[0].buffered_lines,
- filevec[1].changed_flag,
- filevec[1].buffered_lines
- );
-
- }
-
- /** The result of comparison is an "edit script": a chain of change objects.
- Each change represents one place where some lines are deleted
- and some are inserted.
-
- LINE0 and LINE1 are the first affected lines in the two files (origin 0).
- DELETED is the number of lines deleted here from file 0.
- INSERTED is the number of lines inserted here in file 1.
-
- If DELETED is 0 then LINE0 is the number of the line before
- which the insertion was done; vice versa for INSERTED and LINE1. */
-
- public static class change {
- /** Previous or next edit command. */
- public change link;
- /** # lines of file 1 changed here. */
- public final int inserted;
- /** # lines of file 0 changed here. */
- public final int deleted;
- /** Line number of 1st deleted line. */
- public final int line0;
- /** Line number of 1st inserted line. */
- public final int line1;
-
- /** Cons an additional entry onto the front of an edit script OLD.
- LINE0 and LINE1 are the first affected lines in the two files (origin 0).
- DELETED is the number of lines deleted here from file 0.
- INSERTED is the number of lines inserted here in file 1.
-
- If DELETED is 0 then LINE0 is the number of the line before
- which the insertion was done; vice versa for INSERTED and LINE1. */
- public change(int line0, int line1, int deleted, int inserted, change old) {
- this.line0 = line0;
- this.line1 = line1;
- this.inserted = inserted;
- this.deleted = deleted;
- this.link = old;
- //System.err.println(line0+","+line1+","+inserted+","+deleted);
- }
- }
-
- /** Data on one input file being compared.
- */
-
- class file_data {
-
- /** Allocate changed array for the results of comparison. */
- void clear() {
- /* Allocate a flag for each line of each file, saying whether that line
- is an insertion or deletion.
- Allocate an extra element, always zero, at each end of each IndexedSeq.
- */
- changed_flag = new boolean[buffered_lines + 2];
- }
-
- /** Return equiv_count[I] as the number of lines in this file
- that fall in equivalence class I.
- @return the array of equivalence class counts.
- */
- int[] equivCount() {
- int[] equiv_count = new int[equiv_max];
- for (int i = 0; i < buffered_lines; ++i)
- ++equiv_count[equivs[i]];
- return equiv_count;
- }
-
- /** Discard lines that have no matches in another file.
-
- A line which is discarded will not be considered by the actual
- comparison algorithm; it will be as if that line were not in the file.
- The file's `realindexes' table maps virtual line numbers
- (which don't count the discarded lines) into real line numbers;
- this is how the actual comparison algorithm produces results
- that are comprehensible when the discarded lines are counted.
-<p>
- When we discard a line, we also mark it as a deletion or insertion
- so that it will be printed in the output.
- @param f the other file
- */
- void discard_confusing_lines(file_data f) {
- clear();
- /* Set up table of which lines are going to be discarded. */
- final byte[] discarded = discardable(f.equivCount());
-
- /* Don't really discard the provisional lines except when they occur
- in a run of discardables, with nonprovisionals at the beginning
- and end. */
- filterDiscards(discarded);
-
- /* Actually discard the lines. */
- discard(discarded);
- }
-
- /** Mark to be discarded each line that matches no line of another file.
- If a line matches many lines, mark it as provisionally discardable.
- @see equivCount()
- @param counts The count of each equivalence number for the other file.
- @return 0=nondiscardable, 1=discardable or 2=provisionally discardable
- for each line
- */
-
- private byte[] discardable(final int[] counts) {
- final int end = buffered_lines;
- final byte[] discards = new byte[end];
- final int[] equivs = this.equivs;
- int many = 5;
- int tem = end / 64;
-
- /* Multiply MANY by approximate square root of number of lines.
- That is the threshold for provisionally discardable lines. */
- while ((tem = tem >> 2) > 0)
- many *= 2;
-
- for (int i = 0; i < end; i++)
- {
- int nmatch;
- if (equivs[i] == 0)
- continue;
- nmatch = counts[equivs[i]];
- if (nmatch == 0)
- discards[i] = 1;
- else if (nmatch > many)
- discards[i] = 2;
- }
- return discards;
- }
-
- /** Don't really discard the provisional lines except when they occur
- in a run of discardables, with nonprovisionals at the beginning
- and end. */
-
- private void filterDiscards(final byte[] discards) {
- final int end = buffered_lines;
-
- for (int i = 0; i < end; i++)
- {
- /* Cancel provisional discards not in middle of run of discards. */
- if (discards[i] == 2)
- discards[i] = 0;
- else if (discards[i] != 0)
- {
- /* We have found a nonprovisional discard. */
- int j;
- int length;
- int provisional = 0;
-
- /* Find end of this run of discardable lines.
- Count how many are provisionally discardable. */
- for (j = i; j < end; j++)
- {
- if (discards[j] == 0)
- break;
- if (discards[j] == 2)
- ++provisional;
- }
-
- /* Cancel provisional discards at end, and shrink the run. */
- while (j > i && discards[j - 1] == 2) {
- discards[--j] = 0; --provisional;
- }
-
- /* Now we have the length of a run of discardable lines
- whose first and last are not provisional. */
- length = j - i;
-
- /* If 1/4 of the lines in the run are provisional,
- cancel discarding of all provisional lines in the run. */
- if (provisional * 4 > length)
- {
- while (j > i)
- if (discards[--j] == 2)
- discards[j] = 0;
- }
- else
- {
- int consec;
- int minimum = 1;
- int tem = length / 4;
-
- /* MINIMUM is approximate square root of LENGTH/4.
- A subrun of two or more provisionals can stand
- when LENGTH is at least 16.
- A subrun of 4 or more can stand when LENGTH >= 64. */
- while ((tem = tem >> 2) > 0)
- minimum *= 2;
- minimum++;
-
- /* Cancel any subrun of MINIMUM or more provisionals
- within the larger run. */
- for (j = 0, consec = 0; j < length; j++)
- if (discards[i + j] != 2)
- consec = 0;
- else if (minimum == ++consec)
- /* Back up to start of subrun, to cancel it all. */
- j -= consec;
- else if (minimum < consec)
- discards[i + j] = 0;
-
- /* Scan from beginning of run
- until we find 3 or more nonprovisionals in a row
- or until the first nonprovisional at least 8 lines in.
- Until that point, cancel any provisionals. */
- for (j = 0, consec = 0; j < length; j++)
- {
- if (j >= 8 && discards[i + j] == 1)
- break;
- if (discards[i + j] == 2) {
- consec = 0; discards[i + j] = 0;
- }
- else if (discards[i + j] == 0)
- consec = 0;
- else
- consec++;
- if (consec == 3)
- break;
- }
-
- /* I advances to the last line of the run. */
- i += length - 1;
-
- /* Same thing, from end. */
- for (j = 0, consec = 0; j < length; j++)
- {
- if (j >= 8 && discards[i - j] == 1)
- break;
- if (discards[i - j] == 2) {
- consec = 0; discards[i - j] = 0;
- }
- else if (discards[i - j] == 0)
- consec = 0;
- else
- consec++;
- if (consec == 3)
- break;
- }
- }
- }
- }
- }
-
- /** Actually discard the lines.
- @param discards flags lines to be discarded
- */
- private void discard(final byte[] discards) {
- final int end = buffered_lines;
- int j = 0;
- for (int i = 0; i < end; ++i)
- if (no_discards || discards[i] == 0)
- {
- undiscarded[j] = equivs[i];
- realindexes[j++] = i;
- }
- else
- changed_flag[1+i] = true;
- nondiscarded_lines = j;
- }
-
- file_data(Object[] data, Hashtable<Object, Integer> h) {
- buffered_lines = data.length;
-
- equivs = new int[buffered_lines];
- undiscarded = new int[buffered_lines];
- realindexes = new int[buffered_lines];
-
- for (int i = 0; i < data.length; ++i) {
- Integer ir = h.get(data[i]);
- if (ir == null)
- h.put(data[i], new Integer(equivs[i] = equiv_max++));
- else
- equivs[i] = ir.intValue();
- }
- }
-
- /** Adjust inserts/deletes of blank lines to join changes
- as much as possible.
-
- We do something when a run of changed lines include a blank
- line at one end and have an excluded blank line at the other.
- We are free to choose which blank line is included.
- `compareseq' always chooses the one at the beginning,
- but usually it is cleaner to consider the following blank line
- to be the "change". The only exception is if the preceding blank line
- would join this change to other changes.
- @param f the file being compared against
- */
-
- void shift_boundaries(file_data f) {
- final boolean[] changed = changed_flag;
- final boolean[] other_changed = f.changed_flag;
- int i = 0;
- int j = 0;
- int i_end = buffered_lines;
- int preceding = -1;
- int other_preceding = -1;
-
- for (;;)
- {
- int start, end, other_start;
-
- /* Scan forwards to find beginning of another run of changes.
- Also keep track of the corresponding point in the other file. */
-
- while (i < i_end && !changed[1+i])
- {
- while (other_changed[1+j++])
- /* Non-corresponding lines in the other file
- will count as the preceding batch of changes. */
- other_preceding = j;
- i++;
- }
-
- if (i == i_end)
- break;
-
- start = i;
- other_start = j;
-
- for (;;)
- {
- /* Now find the end of this run of changes. */
-
- while (i < i_end && changed[1+i]) i++;
- end = i;
-
- /* If the first changed line matches the following unchanged one,
- and this run does not follow right after a previous run,
- and there are no lines deleted from the other file here,
- then classify the first changed line as unchanged
- and the following line as changed in its place. */
-
- /* You might ask, how could this run follow right after another?
- Only because the previous run was shifted here. */
-
- if (end != i_end
- && equivs[start] == equivs[end]
- && !other_changed[1+j]
- && end != i_end
- && !((preceding >= 0 && start == preceding)
- || (other_preceding >= 0
- && other_start == other_preceding)))
- {
- changed[1+end++] = true;
- changed[1+start++] = false;
- ++i;
- /* Since one line-that-matches is now before this run
- instead of after, we must advance in the other file
- to keep in synch. */
- ++j;
- }
- else
- break;
- }
-
- preceding = i;
- other_preceding = j;
- }
- }
-
- /** Number of elements (lines) in this file. */
- final int buffered_lines;
-
- /** IndexedSeq, indexed by line number, containing an equivalence code for
- each line. It is this IndexedSeq that is actually compared with that
- of another file to generate differences. */
- private final int[] equivs;
-
- /** IndexedSeq, like the previous one except that
- the elements for discarded lines have been squeezed out. */
- final int[] undiscarded;
-
- /** IndexedSeq mapping virtual line numbers (not counting discarded lines)
- to real ones (counting those lines). Both are origin-0. */
- final int[] realindexes;
-
- /** Total number of nondiscarded lines. */
- int nondiscarded_lines;
-
- /** Array, indexed by real origin-1 line number,
- containing true for a line that is an insertion or a deletion.
- The results of comparison are stored here. */
- boolean[] changed_flag;
-
- }
-}
diff --git a/src/partest/scala/tools/partest/nest/DiffPrint.java b/src/partest/scala/tools/partest/nest/DiffPrint.java
deleted file mode 100644
index 31f9a1bc79..0000000000
--- a/src/partest/scala/tools/partest/nest/DiffPrint.java
+++ /dev/null
@@ -1,606 +0,0 @@
-
-package scala.tools.partest.nest;
-
-import java.io.*;
-import java.util.Vector;
-import java.util.Date;
-//import com.objectspace.jgl.predicates.UnaryPredicate;
-
-interface UnaryPredicate {
- boolean execute(Object obj);
-}
-
-/** A simple framework for printing change lists produced by <code>Diff</code>.
- @see bmsi.util.Diff
- @author Stuart D. Gathman
- Copyright (C) 2000 Business Management Systems, Inc.
-<p>
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 1, or (at your option)
- any later version.
-<p>
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-<p>
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-public class DiffPrint {
- /** A Base class for printing edit scripts produced by Diff.
- This class divides the change list into "hunks", and calls
- <code>print_hunk</code> for each hunk. Various utility methods
- are provided as well.
- */
- public static abstract class Base {
- protected Base(Object[] a,Object[] b, Writer w) {
- outfile = new PrintWriter(w);
- file0 = a;
- file1 = b;
- }
- /** Set to ignore certain kinds of lines when printing
- an edit script. For example, ignoring blank lines or comments.
- */
- protected UnaryPredicate ignore = null;
-
- /** Set to the lines of the files being compared.
- */
- protected Object[] file0, file1;
-
- /** Divide SCRIPT into pieces by calling HUNKFUN and
- print each piece with PRINTFUN.
- Both functions take one arg, an edit script.
-
- PRINTFUN takes a subscript which belongs together (with a null
- link at the end) and prints it. */
- public void print_script(Diff.change script) {
- Diff.change next = script;
-
- while (next != null)
- {
- Diff.change t, end;
-
- /* Find a set of changes that belong together. */
- t = next;
- end = hunkfun(next);
-
- /* Disconnect them from the rest of the changes,
- making them a hunk, and remember the rest for next iteration. */
- next = end.link;
- end.link = null;
- //if (DEBUG)
- // debug_script(t);
-
- /* Print this hunk. */
- print_hunk(t);
-
- /* Reconnect the script so it will all be freed properly. */
- end.link = next;
- }
- outfile.flush();
- }
-
- /** Called with the tail of the script
- and returns the last link that belongs together with the start
- of the tail. */
-
- protected Diff.change hunkfun(Diff.change hunk) {
- return hunk;
- }
-
- protected int first0, last0, first1, last1, deletes, inserts;
- protected PrintWriter outfile;
-
- /** Look at a hunk of edit script and report the range of lines in each file
- that it applies to. HUNK is the start of the hunk, which is a chain
- of `struct change'. The first and last line numbers of file 0 are stored
- in *FIRST0 and *LAST0, and likewise for file 1 in *FIRST1 and *LAST1.
- Note that these are internal line numbers that count from 0.
-
- If no lines from file 0 are deleted, then FIRST0 is LAST0+1.
-
- Also set *DELETES nonzero if any lines of file 0 are deleted
- and set *INSERTS nonzero if any lines of file 1 are inserted.
- If only ignorable lines are inserted or deleted, both are
- set to 0. */
-
- protected void analyze_hunk(Diff.change hunk) {
- int f0, l0 = 0, f1, l1 = 0, show_from = 0, show_to = 0;
- int i;
- Diff.change next;
- boolean nontrivial = (ignore == null);
-
- show_from = show_to = 0;
-
- f0 = hunk.line0;
- f1 = hunk.line1;
-
- for (next = hunk; next != null; next = next.link)
- {
- l0 = next.line0 + next.deleted - 1;
- l1 = next.line1 + next.inserted - 1;
- show_from += next.deleted;
- show_to += next.inserted;
- for (i = next.line0; i <= l0 && ! nontrivial; i++)
- if (!ignore.execute(file0[i]))
- nontrivial = true;
- for (i = next.line1; i <= l1 && ! nontrivial; i++)
- if (!ignore.execute(file1[i]))
- nontrivial = true;
- }
-
- first0 = f0;
- last0 = l0;
- first1 = f1;
- last1 = l1;
-
- /* If all inserted or deleted lines are ignorable,
- tell the caller to ignore this hunk. */
-
- if (!nontrivial)
- show_from = show_to = 0;
-
- deletes = show_from;
- inserts = show_to;
- }
-
- /** Print the script header which identifies the files compared. */
- protected void print_header(String filea, String fileb) { }
-
- protected abstract void print_hunk(Diff.change hunk);
-
- protected void print_1_line(String pre,Object linbuf) {
- outfile.println(pre + linbuf.toString());
- }
-
- /** Print a pair of line numbers with SEPCHAR, translated for file FILE.
- If the two numbers are identical, print just one number.
-
- Args A and B are internal line numbers.
- We print the translated (real) line numbers. */
-
- protected void print_number_range (char sepchar, int a, int b) {
- /* Note: we can have B < A in the case of a range of no lines.
- In this case, we should print the line number before the range,
- which is B. */
- if (++b > ++a)
- outfile.print("" + a + sepchar + b);
- else
- outfile.print(b);
- }
-
- public static char change_letter(int inserts, int deletes) {
- if (inserts == 0)
- return 'd';
- else if (deletes == 0)
- return 'a';
- else
- return 'c';
- }
- }
-
- /** Print a change list in the standard diff format.
- */
- public static class NormalPrint extends Base {
-
- public NormalPrint(Object[] a,Object[] b, Writer w) {
- super(a,b,w);
- }
-
- /** Print a hunk of a normal diff.
- This is a contiguous portion of a complete edit script,
- describing changes in consecutive lines. */
-
- protected void print_hunk (Diff.change hunk) {
-
- /* Determine range of line numbers involved in each file. */
- analyze_hunk(hunk);
- if (deletes == 0 && inserts == 0)
- return;
-
- /* Print out the line number header for this hunk */
- print_number_range (',', first0, last0);
- outfile.print(change_letter(inserts, deletes));
- print_number_range (',', first1, last1);
- outfile.println();
-
- /* Print the lines that the first file has. */
- if (deletes != 0)
- for (int i = first0; i <= last0; i++)
- print_1_line ("< ", file0[i]);
-
- if (inserts != 0 && deletes != 0)
- outfile.println("---");
-
- /* Print the lines that the second file has. */
- if (inserts != 0)
- for (int i = first1; i <= last1; i++)
- print_1_line ("> ", file1[i]);
- }
- }
-
- /** Prints an edit script in a format suitable for input to <code>ed</code>.
- The edit script must be generated with the reverse option to
- be useful as actual <code>ed</code> input.
- */
- public static class EdPrint extends Base {
-
- public EdPrint(Object[] a,Object[] b, Writer w) {
- super(a,b,w);
- }
-
- /** Print a hunk of an ed diff */
- protected void print_hunk(Diff.change hunk) {
-
- /* Determine range of line numbers involved in each file. */
- analyze_hunk (hunk);
- if (deletes == 0 && inserts == 0)
- return;
-
- /* Print out the line number header for this hunk */
- print_number_range (',', first0, last0);
- outfile.println(change_letter(inserts, deletes));
-
- /* Print new/changed lines from second file, if needed */
- if (inserts != 0)
- {
- boolean inserting = true;
- for (int i = first1; i <= last1; i++)
- {
- /* Resume the insert, if we stopped. */
- if (! inserting)
- outfile.println(i - first1 + first0 + "a");
- inserting = true;
-
- /* If the file's line is just a dot, it would confuse `ed'.
- So output it with a double dot, and set the flag LEADING_DOT
- so that we will output another ed-command later
- to change the double dot into a single dot. */
-
- if (".".equals(file1[i]))
- {
- outfile.println("..");
- outfile.println(".");
- /* Now change that double dot to the desired single dot. */
- outfile.println(i - first1 + first0 + 1 + "s/^\\.\\././");
- inserting = false;
- }
- else
- /* Line is not `.', so output it unmodified. */
- print_1_line ("", file1[i]);
- }
-
- /* End insert mode, if we are still in it. */
- if (inserting)
- outfile.println(".");
- }
- }
- }
-
- /** Prints an edit script in context diff format. This and its
- 'unified' variation is used for source code patches.
- */
- public static class ContextPrint extends Base {
-
- protected int context = 3;
-
- public ContextPrint(Object[] a,Object[] b, Writer w) {
- super(a,b,w);
- }
-
- protected void print_context_label (String mark, File inf, String label) {
- if (label != null)
- outfile.println(mark + ' ' + label);
- else if (inf.lastModified() > 0)
- // FIXME: use DateFormat to get precise format needed.
- outfile.println(
- mark + ' ' + inf.getPath() + '\t' + new Date(inf.lastModified())
- );
- else
- /* Don't pretend that standard input is ancient. */
- outfile.println(mark + ' ' + inf.getPath());
- }
-
- public void print_header(String filea,String fileb) {
- print_context_label ("***", new File(filea), filea);
- print_context_label ("---", new File(fileb), fileb);
- }
-
- /** If function_regexp defined, search for start of function. */
- private String find_function(Object[] lines, int start) {
- return null;
- }
-
- protected void print_function(Object[] file,int start) {
- String function = find_function (file0, first0);
- if (function != null) {
- outfile.print(" ");
- outfile.print(
- (function.length() < 40) ? function : function.substring(0,40)
- );
- }
- }
-
- protected void print_hunk(Diff.change hunk) {
-
- /* Determine range of line numbers involved in each file. */
-
- analyze_hunk (hunk);
-
- if (deletes == 0 && inserts == 0)
- return;
-
- /* Include a context's width before and after. */
-
- first0 = Math.max(first0 - context, 0);
- first1 = Math.max(first1 - context, 0);
- last0 = Math.min(last0 + context, file0.length - 1);
- last1 = Math.min(last1 + context, file1.length - 1);
-
-
- outfile.print("***************");
-
- /* If we looked for and found a function this is part of,
- include its name in the header of the diff section. */
- print_function (file0, first0);
-
- outfile.println();
- outfile.print("*** ");
- print_number_range (',', first0, last0);
- outfile.println(" ****");
-
- if (deletes != 0) {
- Diff.change next = hunk;
-
- for (int i = first0; i <= last0; i++) {
- /* Skip past changes that apply (in file 0)
- only to lines before line I. */
-
- while (next != null && next.line0 + next.deleted <= i)
- next = next.link;
-
- /* Compute the marking for line I. */
-
- String prefix = " ";
- if (next != null && next.line0 <= i)
- /* The change NEXT covers this line.
- If lines were inserted here in file 1, this is "changed".
- Otherwise it is "deleted". */
- prefix = (next.inserted > 0) ? "!" : "-";
-
- print_1_line (prefix, file0[i]);
- }
- }
-
- outfile.print("--- ");
- print_number_range (',', first1, last1);
- outfile.println(" ----");
-
- if (inserts != 0) {
- Diff.change next = hunk;
-
- for (int i = first1; i <= last1; i++) {
- /* Skip past changes that apply (in file 1)
- only to lines before line I. */
-
- while (next != null && next.line1 + next.inserted <= i)
- next = next.link;
-
- /* Compute the marking for line I. */
-
- String prefix = " ";
- if (next != null && next.line1 <= i)
- /* The change NEXT covers this line.
- If lines were deleted here in file 0, this is "changed".
- Otherwise it is "inserted". */
- prefix = (next.deleted > 0) ? "!" : "+";
-
- print_1_line (prefix, file1[i]);
- }
- }
- }
- }
-
- /** Prints an edit script in context diff format. This and its
- 'unified' variation is used for source code patches.
- */
- public static class UnifiedPrint extends ContextPrint {
-
- public UnifiedPrint(Object[] a,Object[] b, Writer w) {
- super(a,b,w);
- }
-
- public void print_header(String filea,String fileb) {
- print_context_label ("---", new File(filea), filea);
- print_context_label ("+++", new File(fileb), fileb);
- }
-
- private void print_number_range (int a, int b) {
- //translate_range (file, a, b, &trans_a, &trans_b);
-
- /* Note: we can have B < A in the case of a range of no lines.
- In this case, we should print the line number before the range,
- which is B. */
- if (b < a)
- outfile.print(b + ",0");
- else
- super.print_number_range(',',a,b);
- }
-
- protected void print_hunk(Diff.change hunk) {
- /* Determine range of line numbers involved in each file. */
- analyze_hunk (hunk);
-
- if (deletes == 0 && inserts == 0)
- return;
-
- /* Include a context's width before and after. */
-
- first0 = Math.max(first0 - context, 0);
- first1 = Math.max(first1 - context, 0);
- last0 = Math.min(last0 + context, file0.length - 1);
- last1 = Math.min(last1 + context, file1.length - 1);
-
-
-
- outfile.print("@@ -");
- print_number_range (first0, last0);
- outfile.print(" +");
- print_number_range (first1, last1);
- outfile.print(" @@");
-
- /* If we looked for and found a function this is part of,
- include its name in the header of the diff section. */
- print_function(file0,first0);
-
- outfile.println();
-
- Diff.change next = hunk;
- int i = first0;
- int j = first1;
-
- while (i <= last0 || j <= last1) {
-
- /* If the line isn't a difference, output the context from file 0. */
-
- if (next == null || i < next.line0) {
- outfile.print(' ');
- print_1_line ("", file0[i++]);
- j++;
- }
- else {
- /* For each difference, first output the deleted part. */
-
- int k = next.deleted;
- while (k-- > 0) {
- outfile.print('-');
- print_1_line ("", file0[i++]);
- }
-
- /* Then output the inserted part. */
-
- k = next.inserted;
- while (k-- > 0) {
- outfile.print('+');
- print_1_line ("", file1[j++]);
- }
-
- /* We're done with this hunk, so on to the next! */
-
- next = next.link;
- }
- }
- }
- }
-
-
- /** Read a text file into an array of String. This provides basic diff
- functionality. A more advanced diff utility will use specialized
- objects to represent the text lines, with options to, for example,
- convert sequences of whitespace to a single space for comparison
- purposes.
- */
- static String[] slurp(String file) throws IOException {
- BufferedReader rdr = new BufferedReader(new FileReader(file));
- Vector<String> s = new Vector<String>();
- for (;;) {
- String line = rdr.readLine();
- if (line == null) break;
- s.addElement(line);
- }
- String[] a = new String[s.size()];
- s.copyInto(a);
- return a;
- }
-
- public static void main(String[] argv) throws IOException {
- String filea = argv[argv.length - 2];
- String fileb = argv[argv.length - 1];
- String[] a = slurp(filea);
- String[] b = slurp(fileb);
- Diff d = new Diff(a,b);
- char style = 'n';
- for (int i = 0; i < argv.length - 2; ++i) {
- String f = argv[i];
- if (f.startsWith("-")) {
- for (int j = 1; j < f.length(); ++j) {
- switch (f.charAt(j)) {
- case 'e': // Ed style
- style = 'e'; break;
- case 'c': // Context diff
- style = 'c'; break;
- case 'u':
- style = 'u'; break;
- }
- }
- }
- }
- boolean reverse = style == 'e';
- Diff.change script = d.diff_2(reverse);
- if (script == null)
- System.err.println("No differences");
- else {
- Base p;
- Writer w = new OutputStreamWriter(System.out);
- switch (style) {
- case 'e':
- p = new EdPrint(a,b,w); break;
- case 'c':
- p = new ContextPrint(a,b,w); break;
- case 'u':
- p = new UnifiedPrint(a,b,w); break;
- default:
- p = new NormalPrint(a,b,w);
- }
- p.print_header(filea,fileb);
- p.print_script(script);
- }
- }
-
- public static void doDiff(String[] argv, Writer w) throws IOException {
- String filea = argv[argv.length - 2];
- String fileb = argv[argv.length - 1];
- String[] a = slurp(filea);
- String[] b = slurp(fileb);
- Diff d = new Diff(a,b);
- char style = 'n';
- for (int i = 0; i < argv.length - 2; ++i) {
- String f = argv[i];
- if (f.startsWith("-")) {
- for (int j = 1; j < f.length(); ++j) {
- switch (f.charAt(j)) {
- case 'e': // Ed style
- style = 'e'; break;
- case 'c': // Context diff
- style = 'c'; break;
- case 'u':
- style = 'u'; break;
- }
- }
- }
- }
- boolean reverse = style == 'e';
- Diff.change script = d.diff_2(reverse);
- if (script == null)
- w.write("No differences\n");
- else {
- Base p;
- switch (style) {
- case 'e':
- p = new EdPrint(a,b,w); break;
- case 'c':
- p = new ContextPrint(a,b,w); break;
- case 'u':
- p = new UnifiedPrint(a,b,w); break;
- default:
- p = new NormalPrint(a,b,w);
- }
- p.print_header(filea,fileb);
- p.print_script(script);
- }
- }
-
-}
diff --git a/src/partest/scala/tools/partest/nest/FileManager.scala b/src/partest/scala/tools/partest/nest/FileManager.scala
index a32c56e973..23546c6511 100644
--- a/src/partest/scala/tools/partest/nest/FileManager.scala
+++ b/src/partest/scala/tools/partest/nest/FileManager.scala
@@ -17,34 +17,31 @@ import scala.collection.mutable
trait FileUtil {
/**
- * Compares two files using a Java implementation of the GNU diff
- * available at http://www.bmsi.com/java/#diff.
+ * Compares two files using difflib to produce a unified diff.
*
* @param f1 the first file to be compared
* @param f2 the second file to be compared
- * @return the text difference between the compared files
+ * @return the unified diff of the compared files or the empty string if they're equal
*/
def compareFiles(f1: File, f2: File): String = {
- val diffWriter = new StringWriter
- val args = Array(f1.getAbsolutePath(), f2.getAbsolutePath())
-
- DiffPrint.doDiff(args, diffWriter)
- val res = diffWriter.toString
- if (res startsWith "No") "" else res
+ compareContents(io.Source.fromFile(f1).getLines.toSeq, io.Source.fromFile(f2).getLines.toSeq, f1.getName, f2.getName)
}
- def compareContents(lines1: Seq[String], lines2: Seq[String]): String = {
- val xs1 = lines1.toArray[AnyRef]
- val xs2 = lines2.toArray[AnyRef]
-
- val diff = new Diff(xs1, xs2)
- val change = diff.diff_2(false)
- val writer = new StringWriter
- val p = new DiffPrint.NormalPrint(xs1, xs2, writer)
-
- p.print_script(change)
- val res = writer.toString
- if (res startsWith "No ") ""
- else res
+
+ /**
+ * Compares two lists of lines using difflib to produce a unified diff.
+ *
+ * @param origLines the first seq of lines to be compared
+ * @param newLines the second seq of lines to be compared
+ * @param origName file name to be used in unified diff for `origLines`
+ * @param newName file name to be used in unified diff for `newLines`
+ * @return the unified diff of the `origLines` and `newLines` or the empty string if they're equal
+ */
+ def compareContents(origLines: Seq[String], newLines: Seq[String], origName: String = "a", newName: String = "b"): String = {
+ import collection.JavaConverters._
+
+ val diff = difflib.DiffUtils.diff(origLines.asJava, newLines.asJava)
+ if (diff.getDeltas.isEmpty) ""
+ else difflib.DiffUtils.generateUnifiedDiff(origName, newName, origLines.asJava, diff, 1).asScala.mkString("\n")
}
}
object FileUtil extends FileUtil { }
diff --git a/src/partest/scala/tools/partest/nest/PathSettings.scala b/src/partest/scala/tools/partest/nest/PathSettings.scala
index 02651c527b..7c005b4f61 100644
--- a/src/partest/scala/tools/partest/nest/PathSettings.scala
+++ b/src/partest/scala/tools/partest/nest/PathSettings.scala
@@ -71,6 +71,9 @@ object PathSettings {
findJar(buildPackLibDir.files ++ srcLibDir.files, "scalacheck") getOrElse {
sys.error("No scalacheck jar found in '%s' or '%s'".format(buildPackLibDir, srcLibDir))
}
+
+ lazy val diffUtils: File =
+ findJar(buildPackLibDir.files, "diffutils") getOrElse sys.error(s"No diffutils.jar found in '$buildPackLibDir'.")
}
class PathSettings() {
diff --git a/src/partest/scala/tools/partest/nest/ReflectiveRunner.scala b/src/partest/scala/tools/partest/nest/ReflectiveRunner.scala
index 05cae7b238..9780e82cd9 100644
--- a/src/partest/scala/tools/partest/nest/ReflectiveRunner.scala
+++ b/src/partest/scala/tools/partest/nest/ReflectiveRunner.scala
@@ -51,10 +51,13 @@ class ReflectiveRunner {
new ConsoleFileManager
// this is a workaround for https://issues.scala-lang.org/browse/SI-5433
- // when that bug is fixed, the addition of PathSettings.srcCodeLib can be removed
+ // when that bug is fixed, the addition of PathSettings.srcCodeLib can be removed
// we hack into the classloader that will become parent classloader for scalac
// this way we ensure that reflective macro lookup will pick correct Code.lift
- val sepUrls = PathSettings.srcCodeLib.toURI.toURL :: fileManager.latestUrls
+ // it's also used to inject diffutils into the classpath when running partest from the test/partest script
+ val srcCodeLibAndDiff = List(PathSettings.srcCodeLib, PathSettings.diffUtils)
+ val sepUrls = srcCodeLibAndDiff.map(_.toURI.toURL) ::: fileManager.latestUrls
+ // this seems to be the core classloader that determines which classes can be found when running partest from the test/partest script
val sepLoader = new URLClassLoader(sepUrls.toArray, null)
if (isPartestDebug)
diff --git a/src/partest/scala/tools/partest/nest/RunnerManager.scala b/src/partest/scala/tools/partest/nest/RunnerManager.scala
index 8f28277a6c..a63a81c47b 100644
--- a/src/partest/scala/tools/partest/nest/RunnerManager.scala
+++ b/src/partest/scala/tools/partest/nest/RunnerManager.scala
@@ -78,6 +78,7 @@ class RunnerManager(kind: String, val fileManager: FileManager, params: TestRunP
val compileMgr = new CompileManager(fileManager)
fileManager.CLASSPATH += File.pathSeparator + PathSettings.scalaCheck
+ fileManager.CLASSPATH += File.pathSeparator + PathSettings.diffUtils // needed to put diffutils on test/partest's classpath
private def compareFiles(f1: File, f2: File): String =
try fileManager.compareFiles(f1, f2)
diff --git a/src/reflect/scala/reflect/internal/ClassfileConstants.scala b/src/reflect/scala/reflect/internal/ClassfileConstants.scala
index 78f7438429..faf61e5205 100644
--- a/src/reflect/scala/reflect/internal/ClassfileConstants.scala
+++ b/src/reflect/scala/reflect/internal/ClassfileConstants.scala
@@ -72,6 +72,9 @@ object ClassfileConstants {
final val CONSTANT_METHODREF = 10
final val CONSTANT_INTFMETHODREF = 11
final val CONSTANT_NAMEANDTYPE = 12
+ final val CONSTANT_METHODHANDLE = 15
+ final val CONSTANT_METHODTYPE = 16
+ final val CONSTANT_INVOKEDYNAMIC = 18
// tags describing the type of a literal in attribute values
final val BYTE_TAG = 'B'
@@ -306,7 +309,7 @@ object ClassfileConstants {
final val invokespecial = 0xb7
final val invokestatic = 0xb8
final val invokeinterface = 0xb9
- final val xxxunusedxxxx = 0xba
+ final val invokedynamic = 0xba
final val new_ = 0xbb
final val newarray = 0xbc
diff --git a/src/reflect/scala/reflect/internal/Symbols.scala b/src/reflect/scala/reflect/internal/Symbols.scala
index 037d44c540..ad7a0d45eb 100644
--- a/src/reflect/scala/reflect/internal/Symbols.scala
+++ b/src/reflect/scala/reflect/internal/Symbols.scala
@@ -2621,20 +2621,32 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
}
/** change name by appending $$<fully-qualified-name-of-class `base`>
- * Do the same for any accessed symbols or setters/getters
+ * Do the same for any accessed symbols or setters/getters.
+ * If the accessor to be renamed is overriding a base symbol, enter
+ * a cloned symbol with the original name but without ACCESSOR flag.
*/
override def expandName(base: Symbol) {
- if (!hasFlag(EXPANDEDNAME)) {
- setFlag(EXPANDEDNAME)
- if (hasAccessorFlag && !isDeferred) {
- accessed.expandName(base)
- }
- else if (hasGetter) {
- getter(owner).expandName(base)
- setter(owner).expandName(base)
- }
- name = nme.expandedName(name.toTermName, base)
+ def expand(sym: Symbol) {
+ if ((sym eq NoSymbol) || (sym hasFlag EXPANDEDNAME)) () // skip
+ else sym setFlag EXPANDEDNAME setName nme.expandedName(sym.name.toTermName, base)
+ }
+ def cloneAndExpand(accessor: Symbol) {
+ val clone = accessor.cloneSymbol(accessor.owner, (accessor.flags | ARTIFACT) & ~ACCESSOR)
+ expand(accessor)
+ log(s"Expanded overriding accessor to $accessor, but cloned $clone to preserve override")
+ accessor.owner.info.decls enter clone
+ }
+ def expandAccessor(accessor: Symbol) {
+ if (accessor.isOverridingSymbol) cloneAndExpand(accessor) else expand(accessor)
+ }
+ if (hasAccessorFlag && !isDeferred) {
+ expand(accessed)
+ }
+ else if (hasGetter) {
+ expandAccessor(getter(owner))
+ expandAccessor(setter(owner))
}
+ expand(this)
}
}
implicit val TermSymbolTag = ClassTag[TermSymbol](classOf[TermSymbol])
diff --git a/src/reflect/scala/reflect/internal/Types.scala b/src/reflect/scala/reflect/internal/Types.scala
index d6eeb68452..611873efc0 100644
--- a/src/reflect/scala/reflect/internal/Types.scala
+++ b/src/reflect/scala/reflect/internal/Types.scala
@@ -3760,10 +3760,11 @@ trait Types
if (tp.isTrivial) tp
else if (tp.prefix.typeSymbol isNonBottomSubClass owner) {
val widened = tp match {
- case _: ConstantType => tp // Java enum constants: don't widen to the enum type!
- case _ => tp.widen // C.X.type widens to C.this.X.type, otherwise `tp asSeenFrom (pre, C)` has no effect.
+ case _: ConstantType => tp // Java enum constants: don't widen to the enum type!
+ case _ => tp.widen // C.X.type widens to C.this.X.type, otherwise `tp asSeenFrom (pre, C)` has no effect.
}
- widened asSeenFrom (pre, tp.typeSymbol.owner)
+ val memType = widened asSeenFrom (pre, tp.typeSymbol.owner)
+ if (tp eq widened) memType else memType.narrow
}
else loop(tp.prefix) memberType tp.typeSymbol
diff --git a/src/reflect/scala/reflect/internal/util/Collections.scala b/src/reflect/scala/reflect/internal/util/Collections.scala
index 63b7f73386..d6fca9d186 100644
--- a/src/reflect/scala/reflect/internal/util/Collections.scala
+++ b/src/reflect/scala/reflect/internal/util/Collections.scala
@@ -76,6 +76,19 @@ trait Collections {
lb.toList
}
+ final def distinctBy[A, B](xs: List[A])(f: A => B): List[A] = {
+ val buf = new ListBuffer[A]
+ val seen = mutable.Set[B]()
+ xs foreach { x =>
+ val y = f(x)
+ if (!seen(y)) {
+ buf += x
+ seen += y
+ }
+ }
+ buf.toList
+ }
+
@tailrec final def flattensToEmpty(xss: Seq[Seq[_]]): Boolean = {
xss.isEmpty || xss.head.isEmpty && flattensToEmpty(xss.tail)
}
diff --git a/src/reflect/scala/reflect/runtime/JavaUniverse.scala b/src/reflect/scala/reflect/runtime/JavaUniverse.scala
index a130013398..4d90afcdc3 100644
--- a/src/reflect/scala/reflect/runtime/JavaUniverse.scala
+++ b/src/reflect/scala/reflect/runtime/JavaUniverse.scala
@@ -14,7 +14,7 @@ class JavaUniverse extends internal.SymbolTable with ReflectSetup with runtime.S
lazy val settings = new Settings
private val isLogging = sys.props contains "scala.debug.reflect"
- def log(msg: => AnyRef): Unit = if (isLogging) Console.err.println("[reflect] " + msg)
+ def log(msg: => AnyRef): Unit = if (isLogging) Console.err.println("[reflect] " + msg)
type TreeCopier = InternalTreeCopierOps
def newStrictTreeCopier: TreeCopier = new StrictTreeCopier
diff --git a/src/scaladoc/scala/tools/nsc/doc/base/comment/Body.scala b/src/scaladoc/scala/tools/nsc/doc/base/comment/Body.scala
index 2a07547de2..ac5fec80b3 100755
--- a/src/scaladoc/scala/tools/nsc/doc/base/comment/Body.scala
+++ b/src/scaladoc/scala/tools/nsc/doc/base/comment/Body.scala
@@ -73,16 +73,20 @@ object EntityLink {
def unapply(el: EntityLink): Option[(Inline, LinkTo)] = Some((el.title, el.link))
}
final case class HtmlTag(data: String) extends Inline {
- def canClose(open: HtmlTag) = {
- open.data.stripPrefix("<") == data.stripPrefix("</")
+ private val Pattern = """(?ms)\A<(/?)(.*?)[\s>].*\z""".r
+ private val (isEnd, tagName) = data match {
+ case Pattern(s1, s2) =>
+ (! s1.isEmpty, Some(s2.toLowerCase))
+ case _ =>
+ (false, None)
}
- def close = {
- if (data.indexOf("</") == -1)
- Some(HtmlTag("</" + data.stripPrefix("<")))
- else
- None
+ def canClose(open: HtmlTag) = {
+ isEnd && tagName == open.tagName
}
+
+ private val TagsNotToClose = Set("br", "img")
+ def close = tagName collect { case name if !TagsNotToClose(name) => HtmlTag(s"</$name>") }
}
/** The summary of a comment, usually its first sentence. There must be exactly one summary per body. */
diff --git a/src/scaladoc/scala/tools/nsc/doc/html/SyntaxHigh.scala b/src/scaladoc/scala/tools/nsc/doc/html/SyntaxHigh.scala
index 5781e680dd..348ea97c5b 100644
--- a/src/scaladoc/scala/tools/nsc/doc/html/SyntaxHigh.scala
+++ b/src/scaladoc/scala/tools/nsc/doc/html/SyntaxHigh.scala
@@ -6,6 +6,7 @@
package scala.tools.nsc.doc.html
import scala.xml.NodeSeq
+import scala.annotation.tailrec
/** Highlight the syntax of Scala code appearing in a `{{{` wiki block
* (see method `HtmlPage.blockToHtml`).
@@ -209,9 +210,9 @@ private[html] object SyntaxHigh {
out.toString
}
- def parse(pre: String, i: Int): Int = {
+ @tailrec def parse(pre: String, i: Int): Unit = {
out append pre
- if (i == buf.length) return i
+ if (i == buf.length) return
buf(i) match {
case '\n' =>
parse("\n", i+1)
@@ -277,7 +278,6 @@ private[html] object SyntaxHigh {
} else
parse(buf(i).toChar.toString, i+1)
}
- i
}
parse("", 0)
diff --git a/starr.number b/starr.number
new file mode 100644
index 0000000000..7e6e869eaf
--- /dev/null
+++ b/starr.number
@@ -0,0 +1 @@
+starr.version=2.10.1 \ No newline at end of file
diff --git a/test/files/jvm/t7253.check b/test/files/jvm/t7253.check
new file mode 100644
index 0000000000..43f53aba12
--- /dev/null
+++ b/test/files/jvm/t7253.check
@@ -0,0 +1 @@
+bytecode identical
diff --git a/test/files/jvm/t7253/Base_1.scala b/test/files/jvm/t7253/Base_1.scala
new file mode 100644
index 0000000000..a531ebb69d
--- /dev/null
+++ b/test/files/jvm/t7253/Base_1.scala
@@ -0,0 +1,5 @@
+trait A { def f(): Int }
+trait B1 extends A
+abstract class B2 extends A
+class B3 extends A { def f(): Int = 1 }
+class B4 extends B3
diff --git a/test/files/jvm/t7253/JavaClient_1.java b/test/files/jvm/t7253/JavaClient_1.java
new file mode 100644
index 0000000000..43475de2f5
--- /dev/null
+++ b/test/files/jvm/t7253/JavaClient_1.java
@@ -0,0 +1,9 @@
+public class JavaClient_1 {
+ int foo() {
+ ((A) null).f();
+ ((B1) null).f();
+ ((B2) null).f();
+ ((B3) null).f();
+ return ((B4) null).f();
+ }
+}
diff --git a/test/files/jvm/t7253/ScalaClient_1.scala b/test/files/jvm/t7253/ScalaClient_1.scala
new file mode 100644
index 0000000000..d244b326a8
--- /dev/null
+++ b/test/files/jvm/t7253/ScalaClient_1.scala
@@ -0,0 +1,9 @@
+class ScalaClient_1 {
+ def foo() = {
+ (null: A).f()
+ (null: B1).f()
+ (null: B2).f()
+ (null: B3).f()
+ (null: B4).f()
+ }
+}
diff --git a/test/files/jvm/t7253/test.scala b/test/files/jvm/t7253/test.scala
new file mode 100644
index 0000000000..7fe08e8813
--- /dev/null
+++ b/test/files/jvm/t7253/test.scala
@@ -0,0 +1,28 @@
+import scala.tools.partest.BytecodeTest
+
+import scala.tools.nsc.util.JavaClassPath
+import java.io.InputStream
+import scala.tools.asm
+import asm.ClassReader
+import asm.tree.{ClassNode, InsnList}
+import scala.collection.JavaConverters._
+
+object Test extends BytecodeTest {
+ import instructions._
+
+ def show: Unit = {
+ val instrBaseSeqs = Seq("ScalaClient_1", "JavaClient_1") map (name => instructions.fromMethod(getMethod(loadClassNode(name), "foo")))
+ val instrSeqs = instrBaseSeqs map (_ filter isInvoke)
+ cmpInstructions(instrSeqs(0), instrSeqs(1))
+ }
+
+ def cmpInstructions(isa: List[Instruction], isb: List[Instruction]) = {
+ if (isa == isb) println("bytecode identical")
+ else diffInstructions(isa, isb)
+ }
+
+ def isInvoke(node: Instruction): Boolean = {
+ val opcode = node.opcode
+ (opcode == "INVOKEVIRTUAL") || (opcode == "INVOKEINTERFACE")
+ }
+}
diff --git a/test/files/neg/t7285.check b/test/files/neg/t7285.check
new file mode 100644
index 0000000000..a38772bead
--- /dev/null
+++ b/test/files/neg/t7285.check
@@ -0,0 +1,15 @@
+t7285.scala:15: warning: match may not be exhaustive.
+It would fail on the following input: (Up, Down)
+ (d1, d2) match {
+ ^
+t7285.scala:33: warning: match may not be exhaustive.
+It would fail on the following input: Down
+ (d1) match {
+ ^
+t7285.scala:51: warning: match may not be exhaustive.
+It would fail on the following input: (Up, Down)
+ (d1, d2) match {
+ ^
+error: No warnings can be incurred under -Xfatal-warnings.
+three warnings found
+one error found
diff --git a/test/files/neg/t7285.flags b/test/files/neg/t7285.flags
new file mode 100644
index 0000000000..e8fb65d50c
--- /dev/null
+++ b/test/files/neg/t7285.flags
@@ -0,0 +1 @@
+-Xfatal-warnings \ No newline at end of file
diff --git a/test/files/neg/t7285.scala b/test/files/neg/t7285.scala
new file mode 100644
index 0000000000..14121d92b1
--- /dev/null
+++ b/test/files/neg/t7285.scala
@@ -0,0 +1,55 @@
+sealed abstract class Base
+
+
+object Test1 {
+ sealed abstract class Base
+
+ object Base {
+ case object Down extends Base {
+ }
+
+ case object Up extends Base {
+ }
+
+ (d1: Base, d2: Base) =>
+ (d1, d2) match {
+ case (Up, Up) | (Down, Down) => false
+ case (Down, Up) => true
+ }
+ }
+}
+
+object Test2 {
+ sealed abstract class Base
+
+ object Base {
+ case object Down extends Base {
+ }
+
+ case object Up extends Base {
+ }
+
+ (d1: Base, d2: Base) =>
+ (d1) match {
+ case Test2.Base.Up => false
+ }
+ }
+}
+
+
+object Test4 {
+ sealed abstract class Base
+
+ object Base {
+ case object Down extends Base
+
+ case object Up extends Base
+ }
+
+ import Test4.Base._
+ (d1: Base, d2: Base) =>
+ (d1, d2) match {
+ case (Up, Up) | (Down, Down) => false
+ case (Down, Test4.Base.Up) => true
+ }
+}
diff --git a/test/files/neg/t7290.check b/test/files/neg/t7290.check
new file mode 100644
index 0000000000..ad2d0e25b0
--- /dev/null
+++ b/test/files/neg/t7290.check
@@ -0,0 +1,12 @@
+t7290.scala:4: warning: Pattern contains duplicate alternatives: 0
+ case 0 | 0 => 0
+ ^
+t7290.scala:5: warning: Pattern contains duplicate alternatives: 2, 3
+ case 2 | 2 | 2 | 3 | 2 | 3 => 0
+ ^
+t7290.scala:6: warning: Pattern contains duplicate alternatives: 4
+ case 4 | (_ @ 4) => 0
+ ^
+error: No warnings can be incurred under -Xfatal-warnings.
+three warnings found
+one error found
diff --git a/test/files/neg/t7290.flags b/test/files/neg/t7290.flags
new file mode 100644
index 0000000000..e8fb65d50c
--- /dev/null
+++ b/test/files/neg/t7290.flags
@@ -0,0 +1 @@
+-Xfatal-warnings \ No newline at end of file
diff --git a/test/files/neg/t7290.scala b/test/files/neg/t7290.scala
new file mode 100644
index 0000000000..b9db7f7e8a
--- /dev/null
+++ b/test/files/neg/t7290.scala
@@ -0,0 +1,10 @@
+object Test extends App {
+ val y = (0: Int) match {
+ case 1 => 1
+ case 0 | 0 => 0
+ case 2 | 2 | 2 | 3 | 2 | 3 => 0
+ case 4 | (_ @ 4) => 0
+ case _ => -1
+ }
+ assert(y == 0, y)
+}
diff --git a/test/files/neg/t7299.check b/test/files/neg/t7299.check
new file mode 100644
index 0000000000..74340c4841
--- /dev/null
+++ b/test/files/neg/t7299.check
@@ -0,0 +1,7 @@
+t7299.scala:4: error: implementation restricts functions to 22 parameters
+ val eta1 = f _
+ ^
+t7299.scala:5: error: implementation restricts functions to 22 parameters
+ val eta2 = g[Any] _
+ ^
+two errors found
diff --git a/test/files/neg/t7299.scala b/test/files/neg/t7299.scala
new file mode 100644
index 0000000000..f3aae5ce5d
--- /dev/null
+++ b/test/files/neg/t7299.scala
@@ -0,0 +1,6 @@
+object Test {
+ def f(a1: Int, a2: Int, a3: Int, a4: Int, a5: Int, a6: Int, a7: Int, a8: Int, a9: Int, a10: Int, a11: Int, a12: Int, a13: Int, a14: Int, a15: Int, a16: Int, a17: Int, a18: Int, a19: Int, a20: Int, a21: Int, a22: Int, a23: Int) = 0
+ def g[A](a1: Int, a2: Int, a3: Int, a4: Int, a5: Int, a6: Int, a7: Int, a8: Int, a9: Int, a10: Int, a11: Int, a12: Int, a13: Int, a14: Int, a15: Int, a16: Int, a17: Int, a18: Int, a19: Int, a20: Int, a21: Int, a22: Int, a23: Int) = 0
+ val eta1 = f _
+ val eta2 = g[Any] _
+}
diff --git a/test/files/pos/t6210.flags b/test/files/pos/t6210.flags
new file mode 100644
index 0000000000..e8fb65d50c
--- /dev/null
+++ b/test/files/pos/t6210.flags
@@ -0,0 +1 @@
+-Xfatal-warnings \ No newline at end of file
diff --git a/test/files/pos/t6210.scala b/test/files/pos/t6210.scala
new file mode 100644
index 0000000000..1ce8493872
--- /dev/null
+++ b/test/files/pos/t6210.scala
@@ -0,0 +1,21 @@
+abstract sealed trait AST
+abstract sealed trait AExpr extends AST
+case class AAssign(name: String, v: AExpr) extends AExpr
+case class AConstBool(v: Boolean) extends AExpr
+
+trait Ty {}
+case class TInt() extends Ty
+case class TBool() extends Ty
+
+object Foo {
+ def checkExpr(ast: AExpr): Ty = {
+ var astTy:Ty = ast match {
+ case AAssign(nm: String, v:AExpr) => TBool()
+
+ case AConstBool(v: Boolean) => TBool()
+
+ case _ => throw new Exception(s"Unhandled case check(ast: ${ast.getClass})")
+ }
+ astTy
+ }
+}
diff --git a/test/files/pos/t6921.scala b/test/files/pos/t6921.scala
new file mode 100644
index 0000000000..36e70e5d2c
--- /dev/null
+++ b/test/files/pos/t6921.scala
@@ -0,0 +1,11 @@
+class Message(messageType: String, reason: Option[String])
+
+class ReproForSI6921 {
+
+ private[this] var reason = ""
+
+ def decideElection = {
+ val explanation = None
+ new Message("", reason = explanation)
+ }
+}
diff --git a/test/files/pos/t7239.scala b/test/files/pos/t7239.scala
new file mode 100644
index 0000000000..16e9d00f17
--- /dev/null
+++ b/test/files/pos/t7239.scala
@@ -0,0 +1,38 @@
+object Test {
+ def BrokenMethod(): HasFilter[(Int, String)] = ???
+
+ trait HasFilter[B] {
+ def filter(p: B => Boolean) = ???
+ }
+
+ trait HasWithFilter {
+ def withFilter = ???
+ }
+
+ object addWithFilter {
+ trait NoImplicit
+ implicit def enrich(v: Any)
+ (implicit F0: NoImplicit): HasWithFilter = ???
+ }
+
+ BrokenMethod().withFilter(_ => true) // okay
+ BrokenMethod().filter(_ => true) // okay
+
+ locally {
+ import addWithFilter._
+ BrokenMethod().withFilter((_: (Int, String)) => true) // okay
+ }
+
+ locally {
+ import addWithFilter._
+ // adaptToMemberWithArgs sets the type of the tree `x`
+ // to ErrorType (while in silent mode, so the error is not
+ // reported. Later, when the fallback from `withFilter`
+ // to `filter` is attempted, the closure is taken to have
+ // have the type `<error> => Boolean`, which conforms to
+ // `(B => Boolean)`. Only later during pickling does the
+ // defensive check for erroneous types in the tree pick up
+ // the problem.
+ BrokenMethod().withFilter(x => true) // erroneous or inaccessible type.
+ }
+}
diff --git a/test/files/pos/t7285a.flags b/test/files/pos/t7285a.flags
new file mode 100644
index 0000000000..e8fb65d50c
--- /dev/null
+++ b/test/files/pos/t7285a.flags
@@ -0,0 +1 @@
+-Xfatal-warnings \ No newline at end of file
diff --git a/test/files/pos/t7285a.scala b/test/files/pos/t7285a.scala
new file mode 100644
index 0000000000..34e79c741b
--- /dev/null
+++ b/test/files/pos/t7285a.scala
@@ -0,0 +1,83 @@
+sealed abstract class Base
+
+object Test {
+ case object Up extends Base
+
+ def foo(d1: Base) =
+ d1 match {
+ case Up =>
+ }
+
+ // Sealed subtype: ModuleTypeRef <empty>.this.Test.Up.type
+ // Pattern: UniqueThisType Test.this.type
+}
+
+
+object Test1 {
+ sealed abstract class Base
+
+ object Base {
+ case object Down extends Base {
+ }
+
+ case object Up extends Base {
+ }
+
+ (d1: Base, d2: Base) =>
+ (d1, d2) match {
+ case (Up, Up) | (Down, Down) => false
+ case (Down, Up) => true
+ case (Up, Down) => false
+ }
+ }
+}
+
+object Test2 {
+ sealed abstract class Base
+
+ object Base {
+ case object Down extends Base {
+ }
+
+ case object Up extends Base {
+ }
+
+ (d1: Base, d2: Base) =>
+ (d1) match {
+ case Up | Down => false
+ }
+ }
+}
+
+object Test3 {
+ sealed abstract class Base
+
+ object Base {
+ case object Down extends Base
+
+ (d1: Base, d2: Base) =>
+ (d1, d2) match {
+ case (Down, Down) => false
+ }
+ }
+}
+
+object Test4 {
+ sealed abstract class Base
+
+ object Base {
+ case object Down extends Base {
+ }
+
+ case object Up extends Base {
+ }
+
+ }
+ import Test4.Base._
+ (d1: Base, d2: Base) =>
+ (d1, d2) match {
+ case (Up, Up) | (Down, Down) => false
+ case (Down, Test4.Base.Up) => true
+ case (Up, Down) => false
+ }
+}
diff --git a/test/files/run/classfile-format-51.scala b/test/files/run/classfile-format-51.scala
new file mode 100644
index 0000000000..9b1e612f4f
--- /dev/null
+++ b/test/files/run/classfile-format-51.scala
@@ -0,0 +1,126 @@
+import java.io.{File, FileOutputStream}
+
+import scala.tools.nsc.settings.ScalaVersion
+import scala.tools.partest._
+import scala.tools.asm
+import asm.{AnnotationVisitor, ClassWriter, FieldVisitor, Handle, MethodVisitor, Opcodes}
+import Opcodes._
+
+// This test ensures that we can read JDK 7 (classfile format 51) files, including those
+// with invokeDynamic instructions and associated constant pool entries
+// to do that it first uses ASM to generate a class called DynamicInvoker. Then
+// 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
+// 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
+object Test extends DirectTest {
+ override def extraSettings: String = "-optimise -usejavacp -d " + testOutput.path + " -cp " + testOutput.path
+
+ def generateClass() {
+ val invokerClassName = "DynamicInvoker"
+ val bootstrapMethodName = "bootstrap"
+ val bootStrapMethodType = "(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;"
+ val targetMethodName = "target"
+ val targetMethodType = "()Ljava/lang/String;"
+
+ val cw = new ClassWriter(0)
+ cw.visit(V1_7, ACC_PUBLIC + ACC_SUPER, invokerClassName, null, "java/lang/Object", null)
+
+ val constructor = cw.visitMethod(ACC_PUBLIC, "<init>", "()V", null, null)
+ constructor.visitCode()
+ constructor.visitVarInsn(ALOAD, 0)
+ constructor.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "<init>", "()V")
+ constructor.visitInsn(RETURN)
+ constructor.visitMaxs(1, 1)
+ constructor.visitEnd()
+
+ val target = cw.visitMethod(ACC_PUBLIC + ACC_STATIC, targetMethodName, targetMethodType, null, null)
+ target.visitCode()
+ target.visitLdcInsn("hello")
+ target.visitInsn(ARETURN)
+ target.visitMaxs(1, 1)
+ target.visitEnd()
+
+ val bootstrap = cw.visitMethod(ACC_PUBLIC + ACC_STATIC, bootstrapMethodName, bootStrapMethodType, null, null)
+ bootstrap.visitCode()
+// val lookup = MethodHandles.lookup();
+ bootstrap.visitMethodInsn(INVOKESTATIC, "java/lang/invoke/MethodHandles", "lookup", "()Ljava/lang/invoke/MethodHandles$Lookup;")
+ bootstrap.visitVarInsn(ASTORE, 3) // lookup
+
+// val clazz = lookup.lookupClass();
+ bootstrap.visitVarInsn(ALOAD, 3) // lookup
+ bootstrap.visitMethodInsn(INVOKEVIRTUAL, "java/lang/invoke/MethodHandles$Lookup", "lookupClass", "()Ljava/lang/Class;")
+ bootstrap.visitVarInsn(ASTORE, 4) // clazz
+
+// val methodType = MethodType.fromMethodDescriptorString("()Ljava/lang/String, clazz.getClassLoader()")
+ bootstrap.visitLdcInsn("()Ljava/lang/String;")
+ bootstrap.visitVarInsn(ALOAD, 4) // CLAZZ
+ bootstrap.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Class", "getClassLoader", "()Ljava/lang/ClassLoader;")
+ bootstrap.visitMethodInsn(INVOKESTATIC, "java/lang/invoke/MethodType", "fromMethodDescriptorString", "(Ljava/lang/String;Ljava/lang/ClassLoader;)Ljava/lang/invoke/MethodType;")
+ bootstrap.visitVarInsn(ASTORE, 5) // methodType
+
+// val methodHandle = lookup.findStatic(thisClass, "target", methodType)
+ bootstrap.visitVarInsn(ALOAD, 3) // lookup
+ bootstrap.visitVarInsn(ALOAD, 4) // clazz
+ bootstrap.visitLdcInsn("target")
+ bootstrap.visitVarInsn(ALOAD, 5) // methodType
+ bootstrap.visitMethodInsn(INVOKEVIRTUAL, "java/lang/invoke/MethodHandles$Lookup", "findStatic", "(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/MethodHandle;")
+ bootstrap.visitVarInsn(ASTORE, 6) // methodHandle
+
+// new ConstantCallSite(methodHandle)
+ bootstrap.visitTypeInsn(NEW, "java/lang/invoke/ConstantCallSite")
+ bootstrap.visitInsn(DUP)
+ bootstrap.visitVarInsn(ALOAD, 6) // methodHandle
+ bootstrap.visitMethodInsn(INVOKESPECIAL, "java/lang/invoke/ConstantCallSite", "<init>", "(Ljava/lang/invoke/MethodHandle;)V")
+ bootstrap.visitInsn(ARETURN)
+ bootstrap.visitMaxs(4,7)
+ bootstrap.visitEnd()
+
+ val test = cw.visitMethod(ACC_PUBLIC + ACC_FINAL, "test", s"()Ljava/lang/String;", null, null)
+ test.visitCode()
+ val bootstrapHandle = new Handle(H_INVOKESTATIC, invokerClassName, bootstrapMethodName, bootStrapMethodType)
+ test.visitInvokeDynamicInsn("invoke", targetMethodType, bootstrapHandle)
+ test.visitInsn(ARETURN)
+ test.visitMaxs(1, 1)
+ test.visitEnd()
+
+ cw.visitEnd()
+ val bytes = cw.toByteArray()
+
+ val fos = new FileOutputStream(new File(s"${testOutput.path}/$invokerClassName.class"))
+ try
+ fos write bytes
+ finally
+ fos.close()
+
+ }
+
+ def code =
+"""
+object Driver {
+ val invoker = new DynamicInvoker()
+ println(invoker.test())
+}
+"""
+
+ override def show(): Unit = {
+ // redirect err to out, for logging
+ val prevErr = System.err
+ System.setErr(System.out)
+ try {
+ // this test is only valid under JDK 1.7+
+ // cheat a little by using 'ScalaVersion' because it can parse java versions just as well
+ val requiredJavaVersion = ScalaVersion("1.7")
+ val executingJavaVersion = ScalaVersion(System.getProperty("java.specification.version"))
+ if (executingJavaVersion >= requiredJavaVersion) {
+ generateClass()
+ compile()
+ }
+ }
+ finally
+ System.setErr(prevErr)
+ }
+}
diff --git a/test/files/run/inline-ex-handlers.check b/test/files/run/inline-ex-handlers.check
index abcc8bf42d..7c885d2cc9 100644
--- a/test/files/run/inline-ex-handlers.check
+++ b/test/files/run/inline-ex-handlers.check
@@ -1,427 +1,492 @@
-172c172
-< locals: value x$1, value x1
----
-> locals: value x$1, value x1, variable boxed1
-174c174
-< blocks: [1,2,3,4]
----
-> blocks: [1,3,4]
-186a187,188
-> 92 STORE_LOCAL(variable boxed1)
-> 92 LOAD_LOCAL(variable boxed1)
-195,197d196
-< 92 JUMP 2
-<
-< 2:
-247c246
-< blocks: [1,2,3,4,5,6,7,8,11,12,13,14,15,16,17,18]
----
-> blocks: [1,2,3,4,5,6,8,11,12,13,14,15,16,17,18]
-258,260d256
-< 92 JUMP 7
-<
-< 7:
-391c387
-< locals: value args, variable result, value ex6, value x4, value x5, value message, value x
----
-> locals: value args, variable result, value ex6, value x4, value x5, value x
-393c389
-< blocks: [1,2,3,4,5,8,10,11,13]
----
-> blocks: [1,2,3,5,8,10,11,13,14]
-417c413,422
-< 103 THROW(MyException)
----
-> ? STORE_LOCAL(value ex6)
-> ? JUMP 14
->
-> 14:
-> 101 LOAD_LOCAL(value ex6)
-> 101 STORE_LOCAL(value x4)
-> 101 SCOPE_ENTER value x4
-> 106 LOAD_LOCAL(value x4)
-> 106 IS_INSTANCE REF(class MyException)
-> 106 CZJUMP (BOOL)NE ? 5 : 8
-430,432d434
-< 101 JUMP 4
-<
-< 4:
-442,445d443
-< 106 LOAD_LOCAL(value x5)
-< 106 CALL_METHOD MyException.message (dynamic)
-< 106 STORE_LOCAL(value message)
-< 106 SCOPE_ENTER value message
-447c445,446
-< 106 LOAD_LOCAL(value message)
----
-> ? LOAD_LOCAL(value x5)
-> 106 CALL_METHOD MyException.message (dynamic)
-519c518
-< blocks: [1,2,3,4,6,7,9,10]
----
-> blocks: [1,3,4,6,7,9,10,11,12,13]
-548c547,552
-< 306 THROW(MyException)
----
-> ? JUMP 11
->
-> 11:
-> ? LOAD_LOCAL(variable monitor4)
-> 305 MONITOR_EXIT
-> ? JUMP 12
-554c558
-< ? THROW(Throwable)
----
-> ? JUMP 12
-560c564,571
-< ? THROW(Throwable)
----
-> ? STORE_LOCAL(value t)
-> ? JUMP 13
->
-> 12:
-> ? LOAD_LOCAL(variable monitor3)
-> 304 MONITOR_EXIT
-> ? STORE_LOCAL(value t)
-> ? JUMP 13
-574c585
-< 310 JUMP 2
----
-> 300 RETURN(UNIT)
-576c587,596
-< 2:
----
-> 13:
-> 310 LOAD_MODULE object Predef
-> 310 CALL_PRIMITIVE(StartConcat)
-> 310 CONSTANT("Caught crash: ")
-> 310 CALL_PRIMITIVE(StringConcat(REF(class String)))
-> 310 LOAD_LOCAL(value t)
-> 310 CALL_METHOD java.lang.Throwable.toString (dynamic)
-> 310 CALL_PRIMITIVE(StringConcat(REF(class String)))
-> 310 CALL_PRIMITIVE(EndConcat)
-> 310 CALL_METHOD scala.Predef.println (dynamic)
-584c604
-< catch (Throwable) in ArrayBuffer(7, 9, 10) starting at: 6
----
-> catch (Throwable) in ArrayBuffer(7, 9, 10, 11) starting at: 6
-587c607
-< catch (Throwable) in ArrayBuffer(4, 6, 7, 9, 10) starting at: 3
----
-> catch (Throwable) in ArrayBuffer(4, 6, 7, 9, 10, 11, 12) starting at: 3
-619c639
-< blocks: [1,3,4,5,6,8,9]
----
-> blocks: [1,3,4,5,6,8,9,10,11]
-643c663,669
-< 78 THROW(IllegalArgumentException)
----
-> ? STORE_LOCAL(value e)
-> ? JUMP 10
->
-> 10:
-> 81 LOAD_LOCAL(value e)
-> ? STORE_LOCAL(variable exc1)
-> ? JUMP 11
-669c695,696
-< 81 THROW(Exception)
----
-> ? STORE_LOCAL(variable exc1)
-> ? JUMP 11
-685a713,725
-> 11:
-> 83 LOAD_MODULE object Predef
-> 83 CONSTANT("finally")
-> 83 CALL_METHOD scala.Predef.println (dynamic)
-> 84 LOAD_LOCAL(variable result)
-> 84 CONSTANT(1)
-> 84 CALL_PRIMITIVE(Arithmetic(SUB,INT))
-> 84 CONSTANT(2)
-> 84 CALL_PRIMITIVE(Arithmetic(DIV,INT))
-> 84 STORE_LOCAL(variable result)
-> 84 LOAD_LOCAL(variable exc1)
-> 84 THROW(Throwable)
->
-691c731
-< catch (<none>) in ArrayBuffer(4, 5, 6, 8) starting at: 3
----
-> catch (<none>) in ArrayBuffer(4, 5, 6, 8, 10) starting at: 3
-715c755
-< locals: value args, variable result, value ex6, variable exc2, value x4, value x5, value message, value x, value ex6, value x4, value x5, value message, value x
----
-> locals: value args, variable result, value ex6, variable exc2, value x4, value x5, value x, value ex6, value x4, value x5, value x
-717c757
-< blocks: [1,3,4,5,6,9,13,14,15,18,20,21,23,24]
----
-> blocks: [1,3,4,5,6,9,13,14,15,18,20,21,23,24,25,26,27]
-741c781,788
-< 172 THROW(MyException)
----
-> ? STORE_LOCAL(value ex6)
-> ? JUMP 25
->
-> 25:
-> 170 LOAD_LOCAL(value ex6)
-> 170 STORE_LOCAL(value x4)
-> 170 SCOPE_ENTER value x4
-> 170 JUMP 14
-781,784d827
-< 175 LOAD_LOCAL(value x5)
-< 175 CALL_METHOD MyException.message (dynamic)
-< 175 STORE_LOCAL(value message)
-< 175 SCOPE_ENTER value message
-786c829,830
-< 176 LOAD_LOCAL(value message)
----
-> ? LOAD_LOCAL(value x5)
-> 176 CALL_METHOD MyException.message (dynamic)
-790c834,835
-< 177 LOAD_LOCAL(value message)
----
-> ? LOAD_LOCAL(value x5)
-> 177 CALL_METHOD MyException.message (dynamic)
-792c837,838
-< 177 THROW(MyException)
----
-> ? STORE_LOCAL(value ex6)
-> ? JUMP 26
-796c842,843
-< 170 THROW(Throwable)
----
-> ? STORE_LOCAL(value ex6)
-> ? JUMP 26
-805a853,858
-> 26:
-> 169 LOAD_LOCAL(value ex6)
-> 169 STORE_LOCAL(value x4)
-> 169 SCOPE_ENTER value x4
-> 169 JUMP 5
->
-816,819d868
-< 180 LOAD_LOCAL(value x5)
-< 180 CALL_METHOD MyException.message (dynamic)
-< 180 STORE_LOCAL(value message)
-< 180 SCOPE_ENTER value message
-821c870,871
-< 181 LOAD_LOCAL(value message)
----
-> ? LOAD_LOCAL(value x5)
-> 181 CALL_METHOD MyException.message (dynamic)
-825c875,876
-< 182 LOAD_LOCAL(value message)
----
-> ? LOAD_LOCAL(value x5)
-> 182 CALL_METHOD MyException.message (dynamic)
-827c878,879
-< 182 THROW(MyException)
----
-> ? STORE_LOCAL(variable exc2)
-> ? JUMP 27
-831c883,884
-< 169 THROW(Throwable)
----
-> ? STORE_LOCAL(variable exc2)
-> ? JUMP 27
-847a901,913
-> 27:
-> 184 LOAD_MODULE object Predef
-> 184 CONSTANT("finally")
-> 184 CALL_METHOD scala.Predef.println (dynamic)
-> 185 LOAD_LOCAL(variable result)
-> 185 CONSTANT(1)
-> 185 CALL_PRIMITIVE(Arithmetic(SUB,INT))
-> 185 CONSTANT(2)
-> 185 CALL_PRIMITIVE(Arithmetic(DIV,INT))
-> 185 STORE_LOCAL(variable result)
-> 185 LOAD_LOCAL(variable exc2)
-> 185 THROW(Throwable)
->
-853c919
-< catch (Throwable) in ArrayBuffer(13, 14, 15, 18, 20, 21, 23) starting at: 4
----
-> catch (Throwable) in ArrayBuffer(13, 14, 15, 18, 20, 21, 23, 25) starting at: 4
-856c922
-< catch (<none>) in ArrayBuffer(4, 5, 6, 9, 13, 14, 15, 18, 20, 21, 23) starting at: 3
----
-> catch (<none>) in ArrayBuffer(4, 5, 6, 9, 13, 14, 15, 18, 20, 21, 23, 25, 26) starting at: 3
-880c946
-< locals: value args, variable result, value e, value ex6, value x4, value x5, value message, value x
----
-> locals: value args, variable result, value e, value ex6, value x4, value x5, value x
-882c948
-< blocks: [1,2,3,6,7,8,11,13,14,16]
----
-> blocks: [1,2,3,6,7,8,11,13,14,16,17]
-906c972,979
-< 124 THROW(MyException)
----
-> ? STORE_LOCAL(value ex6)
-> ? JUMP 17
->
-> 17:
-> 122 LOAD_LOCAL(value ex6)
-> 122 STORE_LOCAL(value x4)
-> 122 SCOPE_ENTER value x4
-> 122 JUMP 7
-931,934d1003
-< 127 LOAD_LOCAL(value x5)
-< 127 CALL_METHOD MyException.message (dynamic)
-< 127 STORE_LOCAL(value message)
-< 127 SCOPE_ENTER value message
-936c1005,1006
-< 127 LOAD_LOCAL(value message)
----
-> ? LOAD_LOCAL(value x5)
-> 127 CALL_METHOD MyException.message (dynamic)
-965c1035
-< catch (IllegalArgumentException) in ArrayBuffer(6, 7, 8, 11, 13, 14, 16) starting at: 3
----
-> catch (IllegalArgumentException) in ArrayBuffer(6, 7, 8, 11, 13, 14, 16, 17) starting at: 3
-989c1059
-< locals: value args, variable result, value ex6, value x4, value x5, value message, value x, value e
----
-> locals: value args, variable result, value ex6, value x4, value x5, value x, value e
-991c1061
-< blocks: [1,2,3,4,5,8,12,13,14,16]
----
-> blocks: [1,2,3,5,8,12,13,14,16,17]
-1015c1085,1094
-< 148 THROW(MyException)
----
-> ? STORE_LOCAL(value ex6)
-> ? JUMP 17
->
-> 17:
-> 145 LOAD_LOCAL(value ex6)
-> 145 STORE_LOCAL(value x4)
-> 145 SCOPE_ENTER value x4
-> 154 LOAD_LOCAL(value x4)
-> 154 IS_INSTANCE REF(class MyException)
-> 154 CZJUMP (BOOL)NE ? 5 : 8
-1036,1038d1114
-< 145 JUMP 4
-<
-< 4:
-1048,1051d1123
-< 154 LOAD_LOCAL(value x5)
-< 154 CALL_METHOD MyException.message (dynamic)
-< 154 STORE_LOCAL(value message)
-< 154 SCOPE_ENTER value message
-1053c1125,1126
-< 154 LOAD_LOCAL(value message)
----
-> ? LOAD_LOCAL(value x5)
-> 154 CALL_METHOD MyException.message (dynamic)
-1270c1343
-< blocks: [1,2,3,4,5,7]
----
-> blocks: [1,2,3,4,5,7,8]
-1294c1367,1374
-< 38 THROW(IllegalArgumentException)
----
-> ? STORE_LOCAL(value e)
-> ? JUMP 8
->
-> 8:
-> 42 LOAD_MODULE object Predef
-> 42 CONSTANT("IllegalArgumentException")
-> 42 CALL_METHOD scala.Predef.println (dynamic)
-> 42 JUMP 2
-1341c1421
-< locals: value args, variable result, value ex6, value x4, value x5, value message, value x
----
-> locals: value args, variable result, value ex6, value x4, value x5, value x
-1343c1423
-< blocks: [1,2,3,4,5,8,10,11,13,14,16]
----
-> blocks: [1,2,3,5,8,10,11,13,14,16,17]
-1367c1447,1448
-< 203 THROW(MyException)
----
-> ? STORE_LOCAL(value ex6)
-> ? JUMP 17
-1387c1468,1477
-< 209 THROW(MyException)
----
-> ? STORE_LOCAL(value ex6)
-> ? JUMP 17
->
-> 17:
-> 200 LOAD_LOCAL(value ex6)
-> 200 STORE_LOCAL(value x4)
-> 200 SCOPE_ENTER value x4
-> 212 LOAD_LOCAL(value x4)
-> 212 IS_INSTANCE REF(class MyException)
-> 212 CZJUMP (BOOL)NE ? 5 : 8
-1400,1402d1489
-< 200 JUMP 4
-<
-< 4:
-1412,1415d1498
-< 212 LOAD_LOCAL(value x5)
-< 212 CALL_METHOD MyException.message (dynamic)
-< 212 STORE_LOCAL(value message)
-< 212 SCOPE_ENTER value message
-1417c1500,1501
-< 213 LOAD_LOCAL(value message)
----
-> ? LOAD_LOCAL(value x5)
-> 213 CALL_METHOD MyException.message (dynamic)
-1461c1545
-< blocks: [1,2,3,4,5,7]
----
-> blocks: [1,2,3,4,5,7,8]
-1485c1569,1570
-< 58 THROW(IllegalArgumentException)
----
-> ? STORE_LOCAL(value e)
-> ? JUMP 8
-1486a1572,1577
-> 8:
-> 62 LOAD_MODULE object Predef
-> 62 CONSTANT("RuntimeException")
-> 62 CALL_METHOD scala.Predef.println (dynamic)
-> 62 JUMP 2
->
-1534c1625
-< blocks: [1,3,4]
----
-> blocks: [1,3,4,5]
-1554c1645,1650
-< 229 THROW(MyException)
----
-> ? JUMP 5
->
-> 5:
-> ? LOAD_LOCAL(variable monitor1)
-> 228 MONITOR_EXIT
-> 228 THROW(Throwable)
-1560c1656
-< ? THROW(Throwable)
----
-> 228 THROW(Throwable)
-1588c1684
-< locals: value args, variable result, variable monitor2, variable monitorResult1
----
-> locals: value exception$1, value args, variable result, variable monitor2, variable monitorResult1
-1590c1686
-< blocks: [1,3,4]
----
-> blocks: [1,3,4,5]
-1613c1709,1717
-< 245 THROW(MyException)
----
-> ? STORE_LOCAL(value exception$1)
-> ? DROP ConcatClass
-> ? LOAD_LOCAL(value exception$1)
-> ? JUMP 5
->
-> 5:
-> ? LOAD_LOCAL(variable monitor2)
-> 244 MONITOR_EXIT
-> 244 THROW(Throwable)
-1619c1723
-< ? THROW(Throwable)
----
-> 244 THROW(Throwable)
-
+--- a
++++ b
+@@ -171,5 +171,5 @@
+ def productElement(x$1: Int (INT)): Object {
+- locals: value x$1, value x1
++ locals: value x$1, value x1, variable boxed1
+ startBlock: 1
+- blocks: [1,2,3,4]
++ blocks: [1,3,4]
+
+@@ -186,2 +186,4 @@
+ 92 LOAD_LOCAL(value x$1)
++ 92 STORE_LOCAL(variable boxed1)
++ 92 LOAD_LOCAL(variable boxed1)
+ 92 BOX INT
+@@ -194,5 +196,2 @@
+ 92 CALL_METHOD MyException.message (dynamic)
+- 92 JUMP 2
+-
+- 2:
+ 92 RETURN(REF(class Object))
+@@ -246,3 +245,3 @@
+ startBlock: 1
+- blocks: [1,2,3,4,5,6,7,8,11,12,13,14,15,16,17,18]
++ blocks: [1,2,3,4,5,6,8,11,12,13,14,15,16,17,18]
+
+@@ -257,5 +256,2 @@
+ 92 SCOPE_ENTER value x1
+- 92 JUMP 7
+-
+- 7:
+ 92 LOAD_LOCAL(value x1)
+@@ -390,5 +386,5 @@
+ def main(args: Array[String] (ARRAY[REF(class String)])): Unit {
+- locals: value args, variable result, value ex6, value x4, value x5, value message, value x
++ locals: value args, variable result, value ex6, value x4, value x5, value x
+ startBlock: 1
+- blocks: [1,2,3,4,5,8,10,11,13]
++ blocks: [1,2,3,5,8,10,11,13,14]
+
+@@ -416,4 +412,13 @@
+ 103 CALL_METHOD MyException.<init> (static-instance)
+- 103 THROW(MyException)
++ ? STORE_LOCAL(value ex6)
++ ? JUMP 14
+
++ 14:
++ 101 LOAD_LOCAL(value ex6)
++ 101 STORE_LOCAL(value x4)
++ 101 SCOPE_ENTER value x4
++ 106 LOAD_LOCAL(value x4)
++ 106 IS_INSTANCE REF(class MyException)
++ 106 CZJUMP (BOOL)NE ? 5 : 8
++
+ 13:
+@@ -429,5 +434,2 @@
+ 101 SCOPE_ENTER value x4
+- 101 JUMP 4
+-
+- 4:
+ 106 LOAD_LOCAL(value x4)
+@@ -441,8 +443,5 @@
+ 106 SCOPE_ENTER value x5
+- 106 LOAD_LOCAL(value x5)
+- 106 CALL_METHOD MyException.message (dynamic)
+- 106 STORE_LOCAL(value message)
+- 106 SCOPE_ENTER value message
+ 106 LOAD_MODULE object Predef
+- 106 LOAD_LOCAL(value message)
++ ? LOAD_LOCAL(value x5)
++ 106 CALL_METHOD MyException.message (dynamic)
+ 106 CALL_METHOD scala.Predef.println (dynamic)
+@@ -518,3 +517,3 @@
+ startBlock: 1
+- blocks: [1,2,3,4,6,7,9,10]
++ blocks: [1,3,4,6,7,9,10,11,12,13]
+
+@@ -547,4 +546,9 @@
+ 306 CALL_METHOD MyException.<init> (static-instance)
+- 306 THROW(MyException)
++ ? JUMP 11
+
++ 11:
++ ? LOAD_LOCAL(variable monitor4)
++ 305 MONITOR_EXIT
++ ? JUMP 12
++
+ 9:
+@@ -553,3 +557,3 @@
+ 305 MONITOR_EXIT
+- ? THROW(Throwable)
++ ? JUMP 12
+
+@@ -559,4 +563,11 @@
+ 304 MONITOR_EXIT
+- ? THROW(Throwable)
++ ? STORE_LOCAL(value t)
++ ? JUMP 13
+
++ 12:
++ ? LOAD_LOCAL(variable monitor3)
++ 304 MONITOR_EXIT
++ ? STORE_LOCAL(value t)
++ ? JUMP 13
++
+ 3:
+@@ -573,5 +584,14 @@
+ 310 CALL_METHOD scala.Predef.println (dynamic)
+- 310 JUMP 2
++ 300 RETURN(UNIT)
+
+- 2:
++ 13:
++ 310 LOAD_MODULE object Predef
++ 310 CALL_PRIMITIVE(StartConcat)
++ 310 CONSTANT("Caught crash: ")
++ 310 CALL_PRIMITIVE(StringConcat(REF(class String)))
++ 310 LOAD_LOCAL(value t)
++ 310 CALL_METHOD java.lang.Throwable.toString (dynamic)
++ 310 CALL_PRIMITIVE(StringConcat(REF(class String)))
++ 310 CALL_PRIMITIVE(EndConcat)
++ 310 CALL_METHOD scala.Predef.println (dynamic)
+ 300 RETURN(UNIT)
+@@ -583,6 +603,6 @@
+ with finalizer: null
+- catch (Throwable) in ArrayBuffer(7, 9, 10) starting at: 6
++ catch (Throwable) in ArrayBuffer(7, 9, 10, 11) starting at: 6
+ consisting of blocks: List(6)
+ with finalizer: null
+- catch (Throwable) in ArrayBuffer(4, 6, 7, 9, 10) starting at: 3
++ catch (Throwable) in ArrayBuffer(4, 6, 7, 9, 10, 11, 12) starting at: 3
+ consisting of blocks: List(3)
+@@ -618,3 +638,3 @@
+ startBlock: 1
+- blocks: [1,3,4,5,6,8,9]
++ blocks: [1,3,4,5,6,8,9,10,11]
+
+@@ -642,4 +662,10 @@
+ 78 CALL_METHOD java.lang.IllegalArgumentException.<init> (static-instance)
+- 78 THROW(IllegalArgumentException)
++ ? STORE_LOCAL(value e)
++ ? JUMP 10
+
++ 10:
++ 81 LOAD_LOCAL(value e)
++ ? STORE_LOCAL(variable exc1)
++ ? JUMP 11
++
+ 8:
+@@ -668,3 +694,4 @@
+ 81 LOAD_LOCAL(value e)
+- 81 THROW(Exception)
++ ? STORE_LOCAL(variable exc1)
++ ? JUMP 11
+
+@@ -685,2 +712,15 @@
+
++ 11:
++ 83 LOAD_MODULE object Predef
++ 83 CONSTANT("finally")
++ 83 CALL_METHOD scala.Predef.println (dynamic)
++ 84 LOAD_LOCAL(variable result)
++ 84 CONSTANT(1)
++ 84 CALL_PRIMITIVE(Arithmetic(SUB,INT))
++ 84 CONSTANT(2)
++ 84 CALL_PRIMITIVE(Arithmetic(DIV,INT))
++ 84 STORE_LOCAL(variable result)
++ 84 LOAD_LOCAL(variable exc1)
++ 84 THROW(Throwable)
++
+ }
+@@ -690,3 +730,3 @@
+ with finalizer: null
+- catch (<none>) in ArrayBuffer(4, 5, 6, 8) starting at: 3
++ catch (<none>) in ArrayBuffer(4, 5, 6, 8, 10) starting at: 3
+ consisting of blocks: List(3)
+@@ -714,5 +754,5 @@
+ def main(args: Array[String] (ARRAY[REF(class String)])): Unit {
+- locals: value args, variable result, value ex6, variable exc2, value x4, value x5, value message, value x, value ex6, value x4, value x5, value message, value x
++ locals: value args, variable result, value ex6, variable exc2, value x4, value x5, value x, value ex6, value x4, value x5, value x
+ startBlock: 1
+- blocks: [1,3,4,5,6,9,13,14,15,18,20,21,23,24]
++ blocks: [1,3,4,5,6,9,13,14,15,18,20,21,23,24,25,26,27]
+
+@@ -740,4 +780,11 @@
+ 172 CALL_METHOD MyException.<init> (static-instance)
+- 172 THROW(MyException)
++ ? STORE_LOCAL(value ex6)
++ ? JUMP 25
+
++ 25:
++ 170 LOAD_LOCAL(value ex6)
++ 170 STORE_LOCAL(value x4)
++ 170 SCOPE_ENTER value x4
++ 170 JUMP 14
++
+ 23:
+@@ -780,8 +827,5 @@
+ 175 SCOPE_ENTER value x5
+- 175 LOAD_LOCAL(value x5)
+- 175 CALL_METHOD MyException.message (dynamic)
+- 175 STORE_LOCAL(value message)
+- 175 SCOPE_ENTER value message
+ 176 LOAD_MODULE object Predef
+- 176 LOAD_LOCAL(value message)
++ ? LOAD_LOCAL(value x5)
++ 176 CALL_METHOD MyException.message (dynamic)
+ 176 CALL_METHOD scala.Predef.println (dynamic)
+@@ -789,5 +833,7 @@
+ 177 DUP(REF(class MyException))
+- 177 LOAD_LOCAL(value message)
++ ? LOAD_LOCAL(value x5)
++ 177 CALL_METHOD MyException.message (dynamic)
+ 177 CALL_METHOD MyException.<init> (static-instance)
+- 177 THROW(MyException)
++ ? STORE_LOCAL(value ex6)
++ ? JUMP 26
+
+@@ -795,3 +841,4 @@
+ 170 LOAD_LOCAL(value ex6)
+- 170 THROW(Throwable)
++ ? STORE_LOCAL(value ex6)
++ ? JUMP 26
+
+@@ -805,2 +852,8 @@
+
++ 26:
++ 169 LOAD_LOCAL(value ex6)
++ 169 STORE_LOCAL(value x4)
++ 169 SCOPE_ENTER value x4
++ 169 JUMP 5
++
+ 5:
+@@ -815,8 +868,5 @@
+ 180 SCOPE_ENTER value x5
+- 180 LOAD_LOCAL(value x5)
+- 180 CALL_METHOD MyException.message (dynamic)
+- 180 STORE_LOCAL(value message)
+- 180 SCOPE_ENTER value message
+ 181 LOAD_MODULE object Predef
+- 181 LOAD_LOCAL(value message)
++ ? LOAD_LOCAL(value x5)
++ 181 CALL_METHOD MyException.message (dynamic)
+ 181 CALL_METHOD scala.Predef.println (dynamic)
+@@ -824,5 +874,7 @@
+ 182 DUP(REF(class MyException))
+- 182 LOAD_LOCAL(value message)
++ ? LOAD_LOCAL(value x5)
++ 182 CALL_METHOD MyException.message (dynamic)
+ 182 CALL_METHOD MyException.<init> (static-instance)
+- 182 THROW(MyException)
++ ? STORE_LOCAL(variable exc2)
++ ? JUMP 27
+
+@@ -830,3 +882,4 @@
+ 169 LOAD_LOCAL(value ex6)
+- 169 THROW(Throwable)
++ ? STORE_LOCAL(variable exc2)
++ ? JUMP 27
+
+@@ -847,2 +900,15 @@
+
++ 27:
++ 184 LOAD_MODULE object Predef
++ 184 CONSTANT("finally")
++ 184 CALL_METHOD scala.Predef.println (dynamic)
++ 185 LOAD_LOCAL(variable result)
++ 185 CONSTANT(1)
++ 185 CALL_PRIMITIVE(Arithmetic(SUB,INT))
++ 185 CONSTANT(2)
++ 185 CALL_PRIMITIVE(Arithmetic(DIV,INT))
++ 185 STORE_LOCAL(variable result)
++ 185 LOAD_LOCAL(variable exc2)
++ 185 THROW(Throwable)
++
+ }
+@@ -852,6 +918,6 @@
+ with finalizer: null
+- catch (Throwable) in ArrayBuffer(13, 14, 15, 18, 20, 21, 23) starting at: 4
++ catch (Throwable) in ArrayBuffer(13, 14, 15, 18, 20, 21, 23, 25) starting at: 4
+ consisting of blocks: List(9, 8, 6, 5, 4)
+ with finalizer: null
+- catch (<none>) in ArrayBuffer(4, 5, 6, 9, 13, 14, 15, 18, 20, 21, 23) starting at: 3
++ catch (<none>) in ArrayBuffer(4, 5, 6, 9, 13, 14, 15, 18, 20, 21, 23, 25, 26) starting at: 3
+ consisting of blocks: List(3)
+@@ -879,5 +945,5 @@
+ def main(args: Array[String] (ARRAY[REF(class String)])): Unit {
+- locals: value args, variable result, value e, value ex6, value x4, value x5, value message, value x
++ locals: value args, variable result, value e, value ex6, value x4, value x5, value x
+ startBlock: 1
+- blocks: [1,2,3,6,7,8,11,13,14,16]
++ blocks: [1,2,3,6,7,8,11,13,14,16,17]
+
+@@ -905,4 +971,11 @@
+ 124 CALL_METHOD MyException.<init> (static-instance)
+- 124 THROW(MyException)
++ ? STORE_LOCAL(value ex6)
++ ? JUMP 17
+
++ 17:
++ 122 LOAD_LOCAL(value ex6)
++ 122 STORE_LOCAL(value x4)
++ 122 SCOPE_ENTER value x4
++ 122 JUMP 7
++
+ 16:
+@@ -930,8 +1003,5 @@
+ 127 SCOPE_ENTER value x5
+- 127 LOAD_LOCAL(value x5)
+- 127 CALL_METHOD MyException.message (dynamic)
+- 127 STORE_LOCAL(value message)
+- 127 SCOPE_ENTER value message
+ 127 LOAD_MODULE object Predef
+- 127 LOAD_LOCAL(value message)
++ ? LOAD_LOCAL(value x5)
++ 127 CALL_METHOD MyException.message (dynamic)
+ 127 CALL_METHOD scala.Predef.println (dynamic)
+@@ -964,3 +1034,3 @@
+ with finalizer: null
+- catch (IllegalArgumentException) in ArrayBuffer(6, 7, 8, 11, 13, 14, 16) starting at: 3
++ catch (IllegalArgumentException) in ArrayBuffer(6, 7, 8, 11, 13, 14, 16, 17) starting at: 3
+ consisting of blocks: List(3)
+@@ -988,5 +1058,5 @@
+ def main(args: Array[String] (ARRAY[REF(class String)])): Unit {
+- locals: value args, variable result, value ex6, value x4, value x5, value message, value x, value e
++ locals: value args, variable result, value ex6, value x4, value x5, value x, value e
+ startBlock: 1
+- blocks: [1,2,3,4,5,8,12,13,14,16]
++ blocks: [1,2,3,5,8,12,13,14,16,17]
+
+@@ -1014,4 +1084,13 @@
+ 148 CALL_METHOD MyException.<init> (static-instance)
+- 148 THROW(MyException)
++ ? STORE_LOCAL(value ex6)
++ ? JUMP 17
+
++ 17:
++ 145 LOAD_LOCAL(value ex6)
++ 145 STORE_LOCAL(value x4)
++ 145 SCOPE_ENTER value x4
++ 154 LOAD_LOCAL(value x4)
++ 154 IS_INSTANCE REF(class MyException)
++ 154 CZJUMP (BOOL)NE ? 5 : 8
++
+ 16:
+@@ -1035,5 +1114,2 @@
+ 145 SCOPE_ENTER value x4
+- 145 JUMP 4
+-
+- 4:
+ 154 LOAD_LOCAL(value x4)
+@@ -1047,8 +1123,5 @@
+ 154 SCOPE_ENTER value x5
+- 154 LOAD_LOCAL(value x5)
+- 154 CALL_METHOD MyException.message (dynamic)
+- 154 STORE_LOCAL(value message)
+- 154 SCOPE_ENTER value message
+ 154 LOAD_MODULE object Predef
+- 154 LOAD_LOCAL(value message)
++ ? LOAD_LOCAL(value x5)
++ 154 CALL_METHOD MyException.message (dynamic)
+ 154 CALL_METHOD scala.Predef.println (dynamic)
+@@ -1269,3 +1342,3 @@
+ startBlock: 1
+- blocks: [1,2,3,4,5,7]
++ blocks: [1,2,3,4,5,7,8]
+
+@@ -1293,4 +1366,11 @@
+ 38 CALL_METHOD java.lang.IllegalArgumentException.<init> (static-instance)
+- 38 THROW(IllegalArgumentException)
++ ? STORE_LOCAL(value e)
++ ? JUMP 8
+
++ 8:
++ 42 LOAD_MODULE object Predef
++ 42 CONSTANT("IllegalArgumentException")
++ 42 CALL_METHOD scala.Predef.println (dynamic)
++ 42 JUMP 2
++
+ 7:
+@@ -1340,5 +1420,5 @@
+ def main(args: Array[String] (ARRAY[REF(class String)])): Unit {
+- locals: value args, variable result, value ex6, value x4, value x5, value message, value x
++ locals: value args, variable result, value ex6, value x4, value x5, value x
+ startBlock: 1
+- blocks: [1,2,3,4,5,8,10,11,13,14,16]
++ blocks: [1,2,3,5,8,10,11,13,14,16,17]
+
+@@ -1366,3 +1446,4 @@
+ 203 CALL_METHOD MyException.<init> (static-instance)
+- 203 THROW(MyException)
++ ? STORE_LOCAL(value ex6)
++ ? JUMP 17
+
+@@ -1386,4 +1467,13 @@
+ 209 CALL_METHOD MyException.<init> (static-instance)
+- 209 THROW(MyException)
++ ? STORE_LOCAL(value ex6)
++ ? JUMP 17
+
++ 17:
++ 200 LOAD_LOCAL(value ex6)
++ 200 STORE_LOCAL(value x4)
++ 200 SCOPE_ENTER value x4
++ 212 LOAD_LOCAL(value x4)
++ 212 IS_INSTANCE REF(class MyException)
++ 212 CZJUMP (BOOL)NE ? 5 : 8
++
+ 16:
+@@ -1399,5 +1489,2 @@
+ 200 SCOPE_ENTER value x4
+- 200 JUMP 4
+-
+- 4:
+ 212 LOAD_LOCAL(value x4)
+@@ -1411,8 +1498,5 @@
+ 212 SCOPE_ENTER value x5
+- 212 LOAD_LOCAL(value x5)
+- 212 CALL_METHOD MyException.message (dynamic)
+- 212 STORE_LOCAL(value message)
+- 212 SCOPE_ENTER value message
+ 213 LOAD_MODULE object Predef
+- 213 LOAD_LOCAL(value message)
++ ? LOAD_LOCAL(value x5)
++ 213 CALL_METHOD MyException.message (dynamic)
+ 213 CALL_METHOD scala.Predef.println (dynamic)
+@@ -1460,3 +1544,3 @@
+ startBlock: 1
+- blocks: [1,2,3,4,5,7]
++ blocks: [1,2,3,4,5,7,8]
+
+@@ -1484,4 +1568,11 @@
+ 58 CALL_METHOD java.lang.IllegalArgumentException.<init> (static-instance)
+- 58 THROW(IllegalArgumentException)
++ ? STORE_LOCAL(value e)
++ ? JUMP 8
+
++ 8:
++ 62 LOAD_MODULE object Predef
++ 62 CONSTANT("RuntimeException")
++ 62 CALL_METHOD scala.Predef.println (dynamic)
++ 62 JUMP 2
++
+ 7:
+@@ -1533,3 +1624,3 @@
+ startBlock: 1
+- blocks: [1,3,4]
++ blocks: [1,3,4,5]
+
+@@ -1553,4 +1644,9 @@
+ 229 CALL_METHOD MyException.<init> (static-instance)
+- 229 THROW(MyException)
++ ? JUMP 5
+
++ 5:
++ ? LOAD_LOCAL(variable monitor1)
++ 228 MONITOR_EXIT
++ 228 THROW(Throwable)
++
+ 3:
+@@ -1559,3 +1655,3 @@
+ 228 MONITOR_EXIT
+- ? THROW(Throwable)
++ 228 THROW(Throwable)
+
+@@ -1587,5 +1683,5 @@
+ def main(args: Array[String] (ARRAY[REF(class String)])): Unit {
+- locals: value args, variable result, variable monitor2, variable monitorResult1
++ locals: value exception$1, value args, variable result, variable monitor2, variable monitorResult1
+ startBlock: 1
+- blocks: [1,3,4]
++ blocks: [1,3,4,5]
+
+@@ -1612,4 +1708,12 @@
+ 245 CALL_METHOD MyException.<init> (static-instance)
+- 245 THROW(MyException)
++ ? STORE_LOCAL(value exception$1)
++ ? DROP ConcatClass
++ ? LOAD_LOCAL(value exception$1)
++ ? JUMP 5
+
++ 5:
++ ? LOAD_LOCAL(variable monitor2)
++ 244 MONITOR_EXIT
++ 244 THROW(Throwable)
++
+ 3:
+@@ -1618,3 +1722,3 @@
+ 244 MONITOR_EXIT
+- ? THROW(Throwable)
++ 244 THROW(Throwable)
+
diff --git a/test/files/run/outertest.scala b/test/files/run/outertest.scala
index 3cc96afa5b..fa0443f669 100644
--- a/test/files/run/outertest.scala
+++ b/test/files/run/outertest.scala
@@ -1,26 +1,57 @@
// A test for the case where the outer field of class B#J should be eliminated.
-// You can verify this by running a javap on B.J
+
+import reflect.ClassTag
+
abstract class A {
+ abstract class I
- abstract class I {
+ val foo = this
+}
+class B extends A {
+ class J extends I {
+ val bar = foo
}
- val foo = "foo"
+ type II = I
+ class K extends II {
+ val bar = foo
+ }
+ class L extends (I @annotation.tailrec) {
+ val bar = foo
+ }
}
-class B extends A {
- class J extends I {
+class C extends A {
+ val c: C = this
+
+ class M extends c.I {
val bar = foo
}
-
}
-object Test extends App {
+object Test extends App {
val b = new B
- assert((new b.J).bar == b.foo)
+ val c0 = new C
+ val c = new { override val c = c0 } with C
+
+ assert((new b.J).bar eq b)
+ assert((new b.K).bar eq b)
+ assert((new b.L).bar eq b)
+ assert((new c.M).bar eq c)
+
+ def checkOuterFields[C: ClassTag](expected: Int) {
+ val cls = implicitly[ClassTag[C]].runtimeClass
+ val outerFields = cls.getDeclaredFields().filter(_.getName.contains("$outer"))
+ assert(outerFields.size == expected, outerFields.map(_.getName))
+ }
+ checkOuterFields[A#I](1) // the base class must have the $outer pointer
+ checkOuterFields[B#J](0) // reuse parent class' $outer pointer
+ checkOuterFields[B#K](0) // ... through an alias
+ checkOuterFields[B#L](0) // ... through the annotated type
+ checkOuterFields[C#M](1) // different prefix, can't share.
}
diff --git a/test/files/run/t3994.scala b/test/files/run/t3994.scala
new file mode 100644
index 0000000000..0ee1d9d966
--- /dev/null
+++ b/test/files/run/t3994.scala
@@ -0,0 +1,20 @@
+trait T {
+ trait Default { def foo = this }
+ object Default extends Default
+}
+
+class Crash { // if you change this to a `trait` it keeps failing, though if it is an `object` it compiles just fine!
+ class Element
+
+ /* declare this as a class, and the crash goes away */
+ trait ElementOrdering extends Ordering[Element] {
+ def compare(a: Element, b: Element): Int = 0
+ }
+
+ implicit object ElementOrdering extends ElementOrdering
+}
+
+object Test extends App {
+ (new T {}).Default
+ (new Crash).ElementOrdering
+}
diff --git a/test/files/run/t5699.check b/test/files/run/t5699.check
new file mode 100755
index 0000000000..df19644ae6
--- /dev/null
+++ b/test/files/run/t5699.check
@@ -0,0 +1,11 @@
+[[syntax trees at end of parser]] // annodef.java
+package <empty> {
+ object MyAnnotation extends {
+ def <init>() = _
+ };
+ class MyAnnotation extends scala.annotation.Annotation with _root_.java.lang.annotation.Annotation with scala.annotation.ClassfileAnnotation {
+ def <init>() = _;
+ def value(): String
+ }
+}
+
diff --git a/test/files/run/t5699.scala b/test/files/run/t5699.scala
new file mode 100755
index 0000000000..5cef67e3b1
--- /dev/null
+++ b/test/files/run/t5699.scala
@@ -0,0 +1,24 @@
+import scala.tools.partest.DirectTest
+import scala.tools.nsc.util.BatchSourceFile
+
+object Test extends DirectTest {
+ // 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 newSources(sourceCodes: String*) = {
+ assert(sourceCodes.size == 1)
+ List(new BatchSourceFile("annodef.java", sourceCodes(0)))
+ }
+}
diff --git a/test/files/run/t6146b.check b/test/files/run/t6146b.check
index b664d1152a..49ff70697e 100644
--- a/test/files/run/t6146b.check
+++ b/test/files/run/t6146b.check
@@ -37,8 +37,15 @@ memType: (sub: u.Type, scrut: u.Type)u.Type
scala>
-scala> memType(S1, fTpe)
-res0: u.Type = O.X.S1.type
+scala> val mt1 = memType(S1, fTpe)
+mt1: u.Type = O.X.S1.type
+
+scala> global.typeDeconstruct.show(mt1)
+res0: String =
+TypeRef(
+ pre = SingleType(pre = ThisType(object O), object X)
+ TypeSymbol(class S1 extends C.this.F[T])
+)
scala> memType(S2, fTpe)
res1: u.Type = O.S2
diff --git a/test/files/run/t6146b.scala b/test/files/run/t6146b.scala
index adcd40d2ee..e63709aa9d 100644
--- a/test/files/run/t6146b.scala
+++ b/test/files/run/t6146b.scala
@@ -31,7 +31,8 @@ val fTpe = typeOf[O.type].decl(newTermName("foo")).paramss.head.head.tpe
def memType(sub: Type, scrut: Type): Type =
nestedMemberType(sub.typeSymbol, scrut.prefix, scrut.typeSymbol.owner)
-memType(S1, fTpe)
+val mt1 = memType(S1, fTpe)
+global.typeDeconstruct.show(mt1)
memType(S2, fTpe)
memType(S3, fTpe)
memType(S4, fTpe)
diff --git a/test/files/run/t6223.scala b/test/files/run/t6223.scala
index fb176e32e6..0996ea1c45 100644
--- a/test/files/run/t6223.scala
+++ b/test/files/run/t6223.scala
@@ -5,7 +5,7 @@ class Foo[@specialized(Int) A](a:A) {
object Test {
def main(args:Array[String]) {
val f = new Foo(333)
- val ms = f.getClass().getDeclaredMethods().sortBy(_.getName)
- ms.foreach(m => println(m.getName))
+ val ms = f.getClass().getDeclaredMethods().map(_.getName).sorted
+ ms.foreach(println)
}
}
diff --git a/test/files/run/t6387.check b/test/files/run/t6387.check
new file mode 100644
index 0000000000..83b33d238d
--- /dev/null
+++ b/test/files/run/t6387.check
@@ -0,0 +1 @@
+1000
diff --git a/test/files/run/t6387.scala b/test/files/run/t6387.scala
new file mode 100644
index 0000000000..bbebb5f511
--- /dev/null
+++ b/test/files/run/t6387.scala
@@ -0,0 +1,16 @@
+trait A {
+ def foo: Long
+}
+
+object Test {
+ def a(): A = new A {
+ var foo: Long = 1000L
+
+ val test = () => {
+ foo = 28
+ }
+ }
+ def main(args: Array[String]) {
+ println(a().foo)
+ }
+}
diff --git a/test/files/run/t7242.scala b/test/files/run/t7242.scala
new file mode 100644
index 0000000000..c995336144
--- /dev/null
+++ b/test/files/run/t7242.scala
@@ -0,0 +1,71 @@
+class CrashTest {
+ def foo = ()
+ trait CrashTestTable {
+ def cols = foo
+ }
+ // This was leading to a class between the mixed in
+ // outer accessor and the outer accessor of this object.
+ object CrashTestTable extends CrashTestTable {
+ foo
+ cols
+ }
+}
+
+class CrashTest1 {
+ def foo = ()
+ class CrashTestTable {
+ def cols = foo
+ }
+ object CrashTestTable extends CrashTestTable {
+ foo
+ cols
+ }
+}
+
+class CrashTest2 {
+ def foo = ()
+ trait CrashTestTable {
+ def cols = foo
+ }
+ object Obj extends CrashTestTable {
+ foo
+ cols
+ }
+}
+
+class CrashTest3 {
+ def foo = ()
+
+ def meth() {
+ trait CrashTestTable {
+ def cols = foo
+ }
+ object Obj extends CrashTestTable {
+ foo
+ cols
+ }
+ Obj
+ }
+}
+
+object Test extends App {
+ {
+ val c = new CrashTest
+ c.CrashTestTable
+ }
+
+ {
+ val c = new CrashTest1
+ c.CrashTestTable
+ }
+
+ {
+ val c = new CrashTest2
+ c.Obj
+ }
+
+ {
+ val c = new CrashTest3
+ c.meth()
+ }
+}
diff --git a/test/files/run/t7246.check b/test/files/run/t7246.check
new file mode 100755
index 0000000000..ce01362503
--- /dev/null
+++ b/test/files/run/t7246.check
@@ -0,0 +1 @@
+hello
diff --git a/test/files/run/t7246/Outer.java b/test/files/run/t7246/Outer.java
new file mode 100755
index 0000000000..163276fb3b
--- /dev/null
+++ b/test/files/run/t7246/Outer.java
@@ -0,0 +1,4 @@
+public class Outer {
+ public class Inner {
+ }
+} \ No newline at end of file
diff --git a/test/files/run/t7246/Test.scala b/test/files/run/t7246/Test.scala
new file mode 100755
index 0000000000..9f23ca8f3a
--- /dev/null
+++ b/test/files/run/t7246/Test.scala
@@ -0,0 +1,16 @@
+object Test extends App {
+
+ val so = new SubOuter
+ val si = new so.SubInner
+ println(si.bar)
+}
+
+class SubOuter extends Outer {
+
+ val foo = "hello"
+
+ class SubInner extends Inner {
+ def bar = foo
+ }
+
+} \ No newline at end of file
diff --git a/test/files/run/t7246b.check b/test/files/run/t7246b.check
new file mode 100755
index 0000000000..5073bd8617
--- /dev/null
+++ b/test/files/run/t7246b.check
@@ -0,0 +1,2 @@
+base
+sub
diff --git a/test/files/run/t7246b/Base.scala b/test/files/run/t7246b/Base.scala
new file mode 100755
index 0000000000..4e71d3313d
--- /dev/null
+++ b/test/files/run/t7246b/Base.scala
@@ -0,0 +1,7 @@
+class Base {
+ val baseOuter = "base"
+
+ class BaseInner {
+ val baseInner = baseOuter
+ }
+}
diff --git a/test/files/run/t7246b/Outer.java b/test/files/run/t7246b/Outer.java
new file mode 100755
index 0000000000..53a79316ef
--- /dev/null
+++ b/test/files/run/t7246b/Outer.java
@@ -0,0 +1,4 @@
+public class Outer extends Base {
+ public class Inner extends BaseInner {
+ }
+} \ No newline at end of file
diff --git a/test/files/run/t7246b/Test.scala b/test/files/run/t7246b/Test.scala
new file mode 100755
index 0000000000..f0982ea8d0
--- /dev/null
+++ b/test/files/run/t7246b/Test.scala
@@ -0,0 +1,14 @@
+object Test extends App {
+
+ val so = new SubOuter
+ val si = new so.SubInner
+ println(si.baseInner)
+ println(si.subInner)
+}
+
+class SubOuter extends Outer {
+ val subOuter = "sub"
+ class SubInner extends Inner {
+ def subInner = subOuter
+ }
+}
diff --git a/test/files/run/t7249.check b/test/files/run/t7249.check
new file mode 100644
index 0000000000..7777e0a5a2
--- /dev/null
+++ b/test/files/run/t7249.check
@@ -0,0 +1 @@
+Yup!
diff --git a/test/files/run/t7249.scala b/test/files/run/t7249.scala
new file mode 100644
index 0000000000..375df5c3ad
--- /dev/null
+++ b/test/files/run/t7249.scala
@@ -0,0 +1,7 @@
+object Test extends App {
+ def bnToLambda(s: => String): () => String = () => s
+ var x: () => String = () => sys.error("Nope")
+ val y = bnToLambda { x() }
+ x = () => "Yup!"
+ println(y())
+}
diff --git a/test/files/run/t7290.scala b/test/files/run/t7290.scala
new file mode 100644
index 0000000000..01f7e8f68e
--- /dev/null
+++ b/test/files/run/t7290.scala
@@ -0,0 +1,9 @@
+object Test extends App {
+ val y = (0: Int) match {
+ case 1 => 1
+ case 0 | 0 => 0
+ case 2 | 2 | 2 | 3 | 2 | 3 => 0
+ case _ => -1
+ }
+ assert(y == 0, y)
+}
diff --git a/test/files/run/test-cpp.check b/test/files/run/test-cpp.check
index bfea438c60..13f4c64be3 100644
--- a/test/files/run/test-cpp.check
+++ b/test/files/run/test-cpp.check
@@ -1,65 +1,81 @@
-37c37
-< locals: value args, value x, value y
----
-> locals: value args
-42,43d41
-< 52 CONSTANT(2)
-< 52 STORE_LOCAL(value x)
-45,46d42
-< 53 LOAD_LOCAL(value x)
-< 53 STORE_LOCAL(value y)
-49c45
-< 54 LOAD_LOCAL(value y)
----
-> 54 CONSTANT(2)
-92c88
-< locals: value args, value x, value y
----
-> locals: value args, value x
-101,102d96
-< 82 LOAD_LOCAL(value x)
-< 82 STORE_LOCAL(value y)
-105c99
-< 83 LOAD_LOCAL(value y)
----
-> 83 LOAD_LOCAL(value x)
-135c129
-< locals: value args, value x, value y
----
-> locals: value args
-140,141d133
-< 66 THIS(TestAliasChainDerefThis)
-< 66 STORE_LOCAL(value x)
-143,144d134
-< 67 LOAD_LOCAL(value x)
-< 67 STORE_LOCAL(value y)
-147c137
-< 68 LOAD_LOCAL(value y)
----
-> 68 THIS(Object)
-176c166
-< locals: value x, value y
----
-> locals: value x
-181,182d170
-< 29 LOAD_LOCAL(value x)
-< 29 STORE_LOCAL(value y)
-185c173
-< 30 LOAD_LOCAL(value y)
----
-> 30 LOAD_LOCAL(value x)
-223,224d210
-< 97 LOAD_LOCAL(variable x)
-< 97 STORE_LOCAL(variable y)
-227c213
-< 98 LOAD_LOCAL(variable y)
----
-> 98 LOAD_LOCAL(variable x)
-233,234d218
-< 101 LOAD_LOCAL(variable y)
-< 101 STORE_LOCAL(variable x)
-236c220
-< 102 LOAD_LOCAL(variable x)
----
-> 102 LOAD_LOCAL(variable y)
-
+--- a
++++ b
+@@ -36,3 +36,3 @@
+ def main(args: Array[String] (ARRAY[REF(class String)])): Unit {
+- locals: value args, value x, value y
++ locals: value args
+ startBlock: 1
+@@ -41,10 +41,6 @@
+ 1:
+- 52 CONSTANT(2)
+- 52 STORE_LOCAL(value x)
+ 52 SCOPE_ENTER value x
+- 53 LOAD_LOCAL(value x)
+- 53 STORE_LOCAL(value y)
+ 53 SCOPE_ENTER value y
+ 54 LOAD_MODULE object Predef
+- 54 LOAD_LOCAL(value y)
++ 54 CONSTANT(2)
+ 54 BOX INT
+@@ -91,3 +87,3 @@
+ def main(args: Array[String] (ARRAY[REF(class String)])): Unit {
+- locals: value args, value x, value y
++ locals: value args, value x
+ startBlock: 1
+@@ -100,7 +96,5 @@
+ 81 SCOPE_ENTER value x
+- 82 LOAD_LOCAL(value x)
+- 82 STORE_LOCAL(value y)
+ 82 SCOPE_ENTER value y
+ 83 LOAD_MODULE object Predef
+- 83 LOAD_LOCAL(value y)
++ 83 LOAD_LOCAL(value x)
+ 83 BOX INT
+@@ -134,3 +128,3 @@
+ def main(args: Array[String] (ARRAY[REF(class String)])): Unit {
+- locals: value args, value x, value y
++ locals: value args
+ startBlock: 1
+@@ -139,10 +133,6 @@
+ 1:
+- 66 THIS(TestAliasChainDerefThis)
+- 66 STORE_LOCAL(value x)
+ 66 SCOPE_ENTER value x
+- 67 LOAD_LOCAL(value x)
+- 67 STORE_LOCAL(value y)
+ 67 SCOPE_ENTER value y
+ 68 LOAD_MODULE object Predef
+- 68 LOAD_LOCAL(value y)
++ 68 THIS(Object)
+ 68 CALL_METHOD scala.Predef.println (dynamic)
+@@ -175,3 +165,3 @@
+ def test(x: Int (INT)): Unit {
+- locals: value x, value y
++ locals: value x
+ startBlock: 1
+@@ -180,7 +170,5 @@
+ 1:
+- 29 LOAD_LOCAL(value x)
+- 29 STORE_LOCAL(value y)
+ 29 SCOPE_ENTER value y
+ 30 LOAD_MODULE object Predef
+- 30 LOAD_LOCAL(value y)
++ 30 LOAD_LOCAL(value x)
+ 30 BOX INT
+@@ -222,7 +210,5 @@
+ 96 SCOPE_ENTER variable x
+- 97 LOAD_LOCAL(variable x)
+- 97 STORE_LOCAL(variable y)
+ 97 SCOPE_ENTER variable y
+ 98 LOAD_MODULE object Predef
+- 98 LOAD_LOCAL(variable y)
++ 98 LOAD_LOCAL(variable x)
+ 98 BOX INT
+@@ -232,6 +218,4 @@
+ 100 STORE_LOCAL(variable y)
+- 101 LOAD_LOCAL(variable y)
+- 101 STORE_LOCAL(variable x)
+ 102 LOAD_MODULE object Predef
+- 102 LOAD_LOCAL(variable x)
++ 102 LOAD_LOCAL(variable y)
+ 102 BOX INT
diff --git a/test/partest b/test/partest
index 9b0ab02fdc..ec66f5c048 100755
--- a/test/partest
+++ b/test/partest
@@ -53,8 +53,8 @@ if [ -z "$EXT_CLASSPATH" ] ; then
fi
done
elif [ -f "$SCALA_HOME/build/pack/lib/scala-partest.jar" ] ; then
- for lib in `echo "partest library reflect compiler"`; do
- ext="$SCALA_HOME/build/pack/lib/scala-$lib.jar"
+ for lib in `echo "scala-partest scala-library scala-reflect scala-compiler diffutils"`; do
+ ext="$SCALA_HOME/build/pack/lib/$lib.jar"
if [ -z "$EXT_CLASSPATH" ] ; then
EXT_CLASSPATH="$ext"
else
diff --git a/test/scaladoc/run/SI-6580.check b/test/scaladoc/run/SI-6580.check
new file mode 100644
index 0000000000..2fb6ec3258
--- /dev/null
+++ b/test/scaladoc/run/SI-6580.check
@@ -0,0 +1,11 @@
+Chain(List(Chain(List(Text(Here z(1) is defined as follows:), Text(
+), HtmlTag(<br>), Text(
+), Text( ), HtmlTag(<img src='http://example.com/fig1.png'>), Text(
+), HtmlTag(<br>), Text(
+), Text(plus z(1) times), Text(
+), HtmlTag(<br>), Text(
+), Text( ), HtmlTag(<img src='http://example.com/fig2.png'>), Text(
+), HtmlTag(<br>), Text(
+), Text(equals QL of something
+)))))
+Done.
diff --git a/test/scaladoc/run/SI-6580.scala b/test/scaladoc/run/SI-6580.scala
new file mode 100644
index 0000000000..c544138f44
--- /dev/null
+++ b/test/scaladoc/run/SI-6580.scala
@@ -0,0 +1,32 @@
+import scala.tools.nsc.doc
+import scala.tools.nsc.doc.model._
+import scala.tools.nsc.doc.html.page.{Index, ReferenceIndex}
+import scala.tools.partest.ScaladocModelTest
+
+object Test extends ScaladocModelTest {
+ override def scaladocSettings = ""
+ override def code = """
+
+ object Test {
+ /** Here z(1) is defined as follows:
+ * <br>
+ * <img src='http://example.com/fig1.png'>
+ * <br>
+ * plus z(1) times
+ * <br>
+ * <img src='http://example.com/fig2.png'>
+ * <br>
+ * equals QL of something
+ */
+ def f = 1
+ }
+
+ """
+
+ def testModel(rootPackage: Package) {
+ import access._
+
+ val f = rootPackage._object("Test")._method("f")
+ println(f.comment.get.short)
+ }
+}