summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore25
-rwxr-xr-xbuild.xml11
-rw-r--r--src/compiler/scala/reflect/macros/compiler/Validators.scala2
-rw-r--r--src/compiler/scala/tools/ant/templates/tool-windows.tmpl68
-rw-r--r--src/compiler/scala/tools/nsc/ast/parser/Parsers.scala3
-rw-r--r--src/compiler/scala/tools/nsc/backend/icode/GenICode.scala10
-rw-r--r--src/compiler/scala/tools/nsc/backend/jvm/BCodeBodyBuilder.scala4
-rw-r--r--src/compiler/scala/tools/nsc/backend/jvm/GenASM.scala6
-rw-r--r--src/compiler/scala/tools/nsc/backend/jvm/GenBCode.scala328
-rw-r--r--src/compiler/scala/tools/nsc/backend/opt/DeadCodeElimination.scala2
-rw-r--r--src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala11
-rw-r--r--src/compiler/scala/tools/nsc/symtab/classfile/Pickler.scala7
-rw-r--r--src/compiler/scala/tools/nsc/transform/Constructors.scala4
-rw-r--r--src/compiler/scala/tools/nsc/transform/Erasure.scala24
-rw-r--r--src/compiler/scala/tools/nsc/transform/Flatten.scala4
-rw-r--r--src/compiler/scala/tools/nsc/transform/patmat/Solving.scala9
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Checkable.scala4
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Contexts.scala2
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Implicits.scala3
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Infer.scala74
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Namers.scala15
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/NamesDefaults.scala9
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/PatternTypers.scala6
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/RefChecks.scala53
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/TypeDiagnostics.scala11
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Typers.scala2
-rw-r--r--src/compiler/scala/tools/nsc/util/ClassPath.scala5
-rw-r--r--src/compiler/scala/tools/nsc/util/StackTracing.scala76
-rw-r--r--src/compiler/scala/tools/nsc/util/package.scala18
-rw-r--r--src/compiler/scala/tools/reflect/ToolBoxFactory.scala5
-rw-r--r--src/interactive/scala/tools/nsc/interactive/Global.scala1
-rw-r--r--src/partest-extras/scala/tools/partest/ReplTest.scala26
-rw-r--r--src/reflect/scala/reflect/internal/BaseTypeSeqs.scala8
-rw-r--r--src/reflect/scala/reflect/internal/ClassfileConstants.scala36
-rw-r--r--src/reflect/scala/reflect/internal/Definitions.scala1
-rw-r--r--src/reflect/scala/reflect/internal/Depth.scala28
-rw-r--r--src/reflect/scala/reflect/internal/Importers.scala5
-rw-r--r--src/reflect/scala/reflect/internal/Names.scala108
-rw-r--r--src/reflect/scala/reflect/internal/Printers.scala2
-rw-r--r--src/reflect/scala/reflect/internal/Symbols.scala11
-rw-r--r--src/reflect/scala/reflect/internal/Types.scala159
-rw-r--r--src/reflect/scala/reflect/internal/Variance.scala3
-rw-r--r--src/reflect/scala/reflect/internal/Variances.scala6
-rw-r--r--src/reflect/scala/reflect/internal/annotations/uncheckedBounds.scala13
-rw-r--r--src/reflect/scala/reflect/internal/tpe/GlbLubs.scala50
-rw-r--r--src/reflect/scala/reflect/internal/tpe/TypeComparers.scala10
-rw-r--r--src/reflect/scala/reflect/internal/tpe/TypeConstraints.scala60
-rw-r--r--src/reflect/scala/reflect/internal/tpe/TypeMaps.scala13
-rw-r--r--src/reflect/scala/reflect/internal/util/package.scala2
-rw-r--r--src/reflect/scala/reflect/io/ZipArchive.scala6
-rw-r--r--src/reflect/scala/reflect/runtime/JavaMirrors.scala19
-rw-r--r--src/reflect/scala/reflect/runtime/ReflectionUtils.scala6
-rw-r--r--src/reflect/scala/reflect/runtime/SymbolLoaders.scala11
-rw-r--r--src/reflect/scala/reflect/runtime/SynchronizedOps.scala5
-rw-r--r--src/reflect/scala/reflect/runtime/SynchronizedTypes.scala3
-rw-r--r--src/repl/scala/tools/nsc/interpreter/IMain.scala4
-rw-r--r--test/files/neg/macro-abort.check4
-rw-r--r--test/files/neg/macro-abort/Macros_1.scala9
-rw-r--r--test/files/neg/macro-abort/Test_2.scala3
-rw-r--r--test/files/neg/macro-exception.check7
-rw-r--r--test/files/neg/macro-exception/Macros_1.scala9
-rw-r--r--test/files/neg/macro-exception/Test_2.scala3
-rw-r--r--test/files/neg/macro-invalidusage-presuper.check2
-rw-r--r--test/files/neg/t2796.check5
-rw-r--r--test/files/neg/t2796.flags2
-rw-r--r--test/files/neg/t2796.scala3
-rw-r--r--test/files/neg/t7020.check19
-rw-r--r--test/files/neg/t7020.flags1
-rw-r--r--test/files/neg/t7020.scala30
-rw-r--r--test/files/neg/t7501.check7
-rw-r--r--test/files/neg/t7501/t7501_1.scala12
-rw-r--r--test/files/neg/t7501/t7501_2.scala5
-rw-r--r--test/files/neg/t7694b.check7
-rw-r--r--test/files/neg/t7752.check27
-rw-r--r--test/files/neg/t7752.scala26
-rw-r--r--test/files/pos/t7014/ThreadSafety.java9
-rw-r--r--test/files/pos/t7014/ThreadSafetyLevel.java8
-rw-r--r--test/files/pos/t7014/t7014.scala4
-rw-r--r--test/files/pos/t7486-named.scala8
-rw-r--r--test/files/pos/t7486.scala (renamed from test/pending/pos/t7486.scala)0
-rw-r--r--test/files/pos/t7694.scala40
-rw-r--r--test/files/pos/t7716.scala16
-rw-r--r--test/files/pos/t7785.scala34
-rw-r--r--test/files/pos/t942/Amount_1.java5
-rw-r--r--test/files/pos/t942/Test_2.scala3
-rw-r--r--test/files/run/analyzerPlugins.scala6
-rw-r--r--test/files/run/deprecate-early-type-defs.check3
-rw-r--r--test/files/run/deprecate-early-type-defs.flags1
-rw-r--r--test/files/run/deprecate-early-type-defs.scala1
-rw-r--r--test/files/run/macro-auto-duplicate.check1
-rw-r--r--test/files/run/macro-auto-duplicate/Macros_1.scala17
-rw-r--r--test/files/run/macro-auto-duplicate/Test_2.scala3
-rw-r--r--test/files/run/macro-duplicate/Impls_Macros_1.scala2
-rw-r--r--test/files/run/reflection-magicsymbols-invoke.check2
-rw-r--r--test/files/run/repl-trim-stack-trace.scala11
-rw-r--r--test/files/run/t6392b.check2
-rw-r--r--test/files/run/t6989.check24
-rw-r--r--test/files/run/t7407.check1
-rw-r--r--test/files/run/t7407.flags1
-rw-r--r--test/files/run/t7407.scala11
-rw-r--r--test/files/run/t7407b.check2
-rw-r--r--test/files/run/t7407b.flags1
-rw-r--r--test/files/run/t7407b.scala20
-rw-r--r--test/files/run/t7510.check0
-rw-r--r--test/files/run/t7510/Ann_1.java4
-rw-r--r--test/files/run/t7510/Test_2.scala9
-rw-r--r--test/files/run/t7763.scala20
-rw-r--r--test/files/run/toolbox_current_run_compiles.check2
-rw-r--r--test/files/run/toolbox_current_run_compiles.scala28
-rw-r--r--test/junit/scala/reflect/io/ZipArchiveTest.scala37
-rw-r--r--test/junit/scala/tools/nsc/util/StackTraceTest.scala159
-rw-r--r--test/pending/pos/t7778/Foo_1.java6
-rw-r--r--test/pending/pos/t7778/Test_2.scala3
-rw-r--r--test/pending/run/t7733.check1
-rw-r--r--test/pending/run/t7733/Separate_1.scala5
-rw-r--r--test/pending/run/t7733/Test_2.scala9
-rwxr-xr-xtools/binary-repo-lib.sh2
117 files changed, 1637 insertions, 462 deletions
diff --git a/.gitignore b/.gitignore
index e60505f663..f90835d970 100644
--- a/.gitignore
+++ b/.gitignore
@@ -9,10 +9,21 @@
# see also test/files/.gitignore
#
-*.jar
-*~
+#
+# JARs aren't checked in, they are fetched by Ant / pull_binary_libs.sh
+#
+# We could be more concise with /lib/**/*.jar but that assumes
+# a late-model git.
+#
+/lib/ant/*.jar
+/lib/*.jar
+/test/files/codelib/*.jar
+/test/files/lib/*.jar
+/test/files/speclib/instrumented.jar
+/tools/*.jar
-build.properties
+# Developer specific Ant properties
+/build.properties
# target directories for ant build
/build/
@@ -33,11 +44,5 @@ build.properties
/.idea
/.settings
-# bak files produced by ./cleanup-commit
-*.bak
-
# Standard symbolic link to build/quick/bin
-qbin
-
-# Mac specific, but that is common enough a dev platform to warrant inclusion.
-.DS_Store
+/qbin
diff --git a/build.xml b/build.xml
index f428734ee0..4a2456eebf 100755
--- a/build.xml
+++ b/build.xml
@@ -391,9 +391,9 @@ TODO:
<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.url" value="http://private-repo.typesafe.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"/>
+ <property name="sbt.interface.src.url" value="http://private-repo.typesafe.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 -->
@@ -845,7 +845,11 @@ TODO:
<target name="docs.clean"> <clean build="docs"/> <delete dir="${build.dir}/manmaker" includeemptydirs="yes" quiet="yes" failonerror="no"/> </target>
<target name="dist.clean"> <delete dir="${dists.dir}" includeemptydirs="yes" quiet="yes" failonerror="no"/> </target>
- <target name="all.clean" depends="locker.clean, docs.clean"> <clean build="sbt"/> <clean build="osgi"/> </target>
+ <target name="junit.clean"> <clean build="junit"/> </target>
+
+ <target name="all.clean" depends="locker.clean, docs.clean, junit.clean">
+ <clean build="sbt"/> <clean build="osgi"/>
+ </target>
<!-- Used by the scala-installer script -->
<target name="allallclean" depends="all.clean, dist.clean"/>
@@ -1560,6 +1564,7 @@ TODO:
<target name="test.junit" depends="test.junit.comp">
<stopwatch name="test.junit.timer"/>
<mkdir dir="${test.junit.classes}"/>
+ <echo message="Note: details of failed tests will be output to ${build-junit.dir}"/>
<junit fork="yes" haltonfailure="yes" printsummary="on">
<classpath refid="test.junit.compiler.build.path"/>
<batchtest fork="yes" todir="${build-junit.dir}">
diff --git a/src/compiler/scala/reflect/macros/compiler/Validators.scala b/src/compiler/scala/reflect/macros/compiler/Validators.scala
index af17fd87c0..8d396a56d8 100644
--- a/src/compiler/scala/reflect/macros/compiler/Validators.scala
+++ b/src/compiler/scala/reflect/macros/compiler/Validators.scala
@@ -57,7 +57,7 @@ trait Validators {
checkMacroImplResultTypeMismatch(atpeToRtpe(aret), rret)
val maxLubDepth = lubDepth(aparamss.flatten map (_.tpe)) max lubDepth(rparamss.flatten map (_.tpe))
- val atargs = solvedTypes(atvars, atparams, atparams map varianceInType(aret), upper = false, depth = maxLubDepth)
+ val atargs = solvedTypes(atvars, atparams, atparams map varianceInType(aret), upper = false, maxLubDepth)
val boundsOk = typer.silent(_.infer.checkBounds(macroDdef, NoPrefix, NoSymbol, atparams, atargs, ""))
boundsOk match {
case SilentResultValue(true) => // do nothing, success
diff --git a/src/compiler/scala/tools/ant/templates/tool-windows.tmpl b/src/compiler/scala/tools/ant/templates/tool-windows.tmpl
index a3a95ffd37..1288eb0b7c 100644
--- a/src/compiler/scala/tools/ant/templates/tool-windows.tmpl
+++ b/src/compiler/scala/tools/ant/templates/tool-windows.tmpl
@@ -22,13 +22,74 @@ if "%~1"=="-toolcp" (
goto another_param
)
-set _LINE_PARAMS=%1
+rem We keep in _JAVA_PARAMS all -J-prefixed and -D-prefixed arguments
+set _JAVA_PARAMS=
+
+if [%1]==[] goto param_afterloop
+set _TEST_PARAM=%~1
+if not "%_TEST_PARAM:~0,1%"=="-" goto param_afterloop
+
+rem ignore -e "scala code"
+if "%_TEST_PARAM:~0,2%"=="-e" (
+ shift
+ shift
+ if [%1]==[] goto param_afterloop
+)
+
+set _TEST_PARAM=%~1
+if "%_TEST_PARAM:~0,2%"=="-J" (
+ set _JAVA_PARAMS=%_TEST_PARAM:~2%
+)
+
+if "%_TEST_PARAM:~0,2%"=="-D" (
+ rem test if this was double-quoted property "-Dprop=42"
+ for /F "delims== tokens=1-2" %%G in ("%_TEST_PARAM%") DO (
+ if not "%%G" == "%_TEST_PARAM%" (
+ rem double quoted: "-Dprop=42" -> -Dprop="42"
+ set _JAVA_PARAMS=%%G="%%H"
+ ) else if [%2] neq [] (
+ rem it was a normal property: -Dprop=42 or -Drop="42"
+ set _JAVA_PARAMS=%_TEST_PARAM%=%2
+ shift
+ )
+ )
+)
+
:param_loop
shift
+
if [%1]==[] goto param_afterloop
-set _LINE_PARAMS=%_LINE_PARAMS% %1
+set _TEST_PARAM=%~1
+if not "%_TEST_PARAM:~0,1%"=="-" goto param_afterloop
+
+rem ignore -e "scala code"
+if "%_TEST_PARAM:~0,2%"=="-e" (
+ shift
+ shift
+ if [%1]==[] goto param_afterloop
+)
+
+set _TEST_PARAM=%~1
+if "%_TEST_PARAM:~0,2%"=="-J" (
+ set _JAVA_PARAMS=%_JAVA_PARAMS% %_TEST_PARAM:~2%
+)
+
+if "%_TEST_PARAM:~0,2%"=="-D" (
+ rem test if this was double-quoted property "-Dprop=42"
+ for /F "delims== tokens=1-2" %%G in ("%_TEST_PARAM%") DO (
+ if not "%%G" == "%_TEST_PARAM%" (
+ rem double quoted: "-Dprop=42" -> -Dprop="42"
+ set _JAVA_PARAMS=%_JAVA_PARAMS% %%G="%%H"
+ ) else if [%2] neq [] (
+ rem it was a normal property: -Dprop=42 or -Drop="42"
+ set _JAVA_PARAMS=%_JAVA_PARAMS% %_TEST_PARAM%=%2
+ shift
+ )
+ )
+)
goto param_loop
:param_afterloop
+
if "%OS%" NEQ "Windows_NT" (
echo "Warning, your version of Windows is not supported. Attempting to start scala anyway."
)
@@ -51,6 +112,9 @@ rem We use the value of the JAVA_OPTS environment variable if defined
set _JAVA_OPTS=%JAVA_OPTS%
if not defined _JAVA_OPTS set _JAVA_OPTS=@javaflags@
+rem We append _JAVA_PARAMS java arguments to JAVA_OPTS if necessary
+if defined _JAVA_PARAMS set _JAVA_OPTS=%_JAVA_OPTS% %_JAVA_PARAMS%
+
set _TOOL_CLASSPATH=@classpath@
if "%_TOOL_CLASSPATH%"=="" (
for %%f in ("!_SCALA_HOME!\lib\*") do call :add_cpath "%%f"
diff --git a/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala b/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala
index 94270e4cf3..e5101a27a8 100644
--- a/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala
+++ b/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala
@@ -2800,9 +2800,10 @@ self =>
case vdef @ ValDef(mods, _, _, _) if !mods.isDeferred =>
List(copyValDef(vdef)(mods = mods | Flags.PRESUPER))
case tdef @ TypeDef(mods, name, tparams, rhs) =>
+ deprecationWarning(tdef.pos.point, "early type members are deprecated. Move them to the regular body: the semantics are the same.")
List(treeCopy.TypeDef(tdef, mods | Flags.PRESUPER, name, tparams, rhs))
case stat if !stat.isEmpty =>
- syntaxError(stat.pos, "only type definitions and concrete field definitions allowed in early object initialization section", skipIt = false)
+ syntaxError(stat.pos, "only concrete field definitions allowed in early object initialization section", skipIt = false)
List()
case _ => List()
}
diff --git a/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala b/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala
index 410d451316..843299398b 100644
--- a/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala
+++ b/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala
@@ -72,7 +72,7 @@ abstract class GenICode extends SubComponent {
* it is the host class; otherwise the symbol's owner.
*/
def findHostClass(selector: Type, sym: Symbol) = selector member sym.name match {
- case NoSymbol => log(s"Rejecting $selector as host class for $sym") ; sym.owner
+ case NoSymbol => debuglog(s"Rejecting $selector as host class for $sym") ; sym.owner
case _ => selector.typeSymbol
}
@@ -739,7 +739,7 @@ abstract class GenICode extends SubComponent {
resolveForwardLabel(ctx.defdef, ctx, sym)
ctx.labels.get(sym) match {
case Some(l) =>
- log("Forward jump for " + sym.fullLocationString + ": scan found label " + l)
+ debuglog("Forward jump for " + sym.fullLocationString + ": scan found label " + l)
l
case _ =>
abort("Unknown label target: " + sym + " at: " + (fun.pos) + ": ctx: " + ctx)
@@ -845,7 +845,7 @@ abstract class GenICode extends SubComponent {
val sym = tree.symbol
generatedType = toTypeKind(sym.info)
val hostClass = findHostClass(qualifier.tpe, sym)
- log(s"Host class of $sym with qual $qualifier (${qualifier.tpe}) is $hostClass")
+ debuglog(s"Host class of $sym with qual $qualifier (${qualifier.tpe}) is $hostClass")
val qualSafeToElide = treeInfo isQualifierSafeToElide qualifier
def genLoadQualUnlessElidable: Context =
@@ -1026,7 +1026,7 @@ abstract class GenICode extends SubComponent {
* type Null is holding a null.
*/
private def adaptNullRef(from: TypeKind, to: TypeKind, ctx: Context, pos: Position) {
- log(s"GenICode#adaptNullRef($from, $to, $ctx, $pos)")
+ debuglog(s"GenICode#adaptNullRef($from, $to, $ctx, $pos)")
// Don't need to adapt null to unit because we'll just drop it anyway. Don't
// need to adapt to Object or AnyRef because the JVM is happy with
@@ -1046,7 +1046,7 @@ abstract class GenICode extends SubComponent {
private def adapt(from: TypeKind, to: TypeKind, ctx: Context, pos: Position) {
// An awful lot of bugs explode here - let's leave ourselves more clues.
// A typical example is an overloaded type assigned after typer.
- log(s"GenICode#adapt($from, $to, $ctx, $pos)")
+ debuglog(s"GenICode#adapt($from, $to, $ctx, $pos)")
def coerce(from: TypeKind, to: TypeKind) = ctx.bb.emit(CALL_PRIMITIVE(Conversion(from, to)), pos)
diff --git a/src/compiler/scala/tools/nsc/backend/jvm/BCodeBodyBuilder.scala b/src/compiler/scala/tools/nsc/backend/jvm/BCodeBodyBuilder.scala
index 683f35e41f..817546b0f1 100644
--- a/src/compiler/scala/tools/nsc/backend/jvm/BCodeBodyBuilder.scala
+++ b/src/compiler/scala/tools/nsc/backend/jvm/BCodeBodyBuilder.scala
@@ -36,7 +36,7 @@ abstract class BCodeBodyBuilder extends BCodeSkelBuilder {
* it is the host class; otherwise the symbol's owner.
*/
def findHostClass(selector: Type, sym: Symbol) = selector member sym.name match {
- case NoSymbol => log(s"Rejecting $selector as host class for $sym") ; sym.owner
+ case NoSymbol => debuglog(s"Rejecting $selector as host class for $sym") ; sym.owner
case _ => selector.typeSymbol
}
@@ -330,7 +330,7 @@ abstract class BCodeBodyBuilder extends BCodeSkelBuilder {
val sym = tree.symbol
generatedType = symInfoTK(sym)
val hostClass = findHostClass(qualifier.tpe, sym)
- log(s"Host class of $sym with qual $qualifier (${qualifier.tpe}) is $hostClass")
+ debuglog(s"Host class of $sym with qual $qualifier (${qualifier.tpe}) is $hostClass")
val qualSafeToElide = treeInfo isQualifierSafeToElide qualifier
def genLoadQualUnlessElidable() { if (!qualSafeToElide) { genLoadQualifier(tree) } }
diff --git a/src/compiler/scala/tools/nsc/backend/jvm/GenASM.scala b/src/compiler/scala/tools/nsc/backend/jvm/GenASM.scala
index 4cb2f514ec..3947db2dd4 100644
--- a/src/compiler/scala/tools/nsc/backend/jvm/GenASM.scala
+++ b/src/compiler/scala/tools/nsc/backend/jvm/GenASM.scala
@@ -1122,13 +1122,13 @@ abstract class GenASM extends SubComponent with BytecodeWriters with GenJVMASM {
for (m <- moduleClass.info.membersBasedOnFlags(ExcludedForwarderFlags, Flags.METHOD)) {
if (m.isType || m.isDeferred || (m.owner eq ObjectClass) || m.isConstructor)
- debuglog("No forwarder for '%s' from %s to '%s'".format(m, jclassName, moduleClass))
+ debuglog(s"No forwarder for '$m' from $jclassName to '$moduleClass'")
else if (conflictingNames(m.name))
- log("No forwarder for " + m + " due to conflict with " + linkedClass.info.member(m.name))
+ log(s"No forwarder for $m due to conflict with " + linkedClass.info.member(m.name))
else if (m.hasAccessBoundary)
log(s"No forwarder for non-public member $m")
else {
- log("Adding static forwarder for '%s' from %s to '%s'".format(m, jclassName, moduleClass))
+ debuglog(s"Adding static forwarder for '$m' from $jclassName to '$moduleClass'")
addForwarder(isRemoteClass, jclass, moduleClass, m)
}
}
diff --git a/src/compiler/scala/tools/nsc/backend/jvm/GenBCode.scala b/src/compiler/scala/tools/nsc/backend/jvm/GenBCode.scala
index e55a3baed0..193100474c 100644
--- a/src/compiler/scala/tools/nsc/backend/jvm/GenBCode.scala
+++ b/src/compiler/scala/tools/nsc/backend/jvm/GenBCode.scala
@@ -17,13 +17,25 @@ import scala.tools.asm
/*
* Prepare in-memory representations of classfiles using the ASM Tree API, and serialize them to disk.
*
- * `BCodePhase.apply(CompilationUnit)` is invoked by some external force and that sets in motion:
- * - visiting each ClassDef contained in that CompilationUnit
- * - lowering the ClassDef into:
+ * Three pipelines are at work, each taking work items from a queue dedicated to that pipeline:
+ *
+ * (There's another pipeline so to speak, the one that populates queue-1 by traversing a CompilationUnit until ClassDefs are found,
+ * but the "interesting" pipelines are the ones described below)
+ *
+ * (1) In the first queue, an item consists of a ClassDef along with its arrival position.
+ * This position is needed at the time classfiles are serialized to disk,
+ * so as to emit classfiles in the same order CleanUp handed them over.
+ * As a result, two runs of the compiler on the same files produce jars that are identical on a byte basis.
+ * See `ant test.stability`
+ *
+ * (2) The second queue contains items where a ClassDef has been lowered into:
* (a) an optional mirror class,
* (b) a plain class, and
* (c) an optional bean class.
- * - each of the ClassNodes above is lowered into a byte-array (ie into a classfile) and serialized.
+ *
+ * (3) The third queue contains items ready for serialization.
+ * It's a priority queue that follows the original arrival order,
+ * so as to emit identical jars on repeated compilation of the same sources.
*
* Plain, mirror, and bean classes are built respectively by PlainClassBuilder, JMirrorBuilder, and JBeanInfoBuilder.
*
@@ -50,75 +62,192 @@ abstract class GenBCode extends BCodeSyncAndTry {
private var mirrorCodeGen : JMirrorBuilder = null
private var beanInfoCodeGen : JBeanInfoBuilder = null
- private var needsOutFolder = false // whether getOutFolder(claszSymbol) should be invoked for each claszSymbol
+ /* ---------------- q1 ---------------- */
+
+ case class Item1(arrivalPos: Int, cd: ClassDef, cunit: CompilationUnit) {
+ def isPoison = { arrivalPos == Int.MaxValue }
+ }
+ private val poison1 = Item1(Int.MaxValue, null, null)
+ private val q1 = new java.util.LinkedList[Item1]
+
+ /* ---------------- q2 ---------------- */
- val caseInsensitively = mutable.Map.empty[String, Symbol]
+ case class Item2(arrivalPos: Int,
+ mirror: asm.tree.ClassNode,
+ plain: asm.tree.ClassNode,
+ bean: asm.tree.ClassNode,
+ outFolder: scala.tools.nsc.io.AbstractFile) {
+ def isPoison = { arrivalPos == Int.MaxValue }
+ }
+
+ private val poison2 = Item2(Int.MaxValue, null, null, null, null)
+ private val q2 = new _root_.java.util.LinkedList[Item2]
+
+ /* ---------------- q3 ---------------- */
/*
- * Checks for duplicate internal names case-insensitively,
- * builds ASM ClassNodes for mirror, plain, and bean classes.
+ * An item of queue-3 (the last queue before serializing to disk) contains three of these
+ * (one for each of mirror, plain, and bean classes).
*
+ * @param jclassName internal name of the class
+ * @param jclassBytes bytecode emitted for the class SubItem3 represents
*/
- def visit(arrivalPos: Int, cd: ClassDef, cunit: CompilationUnit) {
- val claszSymbol = cd.symbol
-
- // GenASM checks this before classfiles are emitted, https://github.com/scala/scala/commit/e4d1d930693ac75d8eb64c2c3c69f2fc22bec739
- val lowercaseJavaClassName = claszSymbol.javaClassName.toLowerCase
- caseInsensitively.get(lowercaseJavaClassName) match {
- case None =>
- caseInsensitively.put(lowercaseJavaClassName, claszSymbol)
- case Some(dupClassSym) =>
- cunit.warning(
- claszSymbol.pos,
- s"Class ${claszSymbol.javaClassName} differs only in case from ${dupClassSym.javaClassName}. " +
- "Such classes will overwrite one another on case-insensitive filesystems."
- )
+ case class SubItem3(
+ jclassName: String,
+ jclassBytes: Array[Byte]
+ )
+
+ case class Item3(arrivalPos: Int,
+ mirror: SubItem3,
+ plain: SubItem3,
+ bean: SubItem3,
+ outFolder: scala.tools.nsc.io.AbstractFile) {
+
+ def isPoison = { arrivalPos == Int.MaxValue }
+ }
+ private val i3comparator = new java.util.Comparator[Item3] {
+ override def compare(a: Item3, b: Item3) = {
+ if (a.arrivalPos < b.arrivalPos) -1
+ else if (a.arrivalPos == b.arrivalPos) 0
+ else 1
}
+ }
+ private val poison3 = Item3(Int.MaxValue, null, null, null, null)
+ private val q3 = new java.util.PriorityQueue[Item3](1000, i3comparator)
+
+ /*
+ * Pipeline that takes ClassDefs from queue-1, lowers them into an intermediate form, placing them on queue-2
+ */
+ class Worker1(needsOutFolder: Boolean) {
+
+ val caseInsensitively = mutable.Map.empty[String, Symbol]
- // -------------- mirror class, if needed --------------
- val mirrorC =
- if (isStaticModule(claszSymbol) && isTopLevelModule(claszSymbol)) {
- if (claszSymbol.companionClass == NoSymbol) {
- mirrorCodeGen.genMirrorClass(claszSymbol, cunit)
- } else {
- log(s"No mirror class for module with linked class: ${claszSymbol.fullName}");
- null
+ def run() {
+ while (true) {
+ val item = q1.poll
+ if (item.isPoison) {
+ q2 add poison2
+ return
}
- } else null
-
- // -------------- "plain" class --------------
- val pcb = new PlainClassBuilder(cunit)
- pcb.genPlainClass(cd)
- val outF = if (needsOutFolder) getOutFolder(claszSymbol, pcb.thisName, cunit) else null;
- val plainC = pcb.cnode
-
- // -------------- bean info class, if needed --------------
- val beanC =
- if (claszSymbol hasAnnotation BeanInfoAttr) {
- beanInfoCodeGen.genBeanInfoClass(
- claszSymbol, cunit,
- fieldSymbols(claszSymbol),
- methodSymbols(cd)
- )
- } else null
-
- // ----------- serialize classfiles to disk
-
- def getByteArray(cn: asm.tree.ClassNode): Array[Byte] = {
- val cw = new CClassWriter(extraProc)
- cn.accept(cw)
- cw.toByteArray
+ else {
+ try { visit(item) }
+ catch {
+ case ex: Throwable =>
+ ex.printStackTrace()
+ error(s"Error while emitting ${item.cunit.source}\n${ex.getMessage}")
+ }
+ }
+ }
}
- if (mirrorC != null) {
- sendToDisk(mirrorC.name, getByteArray(mirrorC), outF)
+ /*
+ * Checks for duplicate internal names case-insensitively,
+ * builds ASM ClassNodes for mirror, plain, and bean classes;
+ * enqueues them in queue-2.
+ *
+ */
+ def visit(item: Item1) {
+ val Item1(arrivalPos, cd, cunit) = item
+ val claszSymbol = cd.symbol
+
+ // GenASM checks this before classfiles are emitted, https://github.com/scala/scala/commit/e4d1d930693ac75d8eb64c2c3c69f2fc22bec739
+ val lowercaseJavaClassName = claszSymbol.javaClassName.toLowerCase
+ caseInsensitively.get(lowercaseJavaClassName) match {
+ case None =>
+ caseInsensitively.put(lowercaseJavaClassName, claszSymbol)
+ case Some(dupClassSym) =>
+ item.cunit.warning(
+ claszSymbol.pos,
+ s"Class ${claszSymbol.javaClassName} differs only in case from ${dupClassSym.javaClassName}. " +
+ "Such classes will overwrite one another on case-insensitive filesystems."
+ )
+ }
+
+ // -------------- mirror class, if needed --------------
+ val mirrorC =
+ if (isStaticModule(claszSymbol) && isTopLevelModule(claszSymbol)) {
+ if (claszSymbol.companionClass == NoSymbol) {
+ mirrorCodeGen.genMirrorClass(claszSymbol, cunit)
+ } else {
+ log(s"No mirror class for module with linked class: ${claszSymbol.fullName}")
+ null
+ }
+ } else null
+
+ // -------------- "plain" class --------------
+ val pcb = new PlainClassBuilder(cunit)
+ pcb.genPlainClass(cd)
+ val outF = if (needsOutFolder) getOutFolder(claszSymbol, pcb.thisName, cunit) else null;
+ val plainC = pcb.cnode
+
+ // -------------- bean info class, if needed --------------
+ val beanC =
+ if (claszSymbol hasAnnotation BeanInfoAttr) {
+ beanInfoCodeGen.genBeanInfoClass(
+ claszSymbol, cunit,
+ fieldSymbols(claszSymbol),
+ methodSymbols(cd)
+ )
+ } else null
+
+ // ----------- hand over to pipeline-2
+
+ val item2 =
+ Item2(arrivalPos,
+ mirrorC, plainC, beanC,
+ outF)
+
+ q2 add item2 // at the very end of this method so that no Worker2 thread starts mutating before we're done.
+
+ } // end of method visit(Item1)
+
+ } // end of class BCodePhase.Worker1
+
+ /*
+ * Pipeline that takes ClassNodes from queue-2. The unit of work depends on the optimization level:
+ *
+ * (a) no optimization involves:
+ * - converting the plain ClassNode to byte array and placing it on queue-3
+ */
+ class Worker2 {
+
+ def run() {
+ while (true) {
+ val item = q2.poll
+ if (item.isPoison) {
+ q3 add poison3
+ return
+ }
+ else {
+ try { addToQ3(item) }
+ catch {
+ case ex: Throwable =>
+ ex.printStackTrace()
+ error(s"Error while emitting ${item.plain.name}\n${ex.getMessage}")
+ }
+ }
+ }
}
- sendToDisk(plainC.name, getByteArray(plainC), outF)
- if (beanC != null) {
- sendToDisk(beanC.name, getByteArray(beanC), outF)
+
+ private def addToQ3(item: Item2) {
+
+ def getByteArray(cn: asm.tree.ClassNode): Array[Byte] = {
+ val cw = new CClassWriter(extraProc)
+ cn.accept(cw)
+ cw.toByteArray
+ }
+
+ val Item2(arrivalPos, mirror, plain, bean, outFolder) = item
+
+ val mirrorC = if (mirror == null) null else SubItem3(mirror.name, getByteArray(mirror))
+ val plainC = SubItem3(plain.name, getByteArray(plain))
+ val beanC = if (bean == null) null else SubItem3(bean.name, getByteArray(bean))
+
+ q3 add Item3(arrivalPos, mirrorC, plainC, beanC, outFolder)
+
}
- } // end of method visit()
+ } // end of class BCodePhase.Worker2
var arrivalPos = 0
@@ -144,15 +273,12 @@ abstract class GenBCode extends BCodeSyncAndTry {
mirrorCodeGen = new JMirrorBuilder
beanInfoCodeGen = new JBeanInfoBuilder
- needsOutFolder = bytecodeWriter.isInstanceOf[ClassBytecodeWriter]
-
- super.run()
+ val needsOutfileForSymbol = bytecodeWriter.isInstanceOf[ClassBytecodeWriter]
+ buildAndSendToDisk(needsOutfileForSymbol)
// closing output files.
bytecodeWriter.close()
- caseInsensitively.clear()
-
/* TODO Bytecode can be verified (now that all classfiles have been written to disk)
*
* (1) asm.util.CheckAdapter.verify()
@@ -170,17 +296,69 @@ abstract class GenBCode extends BCodeSyncAndTry {
clearBCodeTypes()
}
- def sendToDisk(jclassName: String, jclassBytes: Array[Byte], outFolder: _root_.scala.tools.nsc.io.AbstractFile) {
- try {
- val outFile =
- if (outFolder == null) null
- else getFileForClassfile(outFolder, jclassName, ".class")
- bytecodeWriter.writeClass(jclassName, jclassName, jclassBytes, outFile)
+ /*
+ * Sequentially:
+ * (a) place all ClassDefs in queue-1
+ * (b) dequeue one at a time from queue-1, convert it to ASM ClassNode, place in queue-2
+ * (c) dequeue one at a time from queue-2, convert it to byte-array, place in queue-3
+ * (d) serialize to disk by draining queue-3.
+ */
+ private def buildAndSendToDisk(needsOutFolder: Boolean) {
+
+ feedPipeline1()
+ (new Worker1(needsOutFolder)).run()
+ (new Worker2).run()
+ drainQ3()
+
+ }
+
+ /* Feed pipeline-1: place all ClassDefs on q1, recording their arrival position. */
+ private def feedPipeline1() {
+ super.run()
+ q1 add poison1
+ }
+
+ /* Pipeline that writes classfile representations to disk. */
+ private def drainQ3() {
+
+ def sendToDisk(cfr: SubItem3, outFolder: scala.tools.nsc.io.AbstractFile) {
+ if (cfr != null){
+ val SubItem3(jclassName, jclassBytes) = cfr
+ try {
+ val outFile =
+ if (outFolder == null) null
+ else getFileForClassfile(outFolder, jclassName, ".class")
+ bytecodeWriter.writeClass(jclassName, jclassName, jclassBytes, outFile)
+ }
+ catch {
+ case e: FileConflictException =>
+ error(s"error writing $jclassName: ${e.getMessage}")
+ }
+ }
}
- catch {
- case e: FileConflictException =>
- error(s"error writing $jclassName: ${e.getMessage}")
+
+ var moreComing = true
+ // `expected` denotes the arrivalPos whose Item3 should be serialized next
+ var expected = 0
+
+ while (moreComing) {
+ val incoming = q3.poll
+ moreComing = !incoming.isPoison
+ if (moreComing) {
+ val item = incoming
+ val outFolder = item.outFolder
+ sendToDisk(item.mirror, outFolder)
+ sendToDisk(item.plain, outFolder)
+ sendToDisk(item.bean, outFolder)
+ expected += 1
+ }
}
+
+ // we're done
+ assert(q1.isEmpty, s"Some ClassDefs remained in the first queue: $q1")
+ assert(q2.isEmpty, s"Some classfiles remained in the second queue: $q2")
+ assert(q3.isEmpty, s"Some classfiles weren't written to disk: $q3")
+
}
override def apply(cunit: CompilationUnit): Unit = {
@@ -190,7 +368,7 @@ abstract class GenBCode extends BCodeSyncAndTry {
case EmptyTree => ()
case PackageDef(_, stats) => stats foreach gen
case cd: ClassDef =>
- visit(arrivalPos, cd, cunit)
+ q1 add Item1(arrivalPos, cd, cunit)
arrivalPos += 1
}
}
diff --git a/src/compiler/scala/tools/nsc/backend/opt/DeadCodeElimination.scala b/src/compiler/scala/tools/nsc/backend/opt/DeadCodeElimination.scala
index 483bff6467..7511da8b00 100644
--- a/src/compiler/scala/tools/nsc/backend/opt/DeadCodeElimination.scala
+++ b/src/compiler/scala/tools/nsc/backend/opt/DeadCodeElimination.scala
@@ -159,7 +159,7 @@ abstract class DeadCodeElimination extends SubComponent {
case RETURN(_) | JUMP(_) | CJUMP(_, _, _, _) | CZJUMP(_, _, _, _) | STORE_FIELD(_, _) |
THROW(_) | LOAD_ARRAY_ITEM(_) | STORE_ARRAY_ITEM(_) | SCOPE_ENTER(_) | SCOPE_EXIT(_) | STORE_THIS(_) |
- LOAD_EXCEPTION(_) | SWITCH(_, _) | MONITOR_ENTER() | MONITOR_EXIT() =>
+ LOAD_EXCEPTION(_) | SWITCH(_, _) | MONITOR_ENTER() | MONITOR_EXIT() | CHECK_CAST(_) =>
moveToWorkList()
case CALL_METHOD(m1, _) if isSideEffecting(m1) =>
diff --git a/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala b/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala
index 14e3f5b642..2b96961291 100644
--- a/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala
+++ b/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala
@@ -874,9 +874,14 @@ abstract class ClassfileParser {
case ENUM_TAG =>
val t = pool.getType(index)
val n = readName()
- val s = t.typeSymbol.companionModule.info.decls.lookup(n)
- assert(s != NoSymbol, t)
- Some(LiteralAnnotArg(Constant(s)))
+ val module = t.typeSymbol.companionModule
+ val s = module.info.decls.lookup(n)
+ if (s != NoSymbol) Some(LiteralAnnotArg(Constant(s)))
+ else {
+ warning(s"""While parsing annotations in ${in.file}, could not find $n in enum $module.\nThis is likely due to an implementation restriction: an annotation argument cannot refer to a member of the annotated class (SI-7014).""")
+ None
+ }
+
case ARRAY_TAG =>
val arr = new ArrayBuffer[ClassfileAnnotArg]()
var hasError = false
diff --git a/src/compiler/scala/tools/nsc/symtab/classfile/Pickler.scala b/src/compiler/scala/tools/nsc/symtab/classfile/Pickler.scala
index 9bad29097c..9ac1ce1b9c 100644
--- a/src/compiler/scala/tools/nsc/symtab/classfile/Pickler.scala
+++ b/src/compiler/scala/tools/nsc/symtab/classfile/Pickler.scala
@@ -88,12 +88,17 @@ abstract class Pickler extends SubComponent {
/** Returns usually symbol's owner, but picks classfile root instead
* for existentially bound variables that have a non-local owner.
* Question: Should this be done for refinement class symbols as well?
+ *
+ * Note: tree pickling also finds its way here; e.g. in SI-7501 the pickling
+ * of trees in annotation arguments considers the parameter symbol of a method
+ * called in such a tree as "local". The condition `sym.isValueParameter` was
+ * added to fix that bug, but there may be a better way.
*/
private def localizedOwner(sym: Symbol) =
if (isLocal(sym) && !isRootSym(sym) && !isLocal(sym.owner))
// don't use a class as the localized owner for type parameters that are not owned by a class: those are not instantiated by asSeenFrom
// however, they would suddenly be considered by asSeenFrom if their localized owner became a class (causing the crashes of #4079, #2741)
- (if(sym.isTypeParameter && !sym.owner.isClass) nonClassRoot
+ (if ((sym.isTypeParameter || sym.isValueParameter) && !sym.owner.isClass) nonClassRoot
else root)
else sym.owner
diff --git a/src/compiler/scala/tools/nsc/transform/Constructors.scala b/src/compiler/scala/tools/nsc/transform/Constructors.scala
index e80117afbd..cbe4f69d25 100644
--- a/src/compiler/scala/tools/nsc/transform/Constructors.scala
+++ b/src/compiler/scala/tools/nsc/transform/Constructors.scala
@@ -44,8 +44,8 @@ abstract class Constructors extends Transform with ast.TreeDSL {
val uninitializedVals = mutable.Set[Symbol](
stats collect { case vd: ValDef if checkableForInit(vd.symbol) => vd.symbol.accessedOrSelf }: _*
)
- if (uninitializedVals.nonEmpty)
- log("Checking constructor for init order issues among: " + uninitializedVals.map(_.name).mkString(", "))
+ if (uninitializedVals.size > 1)
+ log("Checking constructor for init order issues among: " + uninitializedVals.toList.map(_.name.toString.trim).distinct.sorted.mkString(", "))
for (stat <- stats) {
// Checking the qualifier symbol is necessary to prevent a selection on
diff --git a/src/compiler/scala/tools/nsc/transform/Erasure.scala b/src/compiler/scala/tools/nsc/transform/Erasure.scala
index 0a66ba8a32..c74fc620ca 100644
--- a/src/compiler/scala/tools/nsc/transform/Erasure.scala
+++ b/src/compiler/scala/tools/nsc/transform/Erasure.scala
@@ -529,7 +529,8 @@ abstract class Erasure extends AddInterfaces
@inline private def box(tree: Tree, target: => String): Tree = {
val result = box1(tree)
- log(s"boxing ${tree.summaryString}: ${tree.tpe} into $target: ${result.tpe}")
+ if (tree.tpe =:= UnitTpe) ()
+ else log(s"boxing ${tree.summaryString}: ${tree.tpe} into $target: ${result.tpe}")
result
}
@@ -571,7 +572,7 @@ abstract class Erasure extends AddInterfaces
private def unbox(tree: Tree, pt: Type): Tree = {
val result = unbox1(tree, pt)
- log(s"unboxing ${tree.summaryString}: ${tree.tpe} with pt=$pt as type ${result.tpe}")
+ log(s"unboxing ${tree.shortClass}: ${tree.tpe} as a ${result.tpe}")
result
}
@@ -594,7 +595,6 @@ abstract class Erasure extends AddInterfaces
val tree1 = pt match {
case ErasedValueType(tref) =>
val clazz = tref.sym
- log("not boxed: "+tree)
lazy val underlying = underlyingOfValueClass(clazz)
val tree0 =
if (tree.tpe.typeSymbol == NullClass &&
@@ -622,8 +622,18 @@ abstract class Erasure extends AddInterfaces
/** Generate a synthetic cast operation from tree.tpe to pt.
* @pre pt eq pt.normalize
*/
- private def cast(tree: Tree, pt: Type): Tree = logResult(s"cast($tree, $pt)") {
- if (pt.typeSymbol == UnitClass) {
+ private def cast(tree: Tree, pt: Type): Tree = {
+ if ((tree.tpe ne null) && !(tree.tpe =:= ObjectTpe)) {
+ def word = (
+ if (tree.tpe <:< pt) "upcast"
+ else if (pt <:< tree.tpe) "downcast"
+ else if (pt weak_<:< tree.tpe) "coerce"
+ else if (tree.tpe weak_<:< pt) "widen"
+ else "cast"
+ )
+ log(s"erasure ${word}s from ${tree.tpe} to $pt")
+ }
+ if (pt =:= UnitTpe) {
// See SI-4731 for one example of how this occurs.
log("Attempted to cast to Unit: " + tree)
tree.duplicate setType pt
@@ -680,7 +690,7 @@ abstract class Erasure extends AddInterfaces
private def adaptMember(tree: Tree): Tree = {
//Console.println("adaptMember: " + tree);
tree match {
- case Apply(TypeApply(sel @ Select(qual, name), List(targ)), List())
+ case Apply(ta @ TypeApply(sel @ Select(qual, name), List(targ)), List())
if tree.symbol == Any_asInstanceOf =>
val qual1 = typedQualifier(qual, NOmode, ObjectTpe) // need to have an expected type, see #3037
@@ -705,7 +715,7 @@ abstract class Erasure extends AddInterfaces
// }
typed(untyped)
}
- } else qual1
+ } else treeCopy.Apply(tree, treeCopy.TypeApply(ta, treeCopy.Select(sel, qual1, name), List(targ)), List())
case Apply(TypeApply(sel @ Select(qual, name), List(targ)), List())
if tree.symbol == Any_isInstanceOf =>
diff --git a/src/compiler/scala/tools/nsc/transform/Flatten.scala b/src/compiler/scala/tools/nsc/transform/Flatten.scala
index 44d39de205..e31211d321 100644
--- a/src/compiler/scala/tools/nsc/transform/Flatten.scala
+++ b/src/compiler/scala/tools/nsc/transform/Flatten.scala
@@ -24,8 +24,8 @@ abstract class Flatten extends InfoTransform {
val old = (scope lookupUnshadowedEntries sym.name).toList
old foreach (scope unlink _)
scope enter sym
- log(s"lifted ${sym.fullLocationString}" + ( if (old.isEmpty) "" else s" after unlinking $old from scope." ))
- old
+ def old_s = old map (_.sym) mkString ", "
+ debuglog(s"In scope of ${sym.owner}, unlinked $old_s and entered $sym")
}
private def liftClass(sym: Symbol) {
diff --git a/src/compiler/scala/tools/nsc/transform/patmat/Solving.scala b/src/compiler/scala/tools/nsc/transform/patmat/Solving.scala
index 3c7dc79636..114bcba5df 100644
--- a/src/compiler/scala/tools/nsc/transform/patmat/Solving.scala
+++ b/src/compiler/scala/tools/nsc/transform/patmat/Solving.scala
@@ -202,15 +202,16 @@ trait Solving extends Logic {
withLit(findModelFor(dropUnit(f, unitLit)), unitLit)
case _ =>
// partition symbols according to whether they appear in positive and/or negative literals
- val pos = new mutable.HashSet[Sym]()
- val neg = new mutable.HashSet[Sym]()
+ // SI-7020 Linked- for deterministic counter examples.
+ val pos = new mutable.LinkedHashSet[Sym]()
+ val neg = new mutable.LinkedHashSet[Sym]()
f.foreach{_.foreach{ lit =>
if (lit.pos) pos += lit.sym else neg += lit.sym
}}
// appearing in both positive and negative
- val impures = pos intersect neg
+ val impures: mutable.LinkedHashSet[Sym] = pos intersect neg
// appearing only in either positive/negative positions
- val pures = (pos ++ neg) -- impures
+ val pures: mutable.LinkedHashSet[Sym] = (pos ++ neg) -- impures
if (pures nonEmpty) {
val pureSym = pures.head
diff --git a/src/compiler/scala/tools/nsc/typechecker/Checkable.scala b/src/compiler/scala/tools/nsc/typechecker/Checkable.scala
index 67c5666f66..0eae17612d 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Checkable.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Checkable.scala
@@ -277,7 +277,9 @@ trait Checkable {
parents foreach (p => checkCheckable(tree, p, X, inPattern, canRemedy))
case _ =>
val checker = new CheckabilityChecker(X, P)
- log(checker.summaryString)
+ if (checker.result == RuntimeCheckable)
+ log(checker.summaryString)
+
if (checker.neverMatches) {
val addendum = if (checker.neverSubClass) "" else " (but still might match its erasure)"
getContext.unit.warning(tree.pos, s"fruitless type test: a value of type $X cannot also be a $P$addendum")
diff --git a/src/compiler/scala/tools/nsc/typechecker/Contexts.scala b/src/compiler/scala/tools/nsc/typechecker/Contexts.scala
index 86a0d33737..8d42bf94f3 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Contexts.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Contexts.scala
@@ -1026,7 +1026,7 @@ trait Contexts { self: Analyzer =>
(scope lookupUnshadowedEntries name filter (e => qualifies(e.sym))).toList
def newOverloaded(owner: Symbol, pre: Type, entries: List[ScopeEntry]) =
- logResult(s"!!! lookup overloaded")(owner.newOverloaded(pre, entries map (_.sym)))
+ logResult(s"overloaded symbol in $pre")(owner.newOverloaded(pre, entries map (_.sym)))
// Constructor lookup should only look in the decls of the enclosing class
// not in the self-type, nor in the enclosing context, nor in imports (SI-4460, SI-6745)
diff --git a/src/compiler/scala/tools/nsc/typechecker/Implicits.scala b/src/compiler/scala/tools/nsc/typechecker/Implicits.scala
index 4265efc839..3a6b25f1cd 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Implicits.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Implicits.scala
@@ -644,8 +644,7 @@ trait Implicits {
if (tvars.nonEmpty)
typingLog("solve", ptLine("tvars" -> tvars, "tvars.constr" -> tvars.map(_.constr)))
- val targs = solvedTypes(tvars, undetParams, undetParams map varianceInType(pt),
- upper = false, lubDepth(List(itree2.tpe, pt)))
+ val targs = solvedTypes(tvars, undetParams, undetParams map varianceInType(pt), upper = false, lubDepth(itree2.tpe :: pt :: Nil))
// #2421: check that we correctly instantiated type parameters outside of the implicit tree:
checkBounds(itree2, NoPrefix, NoSymbol, undetParams, targs, "inferred ")
diff --git a/src/compiler/scala/tools/nsc/typechecker/Infer.scala b/src/compiler/scala/tools/nsc/typechecker/Infer.scala
index 50d88d7c4d..03f680525c 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Infer.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Infer.scala
@@ -9,6 +9,7 @@ package typechecker
import scala.collection.{ mutable, immutable }
import scala.util.control.ControlThrowable
import symtab.Flags._
+import scala.reflect.internal.Depth
/** This trait contains methods related to type parameter inference.
*
@@ -21,6 +22,7 @@ trait Infer extends Checkable {
import global._
import definitions._
import typeDebug.ptBlock
+ import typeDebug.str.parentheses
import typingStack.{ printTyping }
/** The formal parameter types corresponding to `formals`.
@@ -132,34 +134,17 @@ trait Infer extends Checkable {
* @param upper When `true` search for max solution else min.
* @throws NoInstance
*/
- def solvedTypes(tvars: List[TypeVar], tparams: List[Symbol],
- variances: List[Variance], upper: Boolean, depth: Int): List[Type] = {
-
- if (tvars.nonEmpty) {
- def tp_s = (tparams, tvars).zipped map { case (tp, tv) => s"${tp.name}/$tv" } mkString ","
- printTyping(s"solving for $tp_s")
- }
-
- if (!solve(tvars, tparams, variances, upper, depth)) {
- // no panic, it's good enough to just guess a solution, we'll find out
- // later whether it works. *ZAP* @M danger, Will Robinson! this means
- // that you should never trust inferred type arguments!
- //
- // Need to call checkBounds on the args/typars or type1 on the tree
- // for the expression that results from type inference see e.g., #2421:
- // implicit search had been ignoring this caveat
- // throw new DeferredNoInstance(() =>
- // "no solution exists for constraints"+(tvars map boundsString))
+ def solvedTypes(tvars: List[TypeVar], tparams: List[Symbol], variances: List[Variance], upper: Boolean, depth: Depth): List[Type] = {
+ if (tvars.isEmpty) Nil else {
+ printTyping("solving for " + parentheses((tparams, tvars).zipped map ((p, tv) => s"${p.name}: $tv")))
+ // !!! What should be done with the return value of "solve", which is at present ignored?
+ // The historical commentary says "no panic, it's good enough to just guess a solution,
+ // we'll find out later whether it works", meaning don't issue an error here when types
+ // don't conform to bounds. That means you can never trust the results of implicit search.
+ // For an example where this was not being heeded, SI-2421.
+ solve(tvars, tparams, variances, upper, depth)
+ tvars map instantiate
}
- for (tvar <- tvars ; if tvar.constr.inst == tvar) {
- if (tvar.origin.typeSymbol.info eq ErrorType)
- // this can happen if during solving a cyclic type parameter
- // such as T <: T gets completed. See #360
- tvar.constr.inst = ErrorType
- else
- abort(tvar.origin+" at "+tvar.origin.typeSymbol.owner)
- }
- tvars map instantiate
}
def skipImplicit(tp: Type) = tp match {
@@ -174,7 +159,10 @@ trait Infer extends Checkable {
* This method seems to be performance critical.
*/
def normalize(tp: Type): Type = tp match {
- case PolyType(_, restpe) => logResult(s"Normalizing $tp in infer")(normalize(restpe))
+ case PolyType(_, restpe) =>
+ logResult(sm"""|Normalizing PolyType in infer:
+ | was: $restpe
+ | now""")(normalize(restpe))
case mt @ MethodType(_, restpe) if mt.isImplicit => normalize(restpe)
case mt @ MethodType(_, restpe) if !mt.isDependentMethodType => functionType(mt.paramTypes, normalize(restpe))
case NullaryMethodType(restpe) => normalize(restpe)
@@ -554,10 +542,7 @@ trait Infer extends Checkable {
"argument expression's type is not compatible with formal parameter type" + foundReqMsg(tp1, pt1))
}
}
- val targs = solvedTypes(
- tvars, tparams, tparams map varianceInTypes(formals),
- upper = false, lubDepth(formals) max lubDepth(argtpes)
- )
+ val targs = solvedTypes(tvars, tparams, tparams map varianceInTypes(formals), upper = false, lubDepth(formals) max lubDepth(argtpes))
// Can warn about inferring Any/AnyVal as long as they don't appear
// explicitly anywhere amongst the formal, argument, result, or expected type.
def canWarnAboutAny = !(pt :: restpe :: formals ::: argtpes exists (t => (t contains AnyClass) || (t contains AnyValClass)))
@@ -1030,7 +1015,10 @@ trait Infer extends Checkable {
val variances =
if (ctorTp.paramTypes.isEmpty) undetparams map varianceInType(ctorTp)
else undetparams map varianceInTypes(ctorTp.paramTypes)
- val targs = solvedTypes(tvars, undetparams, variances, upper = true, lubDepth(List(resTp, pt)))
+
+ // Note: this is the only place where solvedTypes (or, indirectly, solve) is called
+ // with upper = true.
+ val targs = solvedTypes(tvars, undetparams, variances, upper = true, lubDepth(resTp :: pt :: Nil))
// checkBounds(tree, NoPrefix, NoSymbol, undetparams, targs, "inferred ")
// no checkBounds here. If we enable it, test bug602 fails.
// TODO: reinstate checkBounds, return params that fail to meet their bounds to undetparams
@@ -1099,7 +1087,7 @@ trait Infer extends Checkable {
val tvars1 = tvars map (_.cloneInternal)
// Note: right now it's not clear that solving is complete, or how it can be made complete!
// So we should come back to this and investigate.
- solve(tvars1, tvars1 map (_.origin.typeSymbol), tvars1 map (_ => Variance.Covariant), upper = false)
+ solve(tvars1, tvars1 map (_.origin.typeSymbol), tvars1 map (_ => Variance.Covariant), upper = false, Depth.AnyDepth)
}
// this is quite nasty: it destructively changes the info of the syms of e.g., method type params
@@ -1110,16 +1098,14 @@ trait Infer extends Checkable {
val TypeBounds(lo0, hi0) = tparam.info.bounds
val tb @ TypeBounds(lo1, hi1) = instBounds(tvar)
val enclCase = context.enclosingCaseDef
-
- log("\n" + sm"""
- |-----
- | enclCase: ${enclCase.tree}
- | saved: ${enclCase.savedTypeBounds}
- | tparam: ${tparam.shortSymbolClass}
- | def_s: ${tparam.defString}
- | seen_s: ${tparam.defStringSeenAs(tb)}
- |-----
- """.trim)
+ def enclCase_s = enclCase.toString.replaceAll("\\n", " ").take(60)
+
+ if (enclCase.savedTypeBounds.nonEmpty) log(
+ sm"""|instantiateTypeVar with nonEmpty saved type bounds {
+ | enclosing $enclCase_s
+ | saved ${enclCase.savedTypeBounds}
+ | tparam ${tparam.shortSymbolClass} ${tparam.defString}
+ |}""")
if (lo1 <:< hi1) {
if (lo1 <:< lo0 && hi0 <:< hi1) // bounds unimproved
diff --git a/src/compiler/scala/tools/nsc/typechecker/Namers.scala b/src/compiler/scala/tools/nsc/typechecker/Namers.scala
index 2bb2cc1ab4..454f913412 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Namers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Namers.scala
@@ -291,10 +291,13 @@ trait Namers extends MethodSynthesis {
}
private def logAssignSymbol(tree: Tree, sym: Symbol): Symbol = {
- sym.name.toTermName match {
+ if (isPastTyper) sym.name.toTermName match {
case nme.IMPORT | nme.OUTER | nme.ANON_CLASS_NAME | nme.ANON_FUN_NAME | nme.CONSTRUCTOR => ()
case _ =>
- log("[+symbol] " + sym.debugLocationString)
+ tree match {
+ case md: DefDef => log("[+symbol] " + sym.debugLocationString)
+ case _ =>
+ }
}
tree.symbol = sym
sym
@@ -1415,14 +1418,6 @@ trait Namers extends MethodSynthesis {
annCtx.setReportErrors()
// need to be lazy, #1782. beforeTyper to allow inferView in annotation args, SI-5892.
AnnotationInfo lazily {
- if (typer.context ne ctx)
- log(sm"""|The var `typer.context` in ${Namer.this} was mutated before the annotation ${ann} was forced.
- |
- |current value = ${typer.context}
- |original value = $ctx
- |
- |This confirms the hypothesis for the cause of SI-7603. If you see this message, please comment on that ticket.""")
-
enteringTyper(newTyper(annCtx) typedAnnotation ann)
}
}
diff --git a/src/compiler/scala/tools/nsc/typechecker/NamesDefaults.scala b/src/compiler/scala/tools/nsc/typechecker/NamesDefaults.scala
index 8e9933f734..dea4c46e79 100644
--- a/src/compiler/scala/tools/nsc/typechecker/NamesDefaults.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/NamesDefaults.scala
@@ -162,7 +162,7 @@ trait NamesDefaults { self: Analyzer =>
// never used for constructor calls, they always have a stable qualifier
def blockWithQualifier(qual: Tree, selected: Name) = {
- val sym = blockTyper.context.owner.newValue(unit.freshTermName("qual$"), qual.pos, newFlags = ARTIFACT) setInfo qual.tpe
+ val sym = blockTyper.context.owner.newValue(unit.freshTermName("qual$"), qual.pos, newFlags = ARTIFACT) setInfo uncheckedBounds(qual.tpe)
blockTyper.context.scope enter sym
val vd = atPos(sym.pos)(ValDef(sym, qual) setType NoType)
// it stays in Vegas: SI-5720, SI-5727
@@ -289,9 +289,10 @@ trait NamesDefaults { self: Analyzer =>
arg.tpe
}
).widen // have to widen or types inferred from literal defaults will be singletons
- val s = context.owner.newValue(unit.freshTermName("x$"), arg.pos, newFlags = ARTIFACT) setInfo (
- if (byName) functionType(Nil, argTpe) else argTpe
- )
+ val s = context.owner.newValue(unit.freshTermName("x$"), arg.pos, newFlags = ARTIFACT) setInfo {
+ val tp = if (byName) functionType(Nil, argTpe) else argTpe
+ uncheckedBounds(tp)
+ }
Some((context.scope.enter(s), byName, repeated))
})
map2(symPs, args) {
diff --git a/src/compiler/scala/tools/nsc/typechecker/PatternTypers.scala b/src/compiler/scala/tools/nsc/typechecker/PatternTypers.scala
index 7120aeaaa6..8bf9ce49be 100644
--- a/src/compiler/scala/tools/nsc/typechecker/PatternTypers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/PatternTypers.scala
@@ -340,11 +340,7 @@ trait PatternTypers {
// use "tree" for the context, not context.tree: don't make another CaseDef context,
// as instantiateTypeVar's bounds would end up there
- log(sm"""|convert to case constructor {
- | tree: $tree: ${tree.tpe}
- | ptSafe: $ptSafe
- | context.tree: ${context.tree}: ${context.tree.tpe}
- |}""".trim)
+ log(s"convert ${tree.summaryString}: ${tree.tpe} to case constructor, pt=$ptSafe")
val ctorContext = context.makeNewScope(tree, context.owner)
freeVars foreach ctorContext.scope.enter
diff --git a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala
index 5929cab1d1..32e908e03b 100644
--- a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala
@@ -1414,17 +1414,35 @@ abstract class RefChecks extends InfoTransform with scala.reflect.internal.trans
false
}
- private def checkTypeRef(tp: Type, tree: Tree) = tp match {
+ private def checkTypeRef(tp: Type, tree: Tree, skipBounds: Boolean) = tp match {
case TypeRef(pre, sym, args) =>
checkDeprecated(sym, tree.pos)
if(sym.isJavaDefined)
sym.typeParams foreach (_.cookJavaRawInfo())
- if (!tp.isHigherKinded)
+ if (!tp.isHigherKinded && !skipBounds)
checkBounds(tree, pre, sym.owner, sym.typeParams, args)
case _ =>
}
- private def checkAnnotations(tpes: List[Type], tree: Tree) = tpes foreach (tp => checkTypeRef(tp, tree))
+ private def checkTypeRefBounds(tp: Type, tree: Tree) = {
+ var skipBounds = false
+ tp match {
+ case AnnotatedType(ann :: Nil, underlying, selfSym) if ann.symbol == UncheckedBoundsClass =>
+ skipBounds = true
+ underlying
+ case TypeRef(pre, sym, args) =>
+ if (!tp.isHigherKinded && !skipBounds)
+ checkBounds(tree, pre, sym.owner, sym.typeParams, args)
+ tp
+ case _ =>
+ tp
+ }
+ }
+
+ private def checkAnnotations(tpes: List[Type], tree: Tree) = tpes foreach { tp =>
+ checkTypeRef(tp, tree, skipBounds = false)
+ checkTypeRefBounds(tp, tree)
+ }
private def doTypeTraversal(tree: Tree)(f: Type => Unit) = if (!inPattern) tree.tpe foreach f
private def applyRefchecksToAnnotations(tree: Tree): Unit = {
@@ -1453,8 +1471,9 @@ abstract class RefChecks extends InfoTransform with scala.reflect.internal.trans
}
doTypeTraversal(tree) {
- case AnnotatedType(annots, _, _) => applyChecks(annots)
- case _ =>
+ case tp @ AnnotatedType(annots, _, _) =>
+ applyChecks(annots)
+ case tp =>
}
case _ =>
}
@@ -1639,13 +1658,27 @@ abstract class RefChecks extends InfoTransform with scala.reflect.internal.trans
}
val existentialParams = new ListBuffer[Symbol]
- doTypeTraversal(tree) { // check all bounds, except those that are existential type parameters
- case ExistentialType(tparams, tpe) =>
+ var skipBounds = false
+ // check all bounds, except those that are existential type parameters
+ // or those within typed annotated with @uncheckedBounds
+ doTypeTraversal(tree) {
+ case tp @ ExistentialType(tparams, tpe) =>
existentialParams ++= tparams
- case t: TypeRef =>
- checkTypeRef(deriveTypeWithWildcards(existentialParams.toList)(t), tree)
+ case ann: AnnotatedType if ann.hasAnnotation(UncheckedBoundsClass) =>
+ // SI-7694 Allow code synthetizers to disable checking of bounds for TypeTrees based on inferred LUBs
+ // which might not conform to the constraints.
+ skipBounds = true
+ case tp: TypeRef =>
+ val tpWithWildcards = deriveTypeWithWildcards(existentialParams.toList)(tp)
+ checkTypeRef(tpWithWildcards, tree, skipBounds)
case _ =>
}
+ if (skipBounds) {
+ tree.tpe = tree.tpe.map {
+ _.filterAnnotations(_.symbol != UncheckedBoundsClass)
+ }
+ }
+
tree
case TypeApply(fn, args) =>
@@ -1715,6 +1748,8 @@ abstract class RefChecks extends InfoTransform with scala.reflect.internal.trans
inPattern = false
super.transform(result)
}
+ case ValDef(_, _, _, _) if treeInfo.hasSynthCaseSymbol(result) =>
+ deriveValDef(result)(transform) // SI-7716 Don't refcheck the tpt of the synthetic val that holds the selector.
case _ =>
super.transform(result)
}
diff --git a/src/compiler/scala/tools/nsc/typechecker/TypeDiagnostics.scala b/src/compiler/scala/tools/nsc/typechecker/TypeDiagnostics.scala
index 0c5f798c23..1af176736b 100644
--- a/src/compiler/scala/tools/nsc/typechecker/TypeDiagnostics.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/TypeDiagnostics.scala
@@ -350,11 +350,14 @@ trait TypeDiagnostics {
val strings = mutable.Map[String, Set[TypeDiag]]() withDefaultValue Set()
val names = mutable.Map[Name, Set[TypeDiag]]() withDefaultValue Set()
- def record(t: Type, sym: Symbol) = {
- val diag = TypeDiag(t, sym)
+ val localsSet = locals.toSet
- strings("" + t) += diag
- names(sym.name) += diag
+ def record(t: Type, sym: Symbol) = {
+ if (!localsSet(sym)) {
+ val diag = TypeDiag(t, sym)
+ strings("" + t) += diag
+ names(sym.name) += diag
+ }
}
for (tpe <- types ; t <- tpe) {
t match {
diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
index cccd0949a2..dd16b5be85 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
@@ -3717,7 +3717,7 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper
*
*/
def mkInvoke(cxTree: Tree, tree: Tree, qual: Tree, name: Name): Option[Tree] = {
- log(s"dyna.mkInvoke($cxTree, $tree, $qual, $name)")
+ debuglog(s"dyna.mkInvoke($cxTree, $tree, $qual, $name)")
val treeInfo.Applied(treeSelection, _, _) = tree
def isDesugaredApply = treeSelection match {
case Select(`qual`, nme.apply) => true
diff --git a/src/compiler/scala/tools/nsc/util/ClassPath.scala b/src/compiler/scala/tools/nsc/util/ClassPath.scala
index 7f9b81e1ec..906a575d90 100644
--- a/src/compiler/scala/tools/nsc/util/ClassPath.scala
+++ b/src/compiler/scala/tools/nsc/util/ClassPath.scala
@@ -16,6 +16,7 @@ import File.pathSeparator
import scala.collection.convert.WrapAsScala.enumerationAsScalaIterator
import java.net.MalformedURLException
import java.util.regex.PatternSyntaxException
+import scala.reflect.runtime.ReflectionUtils
/** <p>
* This module provides star expansion of '-classpath' option arguments, behaves the same as
@@ -80,7 +81,7 @@ object ClassPath {
}
/** A useful name filter. */
- def isTraitImplementation(name: String) = name endsWith "$class.class"
+ def isTraitImplementation(name: String) = ReflectionUtils.isTraitImplementation(name)
def specToURL(spec: String): Option[URL] =
try Some(new URL(spec))
@@ -139,7 +140,7 @@ object ClassPath {
}
object DefaultJavaContext extends JavaContext {
- override def isValidName(name: String) = !isTraitImplementation(name)
+ override def isValidName(name: String) = !ReflectionUtils.scalacShouldntLoadClassfile(name)
}
private def endsClass(s: String) = s.length > 6 && s.substring(s.length - 6) == ".class"
diff --git a/src/compiler/scala/tools/nsc/util/StackTracing.scala b/src/compiler/scala/tools/nsc/util/StackTracing.scala
new file mode 100644
index 0000000000..fa4fe29f28
--- /dev/null
+++ b/src/compiler/scala/tools/nsc/util/StackTracing.scala
@@ -0,0 +1,76 @@
+/* NSC -- new Scala compiler
+ * Copyright 2005-2013 LAMP/EPFL
+ */
+
+package scala.tools.nsc.util
+
+private[util] trait StackTracing extends Any {
+
+ /** Format a stack trace, returning the prefix consisting of frames that satisfy
+ * a given predicate.
+ * The format is similar to the typical case described in the JavaDoc
+ * for [[java.lang.Throwable#printStackTrace]].
+ * If a stack trace is truncated, it will be followed by a line of the form
+ * `... 3 elided`, by analogy to the lines `... 3 more` which indicate
+ * shared stack trace segments.
+ * @param e the exception
+ * @param p the predicate to select the prefix
+ */
+ def stackTracePrefixString(e: Throwable)(p: StackTraceElement => Boolean): String = {
+ import collection.mutable.{ ArrayBuffer, ListBuffer }
+ import compat.Platform.EOL
+ import util.Properties.isJavaAtLeast
+
+ val sb = ListBuffer.empty[String]
+
+ type TraceRelation = String
+ val Self = new TraceRelation("")
+ val CausedBy = new TraceRelation("Caused by: ")
+ val Suppressed = new TraceRelation("Suppressed: ")
+
+ val suppressable = isJavaAtLeast("1.7")
+
+ def clazz(e: Throwable) = e.getClass.getName
+ def because(e: Throwable): String = e.getCause match { case null => null ; case c => header(c) }
+ def msg(e: Throwable): String = e.getMessage match { case null => because(e) ; case s => s }
+ def txt(e: Throwable): String = msg(e) match { case null => "" ; case s => s": $s" }
+ def header(e: Throwable): String = s"${clazz(e)}${txt(e)}"
+
+ val indent = "\u0020\u0020"
+
+ val seen = new ArrayBuffer[Throwable](16)
+ def unseen(t: Throwable) = {
+ def inSeen = seen exists (_ eq t)
+ val interesting = (t != null) && !inSeen
+ if (interesting) seen += t
+ interesting
+ }
+
+ def print(e: Throwable, r: TraceRelation, share: Array[StackTraceElement], indents: Int): Unit = if (unseen(e)) {
+ val trace = e.getStackTrace
+ val frames = (
+ if (share.nonEmpty) {
+ val spare = share.reverseIterator
+ val trimmed = trace.reverse dropWhile (spare.hasNext && spare.next == _)
+ trimmed.reverse
+ } else trace
+ )
+ val prefix = frames takeWhile p
+ val margin = indent * indents
+ val indented = margin + indent
+ sb append s"${margin}${r}${header(e)}"
+ prefix foreach (f => sb append s"${indented}at $f")
+ if (frames.size < trace.size) sb append s"$indented... ${trace.size - frames.size} more"
+ if (r == Self && prefix.size < frames.size) sb append s"$indented... ${frames.size - prefix.size} elided"
+ print(e.getCause, CausedBy, trace, indents)
+ if (suppressable) {
+ import scala.language.reflectiveCalls
+ type Suppressing = { def getSuppressed(): Array[Throwable] }
+ for (s <- e.asInstanceOf[Suppressing].getSuppressed) print(s, Suppressed, frames, indents + 1)
+ }
+ }
+ print(e, Self, share = Array.empty, indents = 0)
+
+ sb mkString EOL
+ }
+}
diff --git a/src/compiler/scala/tools/nsc/util/package.scala b/src/compiler/scala/tools/nsc/util/package.scala
index ea3c9d8dde..72a4bbf5c0 100644
--- a/src/compiler/scala/tools/nsc/util/package.scala
+++ b/src/compiler/scala/tools/nsc/util/package.scala
@@ -8,7 +8,6 @@ package tools
package nsc
import java.io.{ OutputStream, PrintStream, ByteArrayOutputStream, PrintWriter, StringWriter }
-import scala.compat.Platform.EOL
package object util {
@@ -79,12 +78,17 @@ package object util {
s"$clazz$msg @ $frame"
}
- def stackTracePrefixString(ex: Throwable)(p: StackTraceElement => Boolean): String = {
- val frames = ex.getStackTrace takeWhile p map (" at " + _)
- val msg = ex.getMessage match { case null => "" ; case s => s": $s" }
- val clazz = ex.getClass.getName
-
- s"$clazz$msg" +: frames mkString EOL
+ implicit class StackTraceOps(val e: Throwable) extends AnyVal with StackTracing {
+ /** Format the stack trace, returning the prefix consisting of frames that satisfy
+ * a given predicate.
+ * The format is similar to the typical case described in the JavaDoc
+ * for [[java.lang.Throwable#printStackTrace]].
+ * If a stack trace is truncated, it will be followed by a line of the form
+ * `... 3 elided`, by analogy to the lines `... 3 more` which indicate
+ * shared stack trace segments.
+ * @param p the predicate to select the prefix
+ */
+ def stackTracePrefixString(p: StackTraceElement => Boolean): String = stackTracePrefixString(e)(p)
}
lazy val trace = new SimpleTracer(System.out)
diff --git a/src/compiler/scala/tools/reflect/ToolBoxFactory.scala b/src/compiler/scala/tools/reflect/ToolBoxFactory.scala
index 8d2f200e99..57ebe1b30d 100644
--- a/src/compiler/scala/tools/reflect/ToolBoxFactory.scala
+++ b/src/compiler/scala/tools/reflect/ToolBoxFactory.scala
@@ -12,6 +12,7 @@ import java.lang.{Class => jClass}
import scala.compat.Platform.EOL
import scala.reflect.NameTransformer
import scala.reflect.api.JavaUniverse
+import scala.reflect.io.NoAbstractFile
abstract class ToolBoxFactory[U <: JavaUniverse](val u: U) { factorySelf =>
@@ -136,7 +137,9 @@ abstract class ToolBoxFactory[U <: JavaUniverse](val u: U) { factorySelf =>
val wrapper2 = if (!withMacrosDisabled) (currentTyper.context.withMacrosEnabled[Tree] _) else (currentTyper.context.withMacrosDisabled[Tree] _)
def wrapper (tree: => Tree) = wrapper1(wrapper2(tree))
- phase = (new Run).typerPhase // need to set a phase to something <= typerPhase, otherwise implicits in typedSelect will be disabled
+ val run = new Run
+ run.symSource(ownerClass) = NoAbstractFile // need to set file to something different from null, so that currentRun.defines works
+ phase = run.typerPhase // need to set a phase to something <= typerPhase, otherwise implicits in typedSelect will be disabled
currentTyper.context.setReportErrors() // need to manually set context mode, otherwise typer.silent will throw exceptions
reporter.reset()
diff --git a/src/interactive/scala/tools/nsc/interactive/Global.scala b/src/interactive/scala/tools/nsc/interactive/Global.scala
index 492f0f4fb4..721fbf24c7 100644
--- a/src/interactive/scala/tools/nsc/interactive/Global.scala
+++ b/src/interactive/scala/tools/nsc/interactive/Global.scala
@@ -140,6 +140,7 @@ class Global(settings: Settings, _reporter: Reporter, projectName: String = "")
abort("originalOwner is not kept in presentation compiler runs.")
override def forInteractive = true
+ override protected def synchronizeNames = true
override def newAsSeenFromMap(pre: Type, clazz: Symbol): AsSeenFromMap =
new InteractiveAsSeenFromMap(pre, clazz)
diff --git a/src/partest-extras/scala/tools/partest/ReplTest.scala b/src/partest-extras/scala/tools/partest/ReplTest.scala
index 7cc2dd39a9..38662c34b5 100644
--- a/src/partest-extras/scala/tools/partest/ReplTest.scala
+++ b/src/partest-extras/scala/tools/partest/ReplTest.scala
@@ -30,14 +30,30 @@ abstract class ReplTest extends DirectTest {
def show() = eval() foreach println
}
+/** Run a REPL test from a session transcript.
+ * The `session` should be a triple-quoted String starting
+ * with the `Type in expressions` message and ending
+ * after the final `prompt`, including the last space.
+ */
abstract class SessionTest extends ReplTest {
+ /** Session transcript, as a triple-quoted, multiline, marginalized string. */
def session: String
- override final def code = expected filter (_.startsWith(prompt)) map (_.drop(prompt.length)) mkString "\n"
- def expected = session.stripMargin.lines.toList
+
+ /** Expected output, as an iterator. */
+ def expected = session.stripMargin.lines
+
+ /** Code is the command list culled from the session (or the expected session output).
+ * Would be nicer if code were lazy lines.
+ */
+ override final def code = expected filter (_ startsWith prompt) map (_ drop prompt.length) mkString "\n"
+
final def prompt = "scala> "
+
+ /** Default test is to compare expected and actual output and emit the diff on a failed comparison. */
override def show() = {
- val out = eval().toList
- if (out.size != expected.size) Console println s"Expected ${expected.size} lines, got ${out.size}"
- if (out != expected) Console print nest.FileManager.compareContents(expected, out, "expected", "actual")
+ val evaled = eval().toList
+ val wanted = expected.toList
+ if (evaled.size != wanted.size) Console println s"Expected ${wanted.size} lines, got ${evaled.size}"
+ if (evaled != wanted) Console print nest.FileManager.compareContents(wanted, evaled, "expected", "actual")
}
}
diff --git a/src/reflect/scala/reflect/internal/BaseTypeSeqs.scala b/src/reflect/scala/reflect/internal/BaseTypeSeqs.scala
index e3498a95a6..05aaa462c4 100644
--- a/src/reflect/scala/reflect/internal/BaseTypeSeqs.scala
+++ b/src/reflect/scala/reflect/internal/BaseTypeSeqs.scala
@@ -130,9 +130,9 @@ trait BaseTypeSeqs {
lazy val maxDepth = maxDepthOfElems
- protected def maxDepthOfElems: Int = {
- var d = 0
- for (i <- 1 until length) d = max(d, typeDepth(elems(i)))
+ protected def maxDepthOfElems: Depth = {
+ var d = Depth.Zero
+ 1 until length foreach (i => d = d max typeDepth(elems(i)))
d
}
@@ -234,7 +234,7 @@ trait BaseTypeSeqs {
override def map(g: Type => Type) = lateMap(g)
override def lateMap(g: Type => Type) = orig.lateMap(x => g(f(x)))
override def exists(p: Type => Boolean) = elems exists (x => p(f(x)))
- override protected def maxDepthOfElems: Int = elems.map(x => typeDepth(f(x))).max
+ override protected def maxDepthOfElems: Depth = elems.map(x => typeDepth(f(x))).max
override def toString = elems.mkString("MBTS(", ",", ")")
}
diff --git a/src/reflect/scala/reflect/internal/ClassfileConstants.scala b/src/reflect/scala/reflect/internal/ClassfileConstants.scala
index a7ce044780..e0a6757d34 100644
--- a/src/reflect/scala/reflect/internal/ClassfileConstants.scala
+++ b/src/reflect/scala/reflect/internal/ClassfileConstants.scala
@@ -335,13 +335,8 @@ object ClassfileConstants {
abstract class FlagTranslation {
import Flags._
- private var isAnnotation = false
- private var isClass = false
- private def initFields(flags: Int) = {
- isAnnotation = (flags & JAVA_ACC_ANNOTATION) != 0
- isClass = false
- }
- private def translateFlag(jflag: Int): Long = (jflag: @switch) match {
+ private def isAnnotation(flags: Int): Boolean = (flags & JAVA_ACC_ANNOTATION) != 0
+ private def translateFlag(jflag: Int, isAnnotation: Boolean, isClass: Boolean): Long = (jflag: @switch) match {
case JAVA_ACC_PRIVATE => PRIVATE
case JAVA_ACC_PROTECTED => PROTECTED
case JAVA_ACC_FINAL => FINAL
@@ -351,31 +346,28 @@ object ClassfileConstants {
case JAVA_ACC_INTERFACE => if (isAnnotation) 0L else TRAIT | INTERFACE | ABSTRACT
case _ => 0L
}
- private def translateFlags(jflags: Int, baseFlags: Long): Long = {
+ private def translateFlags(jflags: Int, baseFlags: Long, isAnnotation: Boolean, isClass: Boolean): Long = {
+ def translateFlag0(jflags: Int): Long = translateFlag(jflags, isAnnotation, isClass)
var res: Long = JAVA | baseFlags
/* fast, elegant, maintainable, pick any two... */
- res |= translateFlag(jflags & JAVA_ACC_PRIVATE)
- res |= translateFlag(jflags & JAVA_ACC_PROTECTED)
- res |= translateFlag(jflags & JAVA_ACC_FINAL)
- res |= translateFlag(jflags & JAVA_ACC_SYNTHETIC)
- res |= translateFlag(jflags & JAVA_ACC_STATIC)
- res |= translateFlag(jflags & JAVA_ACC_ABSTRACT)
- res |= translateFlag(jflags & JAVA_ACC_INTERFACE)
+ res |= translateFlag0(jflags & JAVA_ACC_PRIVATE)
+ res |= translateFlag0(jflags & JAVA_ACC_PROTECTED)
+ res |= translateFlag0(jflags & JAVA_ACC_FINAL)
+ res |= translateFlag0(jflags & JAVA_ACC_SYNTHETIC)
+ res |= translateFlag0(jflags & JAVA_ACC_STATIC)
+ res |= translateFlag0(jflags & JAVA_ACC_ABSTRACT)
+ res |= translateFlag0(jflags & JAVA_ACC_INTERFACE)
res
}
def classFlags(jflags: Int): Long = {
- initFields(jflags)
- isClass = true
- translateFlags(jflags, 0)
+ translateFlags(jflags, 0, isAnnotation(jflags), isClass = true)
}
def fieldFlags(jflags: Int): Long = {
- initFields(jflags)
- translateFlags(jflags, if ((jflags & JAVA_ACC_FINAL) == 0) MUTABLE else 0)
+ translateFlags(jflags, if ((jflags & JAVA_ACC_FINAL) == 0) MUTABLE else 0 , isAnnotation(jflags), isClass = false)
}
def methodFlags(jflags: Int): Long = {
- initFields(jflags)
- translateFlags(jflags, if ((jflags & JAVA_ACC_BRIDGE) != 0) BRIDGE | ARTIFACT else 0)
+ translateFlags(jflags, if ((jflags & JAVA_ACC_BRIDGE) != 0) BRIDGE | ARTIFACT else 0, isAnnotation(jflags), isClass = false)
}
}
object FlagTranslation extends FlagTranslation { }
diff --git a/src/reflect/scala/reflect/internal/Definitions.scala b/src/reflect/scala/reflect/internal/Definitions.scala
index 92f2a64ce9..90a1ab39d5 100644
--- a/src/reflect/scala/reflect/internal/Definitions.scala
+++ b/src/reflect/scala/reflect/internal/Definitions.scala
@@ -1004,6 +1004,7 @@ trait Definitions extends api.StandardDefinitions {
lazy val ThrowsClass = requiredClass[scala.throws[_]]
lazy val TransientAttr = requiredClass[scala.transient]
lazy val UncheckedClass = requiredClass[scala.unchecked]
+ lazy val UncheckedBoundsClass = getClassIfDefined("scala.reflect.internal.annotations.uncheckedBounds")
lazy val UnspecializedClass = requiredClass[scala.annotation.unspecialized]
lazy val VolatileAttr = requiredClass[scala.volatile]
diff --git a/src/reflect/scala/reflect/internal/Depth.scala b/src/reflect/scala/reflect/internal/Depth.scala
new file mode 100644
index 0000000000..357abf765f
--- /dev/null
+++ b/src/reflect/scala/reflect/internal/Depth.scala
@@ -0,0 +1,28 @@
+package scala
+package reflect
+package internal
+
+import Depth._
+
+final class Depth private (val depth: Int) extends AnyVal with Ordered[Depth] {
+ def max(that: Depth): Depth = if (this < that) that else this
+ def decr(n: Int): Depth = if (isAnyDepth) this else Depth(depth - n)
+ def incr(n: Int): Depth = if (isAnyDepth) this else Depth(depth + n)
+ def decr: Depth = decr(1)
+ def incr: Depth = incr(1)
+
+ def isNegative = depth < 0
+ def isZero = depth == 0
+ def isAnyDepth = this == AnyDepth
+
+ def compare(that: Depth): Int = if (depth < that.depth) -1 else if (this == that) 0 else 1
+ override def toString = s"Depth($depth)"
+}
+
+object Depth {
+ // A don't care value for the depth parameter in lubs/glbs and related operations.
+ final val AnyDepth = new Depth(Int.MinValue)
+ final val Zero = new Depth(0)
+
+ @inline final def apply(depth: Int): Depth = if (depth < 0) AnyDepth else new Depth(depth)
+}
diff --git a/src/reflect/scala/reflect/internal/Importers.scala b/src/reflect/scala/reflect/internal/Importers.scala
index b0828e9c54..9ddf156128 100644
--- a/src/reflect/scala/reflect/internal/Importers.scala
+++ b/src/reflect/scala/reflect/internal/Importers.scala
@@ -411,6 +411,11 @@ trait Importers extends api.Importers { to: SymbolTable =>
if (my != null) {
addFixup(recreatedTreeCompleter(their, my))
tryFixup()
+ // we have to be careful with position import as some shared trees
+ // like EmptyTree, emptyValDef don't support position assignment
+ if (their.pos != NoPosition) {
+ my.setPos(importPosition(their.pos))
+ }
}
my
}
diff --git a/src/reflect/scala/reflect/internal/Names.scala b/src/reflect/scala/reflect/internal/Names.scala
index 0d78e24548..ed248d6e1e 100644
--- a/src/reflect/scala/reflect/internal/Names.scala
+++ b/src/reflect/scala/reflect/internal/Names.scala
@@ -18,6 +18,18 @@ trait Names extends api.Names {
final val nameDebug = false
+ // Ideally we would just synchronize unconditionally and let HotSpot's Biased Locking
+ // kick in in the compiler universe, where access to the lock is single threaded. But,
+ // objects created in the first 4seconds of the JVM startup aren't eligible for biased
+ // locking.
+ //
+ // We might also be able to accept the performance hit, but we don't have tools to
+ // detect performance regressions.
+ //
+ // Discussion: https://groups.google.com/forum/#!search/biased$20scala-internals/scala-internals/0cYB7SkJ-nM/47MLhsgw8jwJ
+ protected def synchronizeNames: Boolean = false
+ private val nameLock: Object = new Object
+
/** Memory to store all names sequentially. */
var chrs: Array[Char] = new Array[Char](NAME_SIZE)
private var nc = 0
@@ -64,61 +76,68 @@ trait Names extends api.Names {
}
/** Create a term name from the characters in cs[offset..offset+len-1]. */
- def newTermName(cs: Array[Char], offset: Int, len: Int): TermName =
+ final def newTermName(cs: Array[Char], offset: Int, len: Int): TermName =
newTermName(cs, offset, len, cachedString = null)
- def newTermName(cs: Array[Char]): TermName = newTermName(cs, 0, cs.length)
- def newTypeName(cs: Array[Char]): TypeName = newTypeName(cs, 0, cs.length)
+ final def newTermName(cs: Array[Char]): TermName = newTermName(cs, 0, cs.length)
+
+ final def newTypeName(cs: Array[Char]): TypeName = newTypeName(cs, 0, cs.length)
/** Create a term name from the characters in cs[offset..offset+len-1].
* TODO - have a mode where name validation is performed at creation time
* (e.g. if a name has the string "$class" in it, then fail if that
* string is not at the very end.)
*/
- protected def newTermName(cs: Array[Char], offset: Int, len: Int, cachedString: String): TermName = {
- val h = hashValue(cs, offset, len) & HASH_MASK
- var n = termHashtable(h)
- while ((n ne null) && (n.length != len || !equals(n.start, cs, offset, len)))
- n = n.next
-
- if (n ne null) n
- else {
- // The logic order here is future-proofing against the possibility
- // that name.toString will become an eager val, in which case the call
- // to enterChars cannot follow the construction of the TermName.
- val ncStart = nc
- enterChars(cs, offset, len)
- if (cachedString ne null) new TermName_S(ncStart, len, h, cachedString)
- else new TermName_R(ncStart, len, h)
+ final def newTermName(cs: Array[Char], offset: Int, len: Int, cachedString: String): TermName = {
+ def body = {
+ val h = hashValue(cs, offset, len) & HASH_MASK
+ var n = termHashtable(h)
+ while ((n ne null) && (n.length != len || !equals(n.start, cs, offset, len)))
+ n = n.next
+
+ if (n ne null) n
+ else {
+ // The logic order here is future-proofing against the possibility
+ // that name.toString will become an eager val, in which case the call
+ // to enterChars cannot follow the construction of the TermName.
+ val ncStart = nc
+ enterChars(cs, offset, len)
+ if (cachedString ne null) new TermName_S(ncStart, len, h, cachedString)
+ else new TermName_R(ncStart, len, h)
+ }
}
+ if (synchronizeNames) nameLock.synchronized(body) else body
}
- protected def newTypeName(cs: Array[Char], offset: Int, len: Int, cachedString: String): TypeName =
+
+ final def newTypeName(cs: Array[Char], offset: Int, len: Int, cachedString: String): TypeName =
newTermName(cs, offset, len, cachedString).toTypeName
/** Create a term name from string. */
+ @deprecatedOverriding("To synchronize, use `override def synchronizeNames = true`", "2.11.0") // overriden in https://github.com/scala-ide/scala-ide/blob/master/org.scala-ide.sdt.core/src/scala/tools/eclipse/ScalaPresentationCompiler.scala
def newTermName(s: String): TermName = newTermName(s.toCharArray(), 0, s.length(), null)
/** Create a type name from string. */
+ @deprecatedOverriding("To synchronize, use `override def synchronizeNames = true`", "2.11.0") // overriden in https://github.com/scala-ide/scala-ide/blob/master/org.scala-ide.sdt.core/src/scala/tools/eclipse/ScalaPresentationCompiler.scala
def newTypeName(s: String): TypeName = newTermName(s).toTypeName
/** Create a term name from the UTF8 encoded bytes in bs[offset..offset+len-1]. */
- def newTermName(bs: Array[Byte], offset: Int, len: Int): TermName = {
+ final def newTermName(bs: Array[Byte], offset: Int, len: Int): TermName = {
val chars = Codec.fromUTF8(bs, offset, len)
newTermName(chars, 0, chars.length)
}
- def newTermNameCached(s: String): TermName =
+ final def newTermNameCached(s: String): TermName =
newTermName(s.toCharArray(), 0, s.length(), cachedString = s)
- def newTypeNameCached(s: String): TypeName =
+ final def newTypeNameCached(s: String): TypeName =
newTypeName(s.toCharArray(), 0, s.length(), cachedString = s)
/** Create a type name from the characters in cs[offset..offset+len-1]. */
- def newTypeName(cs: Array[Char], offset: Int, len: Int): TypeName =
+ final def newTypeName(cs: Array[Char], offset: Int, len: Int): TypeName =
newTermName(cs, offset, len, cachedString = null).toTypeName
/** Create a type name from the UTF8 encoded bytes in bs[offset..offset+len-1]. */
- def newTypeName(bs: Array[Byte], offset: Int, len: Int): TypeName =
+ final def newTypeName(bs: Array[Byte], offset: Int, len: Int): TypeName =
newTermName(bs, offset, len).toTypeName
/**
@@ -128,6 +147,8 @@ trait Names extends api.Names {
* For those of METHOD sort, its descriptor is stored ie has a leading '('
*
* can-multi-thread
+ * TODO SI-6240 !!! JZ Really? the constructors TermName and TypeName publish unconstructed `this` references
+ * into the hash tables; we could observe them here before the subclass constructor completes.
*/
final def lookupTypeName(cs: Array[Char]): TypeName = { lookupTypeNameIfExisting(cs, true) }
@@ -494,23 +515,26 @@ trait Names extends api.Names {
override def toString = new String(chrs, index, len)
}
+ // SYNCNOTE: caller to constructor must synchronize if `synchronizeNames` is enabled
sealed abstract class TermName(index0: Int, len0: Int, hash: Int) extends Name(index0, len0) {
type ThisNameType = TermName
protected[this] def thisName: TermName = this
-
val next: TermName = termHashtable(hash)
termHashtable(hash) = this
def isTermName: Boolean = true
def isTypeName: Boolean = false
def toTermName: TermName = this
def toTypeName: TypeName = {
- val h = hashValue(chrs, index, len) & HASH_MASK
- var n = typeHashtable(h)
- while ((n ne null) && n.start != index)
- n = n.next
-
- if (n ne null) n
- else createCompanionName(h)
+ def body = {
+ val h = hashValue(chrs, index, len) & HASH_MASK
+ var n = typeHashtable(h)
+ while ((n ne null) && n.start != index)
+ n = n.next
+
+ if (n ne null) n
+ else createCompanionName(h)
+ }
+ if (synchronizeNames) nameLock.synchronized(body) else body
}
def newName(str: String): TermName = newTermName(str)
def companionName: TypeName = toTypeName
@@ -518,6 +542,7 @@ trait Names extends api.Names {
newTermName(chrs, start + from, to - from)
def nameKind = "term"
+ /** SYNCNOTE: caller must synchronize if `synchronizeNames` is enabled */
protected def createCompanionName(h: Int): TypeName
}
@@ -534,16 +559,20 @@ trait Names extends api.Names {
val next: TypeName = typeHashtable(hash)
typeHashtable(hash) = this
+
def isTermName: Boolean = false
def isTypeName: Boolean = true
def toTermName: TermName = {
- val h = hashValue(chrs, index, len) & HASH_MASK
- var n = termHashtable(h)
- while ((n ne null) && n.start != index)
- n = n.next
-
- if (n ne null) n
- else createCompanionName(h)
+ def body = {
+ val h = hashValue(chrs, index, len) & HASH_MASK
+ var n = termHashtable(h)
+ while ((n ne null) && n.start != index)
+ n = n.next
+
+ if (n ne null) n
+ else createCompanionName(h)
+ }
+ if (synchronizeNames) nameLock.synchronized(body) else body
}
def toTypeName: TypeName = this
def newName(str: String): TypeName = newTypeName(str)
@@ -553,6 +582,7 @@ trait Names extends api.Names {
def nameKind = "type"
override def decode = if (nameDebug) super.decode + "!" else super.decode
+ /** SYNCNOTE: caller must synchronize if `synchronizeNames` is enabled */
protected def createCompanionName(h: Int): TermName
}
diff --git a/src/reflect/scala/reflect/internal/Printers.scala b/src/reflect/scala/reflect/internal/Printers.scala
index 1603029340..206dff44e2 100644
--- a/src/reflect/scala/reflect/internal/Printers.scala
+++ b/src/reflect/scala/reflect/internal/Printers.scala
@@ -574,6 +574,8 @@ trait Printers extends api.Printers { self: SymbolTable =>
case refTree: RefTree =>
if (tree.symbol.name != refTree.name) print("[", tree.symbol, " aka ", refTree.name, "]")
else print(tree.symbol)
+ case defTree: DefTree =>
+ print(tree.symbol)
case _ =>
print(tree.symbol.name)
}
diff --git a/src/reflect/scala/reflect/internal/Symbols.scala b/src/reflect/scala/reflect/internal/Symbols.scala
index a8efa938c8..d3a0ffb744 100644
--- a/src/reflect/scala/reflect/internal/Symbols.scala
+++ b/src/reflect/scala/reflect/internal/Symbols.scala
@@ -147,7 +147,7 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
def name: NameType
def name_=(n: Name): Unit = {
if (shouldLogAtThisPhase) {
- val msg = s"Renaming $fullLocationString to $n"
+ def msg = s"In $owner, renaming $name -> $n"
if (isSpecialized) debuglog(msg) else log(msg)
}
}
@@ -2524,7 +2524,14 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
}
def infosString = infos.toString
- def debugLocationString = fullLocationString + " (flags: " + debugFlagString + ")"
+ def debugLocationString = {
+ val pre = flagString match {
+ case "" => ""
+ case s if s contains ' ' => "(" + s + ") "
+ case s => s + " "
+ }
+ pre + fullLocationString
+ }
private def defStringCompose(infoString: String) = compose(
flagString,
diff --git a/src/reflect/scala/reflect/internal/Types.scala b/src/reflect/scala/reflect/internal/Types.scala
index b4ae384594..9c66dc476f 100644
--- a/src/reflect/scala/reflect/internal/Types.scala
+++ b/src/reflect/scala/reflect/internal/Types.scala
@@ -17,6 +17,7 @@ import scala.annotation.tailrec
import util.Statistics
import util.ThreeValues._
import Variance._
+import Depth._
/* A standard type pattern match:
case ErrorType =>
@@ -93,12 +94,6 @@ trait Types
private final val LogPendingBaseTypesThreshold = DefaultLogThreshhold
private final val LogVolatileThreshold = DefaultLogThreshhold
- /** A don't care value for the depth parameter in lubs/glbs and related operations. */
- protected[internal] final val AnyDepth = -3
-
- /** Decrement depth unless it is a don't care. */
- protected[internal] final def decr(depth: Int) = if (depth == AnyDepth) AnyDepth else depth - 1
-
private final val traceTypeVars = sys.props contains "scalac.debug.tvar"
private final val breakCycles = settings.breakCycles.value
/** In case anyone wants to turn off type parameter bounds being used
@@ -784,8 +779,8 @@ trait Types
if (Statistics.canEnable) stat_<:<(that)
else {
(this eq that) ||
- (if (explainSwitch) explain("<:", isSubType, this, that)
- else isSubType(this, that, AnyDepth))
+ (if (explainSwitch) explain("<:", isSubType(_: Type, _: Type), this, that)
+ else isSubType(this, that))
}
}
@@ -805,7 +800,7 @@ trait Types
case TypeRef(_, sym, args) =>
val that1 = existentialAbstraction(args map (_.typeSymbol), that)
(that ne that1) && (this <:< that1) && {
- log(s"$this.matchesPattern($that) depended on discarding args and testing <:< $that1")
+ debuglog(s"$this.matchesPattern($that) depended on discarding args and testing <:< $that1")
true
}
case _ =>
@@ -817,8 +812,8 @@ trait Types
val start = if (Statistics.canEnable) Statistics.pushTimer(typeOpsStack, subtypeNanos) else null
val result =
(this eq that) ||
- (if (explainSwitch) explain("<:", isSubType, this, that)
- else isSubType(this, that, AnyDepth))
+ (if (explainSwitch) explain("<:", isSubType(_: Type, _: Type), this, that)
+ else isSubType(this, that))
if (Statistics.canEnable) Statistics.popTimer(typeOpsStack, start)
result
}
@@ -883,7 +878,7 @@ trait Types
/** The maximum depth (@see typeDepth)
* of each type in the BaseTypeSeq of this type except the first.
*/
- def baseTypeSeqDepth: Int = 1
+ def baseTypeSeqDepth: Depth = Depth(1)
/** The list of all baseclasses of this type (including its own typeSymbol)
* in linearization order, starting with the class itself and ending
@@ -1220,7 +1215,7 @@ trait Types
override def decls: Scope = supertype.decls
override def baseType(clazz: Symbol): Type = supertype.baseType(clazz)
override def baseTypeSeq: BaseTypeSeq = supertype.baseTypeSeq
- override def baseTypeSeqDepth: Int = supertype.baseTypeSeqDepth
+ override def baseTypeSeqDepth: Depth = supertype.baseTypeSeqDepth
override def baseClasses: List[Symbol] = supertype.baseClasses
}
@@ -1514,7 +1509,7 @@ trait Types
}
}
- override def baseTypeSeqDepth: Int = baseTypeSeq.maxDepth
+ override def baseTypeSeqDepth: Depth = baseTypeSeq.maxDepth
override def baseClasses: List[Symbol] = {
val cached = baseClassesCache
@@ -2603,7 +2598,7 @@ trait Types
override def parents: List[Type] = resultType.parents
override def decls: Scope = resultType.decls
override def baseTypeSeq: BaseTypeSeq = resultType.baseTypeSeq
- override def baseTypeSeqDepth: Int = resultType.baseTypeSeqDepth
+ override def baseTypeSeqDepth: Depth = resultType.baseTypeSeqDepth
override def baseClasses: List[Symbol] = resultType.baseClasses
override def baseType(clazz: Symbol): Type = resultType.baseType(clazz)
override def boundSyms = resultType.boundSyms
@@ -2642,7 +2637,7 @@ trait Types
override def boundSyms = immutable.Set[Symbol](typeParams ++ resultType.boundSyms: _*)
override def prefix: Type = resultType.prefix
override def baseTypeSeq: BaseTypeSeq = resultType.baseTypeSeq
- override def baseTypeSeqDepth: Int = resultType.baseTypeSeqDepth
+ override def baseTypeSeqDepth: Depth = resultType.baseTypeSeqDepth
override def baseClasses: List[Symbol] = resultType.baseClasses
override def baseType(clazz: Symbol): Type = resultType.baseType(clazz)
override def narrow: Type = resultType.narrow
@@ -2777,13 +2772,13 @@ trait Types
def withTypeVars(op: Type => Boolean): Boolean = withTypeVars(op, AnyDepth)
- def withTypeVars(op: Type => Boolean, depth: Int): Boolean = {
+ def withTypeVars(op: Type => Boolean, depth: Depth): Boolean = {
val quantifiedFresh = cloneSymbols(quantified)
val tvars = quantifiedFresh map (tparam => TypeVar(tparam))
val underlying1 = underlying.instantiateTypeParams(quantified, tvars) // fuse subst quantified -> quantifiedFresh -> tvars
op(underlying1) && {
solve(tvars, quantifiedFresh, quantifiedFresh map (_ => Invariant), upper = false, depth) &&
- isWithinBounds(NoPrefix, NoSymbol, quantifiedFresh, tvars map (_.constr.inst))
+ isWithinBounds(NoPrefix, NoSymbol, quantifiedFresh, tvars map (_.inst))
}
}
}
@@ -2847,6 +2842,9 @@ trait Types
// but pattern-matching returned the original constr0 (a bug)
// now, pattern-matching returns the most recent constr
object TypeVar {
+ private val ConstantTrue = ConstantType(Constant(true))
+ private val ConstantFalse = ConstantType(Constant(false))
+
@inline final def trace[T](action: String, msg: => String)(value: T): T = {
if (traceTypeVars) {
val s = msg match {
@@ -2984,7 +2982,9 @@ trait Types
* or `encounteredHigherLevel` or `suspended` accesses should be necessary.
*/
def instValid = constr.instValid
- override def isGround = instValid && constr.inst.isGround
+ def inst = constr.inst
+ def instWithinBounds = constr.instWithinBounds
+ override def isGround = instValid && inst.isGround
/** The variable's skolemization level */
val level = skolemizationLevel
@@ -3003,6 +3003,7 @@ trait Types
this
else if (newArgs.size == params.size) {
val tv = TypeVar(origin, constr, newArgs, params)
+ tv.linkSuspended(this)
TypeVar.trace("applyArgs", "In " + originLocation + ", apply args " + newArgs.mkString(", ") + " to " + originName)(tv)
}
else
@@ -3025,8 +3026,7 @@ trait Types
// When comparing to types containing skolems, remember the highest level
// of skolemization. If that highest level is higher than our initial
// skolemizationLevel, we can't re-use those skolems as the solution of this
- // typevar, which means we'll need to repack our constr.inst into a fresh
- // existential.
+ // typevar, which means we'll need to repack our inst into a fresh existential.
// were we compared to skolems at a higher skolemizationLevel?
// EXPERIMENTAL: value will not be considered unless enableTypeVarExperimentals is true
// see SI-5729 for why this is still experimental
@@ -3065,7 +3065,16 @@ trait Types
// </region>
// ignore subtyping&equality checks while true -- see findMember
- private[Types] var suspended = false
+ // OPT: This could be Either[TypeVar, Boolean], but this encoding was chosen instead to save allocations.
+ private var _suspended: Type = TypeVar.ConstantFalse
+ private[Types] def suspended: Boolean = (_suspended: @unchecked) match {
+ case TypeVar.ConstantFalse => false
+ case TypeVar.ConstantTrue => true
+ case tv: TypeVar => tv.suspended
+ }
+ private[Types] def suspended_=(b: Boolean): Unit = _suspended = if (b) TypeVar.ConstantTrue else TypeVar.ConstantFalse
+ // SI-7785 Link the suspended attribute of a TypeVar created in, say, a TypeMap (e.g. AsSeenFrom) to its originator
+ private[Types] def linkSuspended(origin: TypeVar): Unit = _suspended = origin
/** Called when a TypeVar is involved in a subtyping check. Result is whether
* this TypeVar could plausibly be a [super/sub]type of argument `tp` and if so,
@@ -3171,8 +3180,8 @@ trait Types
// AM: I think we could use the `suspended` flag to avoid side-effecting during unification
if (suspended) // constraint accumulation is disabled
checkSubtype(tp, origin)
- else if (constr.instValid) // type var is already set
- checkSubtype(tp, constr.inst)
+ else if (instValid) // type var is already set
+ checkSubtype(tp, inst)
else isRelatable(tp) && {
unifySimple || unifyFull(tp) || (
// only look harder if our gaze is oriented toward Any
@@ -3188,14 +3197,14 @@ trait Types
}
def registerTypeEquality(tp: Type, typeVarLHS: Boolean): Boolean = {
-// println("regTypeEq: "+(safeToString, debugString(tp), tp.getClass, if (typeVarLHS) "in LHS" else "in RHS", if (suspended) "ZZ" else if (constr.instValid) "IV" else "")) //@MDEBUG
+// println("regTypeEq: "+(safeToString, debugString(tp), tp.getClass, if (typeVarLHS) "in LHS" else "in RHS", if (suspended) "ZZ" else if (instValid) "IV" else "")) //@MDEBUG
def checkIsSameType(tp: Type) = (
- if (typeVarLHS) constr.inst =:= tp
- else tp =:= constr.inst
+ if (typeVarLHS) inst =:= tp
+ else tp =:= inst
)
if (suspended) tp =:= origin
- else if (constr.instValid) checkIsSameType(tp)
+ else if (instValid) checkIsSameType(tp)
else isRelatable(tp) && {
val newInst = wildcardToTypeVarMap(tp)
(constr isWithinBounds newInst) && {
@@ -3234,7 +3243,7 @@ trait Types
)
override def normalize: Type = (
- if (constr.instValid) constr.inst
+ if (instValid) inst
// get here when checking higher-order subtyping of the typevar by itself
// TODO: check whether this ever happens?
else if (isHigherKinded) logResult("Normalizing HK $this")(typeFun(params, applyArgs(params map (_.typeConstructor))))
@@ -3265,10 +3274,11 @@ trait Types
}
private def levelString = if (settings.explaintypes) level else ""
override def safeToString = (
- if ((constr eq null) || (constr.inst eq null)) "TVar<" + originName + "=null>"
- else if (constr.inst ne NoType) "=?" + constr.inst
+ if ((constr eq null) || (inst eq null)) "TVar<" + originName + "=null>"
+ else if (inst ne NoType) "=?" + inst
else (if(untouchable) "!?" else "?") + levelString + originName
)
+ def originString = s"$originName in $originLocation"
override def kind = "TypeVar"
def cloneInternal = {
@@ -3853,7 +3863,7 @@ trait Types
/** The maximum allowable depth of lubs or glbs over types `ts`.
*/
- def lubDepth(ts: List[Type]): Int = {
+ def lubDepth(ts: List[Type]): Depth = {
val td = typeDepth(ts)
val bd = baseTypeSeqDepth(ts)
lubDepthAdjust(td, td max bd)
@@ -3863,16 +3873,17 @@ trait Types
* as a function over the maximum depth `td` of these types, and
* the maximum depth `bd` of all types in the base type sequences of these types.
*/
- private def lubDepthAdjust(td: Int, bd: Int): Int =
+ private def lubDepthAdjust(td: Depth, bd: Depth): Depth = (
if (settings.XfullLubs) bd
- else if (bd <= 3) bd
- else if (bd <= 5) td max (bd - 1)
- else if (bd <= 7) td max (bd - 2)
- else (td - 1) max (bd - 3)
+ else if (bd <= Depth(3)) bd
+ else if (bd <= Depth(5)) td max bd.decr
+ else if (bd <= Depth(7)) td max (bd decr 2)
+ else td.decr max (bd decr 3)
+ )
- private def symTypeDepth(syms: List[Symbol]): Int = typeDepth(syms map (_.info))
- private def typeDepth(tps: List[Type]): Int = maxDepth(tps)
- private def baseTypeSeqDepth(tps: List[Type]): Int = maxBaseTypeSeqDepth(tps)
+ private def symTypeDepth(syms: List[Symbol]): Depth = typeDepth(syms map (_.info))
+ private def typeDepth(tps: List[Type]): Depth = maxDepth(tps)
+ private def baseTypeSeqDepth(tps: List[Type]): Depth = maxbaseTypeSeqDepth(tps)
/** Is intersection of given types populated? That is,
* for all types tp1, tp2 in intersection
@@ -4141,7 +4152,7 @@ trait Types
case _ => false
}
- def isSubArgs(tps1: List[Type], tps2: List[Type], tparams: List[Symbol], depth: Int): Boolean = {
+ def isSubArgs(tps1: List[Type], tps2: List[Type], tparams: List[Symbol], depth: Depth): Boolean = {
def isSubArg(t1: Type, t2: Type, variance: Variance) = (
(variance.isContravariant || isSubType(t1, t2, depth))
&& (variance.isCovariant || isSubType(t2, t1, depth))
@@ -4150,7 +4161,7 @@ trait Types
corresponds3(tps1, tps2, tparams map (_.variance))(isSubArg)
}
- def specializesSym(tp: Type, sym: Symbol, depth: Int): Boolean = {
+ def specializesSym(tp: Type, sym: Symbol, depth: Depth): Boolean = {
def directlySpecializedBy(member: Symbol): Boolean = (
member == sym
|| specializesSym(tp.narrow, member, sym.owner.thisType, sym, depth)
@@ -4170,7 +4181,7 @@ trait Types
/** Does member `sym1` of `tp1` have a stronger type
* than member `sym2` of `tp2`?
*/
- protected[internal] def specializesSym(tp1: Type, sym1: Symbol, tp2: Type, sym2: Symbol, depth: Int): Boolean = {
+ protected[internal] def specializesSym(tp1: Type, sym1: Symbol, tp2: Type, sym2: Symbol, depth: Depth): Boolean = {
require((sym1 ne NoSymbol) && (sym2 ne NoSymbol), ((tp1, sym1, tp2, sym2, depth)))
val info1 = tp1.memberInfo(sym1)
val info2 = tp2.memberInfo(sym2).substThis(tp2.typeSymbol, tp1)
@@ -4370,7 +4381,7 @@ trait Types
* Return `x` if the computation succeeds with result `x`.
* Return `NoType` if the computation fails.
*/
- def mergePrefixAndArgs(tps: List[Type], variance: Variance, depth: Int): Type = tps match {
+ def mergePrefixAndArgs(tps: List[Type], variance: Variance, depth: Depth): Type = tps match {
case tp :: Nil => tp
case TypeRef(_, sym, _) :: rest =>
val pres = tps map (_.prefix) // prefix normalizes automatically
@@ -4403,7 +4414,7 @@ trait Types
val args = map2(sym.typeParams, argsst) { (tparam, as0) =>
val as = as0.distinct
if (as.size == 1) as.head
- else if (depth == 0) {
+ else if (depth.isZero) {
log("Giving up merging args: can't unify %s under %s".format(as.mkString(", "), tparam.fullLocationString))
// Don't return "Any" (or "Nothing") when we have to give up due to
// recursion depth. Return NoType, which prevents us from poisoning
@@ -4412,11 +4423,11 @@ trait Types
NoType
}
else {
- if (tparam.variance == variance) lub(as, decr(depth))
- else if (tparam.variance == variance.flip) glb(as, decr(depth))
+ if (tparam.variance == variance) lub(as, depth.decr)
+ else if (tparam.variance == variance.flip) glb(as, depth.decr)
else {
- val l = lub(as, decr(depth))
- val g = glb(as, decr(depth))
+ val l = lub(as, depth.decr)
+ val g = glb(as, depth.decr)
if (l <:< g) l
else { // Martin: I removed this, because incomplete. Not sure there is a good way to fix it. For the moment we
// just err on the conservative side, i.e. with a bound that is too high.
@@ -4454,7 +4465,7 @@ trait Types
/** Make symbol `sym` a member of scope `tp.decls`
* where `thistp` is the narrowed owner type of the scope.
*/
- def addMember(thistp: Type, tp: Type, sym: Symbol, depth: Int) {
+ def addMember(thistp: Type, tp: Type, sym: Symbol, depth: Depth) {
assert(sym != NoSymbol)
// debuglog("add member " + sym+":"+sym.info+" to "+thistp) //DEBUG
if (!specializesSym(thistp, sym, depth)) {
@@ -4541,6 +4552,12 @@ trait Types
else (ps :+ SerializableTpe).toList
)
+ /** Adds the @uncheckedBound annotation if the given `tp` has type arguments */
+ final def uncheckedBounds(tp: Type): Type = {
+ if (tp.typeArgs.isEmpty || UncheckedBoundsClass == NoSymbol) tp // second condition for backwards compatibilty with older scala-reflect.jar
+ else tp.withAnnotation(AnnotationInfo marker UncheckedBoundsClass.tpe)
+ }
+
/** Members of the given class, other than those inherited
* from Any or AnyRef.
*/
@@ -4581,23 +4598,15 @@ trait Types
private[scala] val typeIsHigherKinded = (tp: Type) => tp.isHigherKinded
/** The maximum depth of type `tp` */
- def typeDepth(tp: Type): Int = tp match {
- case TypeRef(pre, sym, args) =>
- math.max(typeDepth(pre), typeDepth(args) + 1)
- case RefinedType(parents, decls) =>
- math.max(typeDepth(parents), symTypeDepth(decls.toList) + 1)
- case TypeBounds(lo, hi) =>
- math.max(typeDepth(lo), typeDepth(hi))
- case MethodType(paramtypes, result) =>
- typeDepth(result)
- case NullaryMethodType(result) =>
- typeDepth(result)
- case PolyType(tparams, result) =>
- math.max(typeDepth(result), symTypeDepth(tparams) + 1)
- case ExistentialType(tparams, result) =>
- math.max(typeDepth(result), symTypeDepth(tparams) + 1)
- case _ =>
- 1
+ def typeDepth(tp: Type): Depth = tp match {
+ case TypeRef(pre, sym, args) => typeDepth(pre) max typeDepth(args).incr
+ case RefinedType(parents, decls) => typeDepth(parents) max symTypeDepth(decls.toList).incr
+ case TypeBounds(lo, hi) => typeDepth(lo) max typeDepth(hi)
+ case MethodType(paramtypes, result) => typeDepth(result)
+ case NullaryMethodType(result) => typeDepth(result)
+ case PolyType(tparams, result) => typeDepth(result) max symTypeDepth(tparams).incr
+ case ExistentialType(tparams, result) => typeDepth(result) max symTypeDepth(tparams).incr
+ case _ => Depth(1)
}
def withUncheckedVariance(tp: Type): Type =
@@ -4608,19 +4617,19 @@ trait Types
// var d = 0
// for (tp <- tps) d = d max by(tp) //!!!OPT!!!
// d
- private[scala] def maxDepth(tps: List[Type]): Int = {
- @tailrec def loop(tps: List[Type], acc: Int): Int = tps match {
- case tp :: rest => loop(rest, math.max(acc, typeDepth(tp)))
+ private[scala] def maxDepth(tps: List[Type]): Depth = {
+ @tailrec def loop(tps: List[Type], acc: Depth): Depth = tps match {
+ case tp :: rest => loop(rest, acc max typeDepth(tp))
case _ => acc
}
- loop(tps, 0)
+ loop(tps, Depth.Zero)
}
- private[scala] def maxBaseTypeSeqDepth(tps: List[Type]): Int = {
- @tailrec def loop(tps: List[Type], acc: Int): Int = tps match {
- case tp :: rest => loop(rest, math.max(acc, tp.baseTypeSeqDepth))
+ private[scala] def maxbaseTypeSeqDepth(tps: List[Type]): Depth = {
+ @tailrec def loop(tps: List[Type], acc: Depth): Depth = tps match {
+ case tp :: rest => loop(rest, acc max tp.baseTypeSeqDepth)
case _ => acc
}
- loop(tps, 0)
+ loop(tps, Depth.Zero)
}
@tailrec private def typesContain(tps: List[Type], sym: Symbol): Boolean = tps match {
diff --git a/src/reflect/scala/reflect/internal/Variance.scala b/src/reflect/scala/reflect/internal/Variance.scala
index 3480161567..ecc5d99a40 100644
--- a/src/reflect/scala/reflect/internal/Variance.scala
+++ b/src/reflect/scala/reflect/internal/Variance.scala
@@ -60,8 +60,7 @@ final class Variance private (val flags: Int) extends AnyVal {
/** The symbolic annotation used to indicate the given kind of variance. */
def symbolicString = (
- if (isBivariant) "+/-"
- else if (isCovariant) "+"
+ if (isCovariant) "+"
else if (isContravariant) "-"
else ""
)
diff --git a/src/reflect/scala/reflect/internal/Variances.scala b/src/reflect/scala/reflect/internal/Variances.scala
index 78df3c9617..bf00a7ac87 100644
--- a/src/reflect/scala/reflect/internal/Variances.scala
+++ b/src/reflect/scala/reflect/internal/Variances.scala
@@ -92,7 +92,9 @@ trait Variances {
val relative = relativeVariance(sym)
val required = relative * variance
if (!relative.isBivariant) {
- log(s"verifying $sym (${sym.variance}${sym.locationString}) is $required at $base in ${base.owner}")
+ def sym_s = s"$sym (${sym.variance}${sym.locationString})"
+ def base_s = s"$base in ${base.owner}" + (if (base.owner.isClass) "" else " in " + base.owner.enclClass)
+ log(s"verifying $sym_s is $required at $base_s")
if (sym.variance != required)
issueVarianceError(base, sym, required)
}
@@ -146,7 +148,7 @@ trait Variances {
)
tree match {
case defn: MemberDef if skip =>
- log(s"Skipping variance check of ${sym.defString}")
+ debuglog(s"Skipping variance check of ${sym.defString}")
case ClassDef(_, _, _, _) | TypeDef(_, _, _, _) =>
validateVariance(sym)
super.traverse(tree)
diff --git a/src/reflect/scala/reflect/internal/annotations/uncheckedBounds.scala b/src/reflect/scala/reflect/internal/annotations/uncheckedBounds.scala
new file mode 100644
index 0000000000..a44bb54734
--- /dev/null
+++ b/src/reflect/scala/reflect/internal/annotations/uncheckedBounds.scala
@@ -0,0 +1,13 @@
+package scala.reflect
+package internal
+package annotations
+
+/**
+ * An annotation that designates the annotated type should not be checked for violations of
+ * type parameter bounds in the `refchecks` phase of the compiler. This can be used by synthesized
+ * code the uses an inferred type of an expression as the type of an artifict val/def (for example,
+ * a temporary value introduced by an ANF transform). See [[https://issues.scala-lang.org/browse/SI-7694]].
+ *
+ * @since 2.10.3
+ */
+final class uncheckedBounds extends scala.annotation.StaticAnnotation
diff --git a/src/reflect/scala/reflect/internal/tpe/GlbLubs.scala b/src/reflect/scala/reflect/internal/tpe/GlbLubs.scala
index 1d3c6b0f23..6fa536d84c 100644
--- a/src/reflect/scala/reflect/internal/tpe/GlbLubs.scala
+++ b/src/reflect/scala/reflect/internal/tpe/GlbLubs.scala
@@ -19,7 +19,7 @@ private[internal] trait GlbLubs {
private final val verifyLubs = true
- private def printLubMatrix(btsMap: Map[Type, List[Type]], depth: Int) {
+ private def printLubMatrix(btsMap: Map[Type, List[Type]], depth: Depth) {
import util.TableDef
import TableDef.Column
def str(tp: Type) = {
@@ -76,8 +76,8 @@ private[internal] trait GlbLubs {
* (except that type constructors have been applied to their dummyArgs)
* @See baseTypeSeq for a definition of sorted and upwards closed.
*/
- def lubList(ts: List[Type], depth: Int): List[Type] = {
- var lubListDepth = 0
+ def lubList(ts: List[Type], depth: Depth): List[Type] = {
+ var lubListDepth = Depth.Zero
// This catches some recursive situations which would otherwise
// befuddle us, e.g. pos/hklub0.scala
def isHotForTs(xs: List[Type]) = ts exists (_.typeParams == xs.map(_.typeSymbol))
@@ -89,7 +89,7 @@ private[internal] trait GlbLubs {
}
// pretypes is a tail-recursion-preserving accumulator.
@tailrec def loop(pretypes: List[Type], tsBts: List[List[Type]]): List[Type] = {
- lubListDepth += 1
+ lubListDepth = lubListDepth.incr
if (tsBts.isEmpty || (tsBts exists typeListIsEmpty)) pretypes.reverse
else if (tsBts.tail.isEmpty) pretypes.reverse ++ tsBts.head
@@ -181,13 +181,13 @@ private[internal] trait GlbLubs {
/** Eliminate from list of types all elements which are a subtype
* of some other element of the list. */
- private def elimSub(ts: List[Type], depth: Int): List[Type] = {
+ private def elimSub(ts: List[Type], depth: Depth): List[Type] = {
def elimSub0(ts: List[Type]): List[Type] = ts match {
case List() => List()
case List(t) => List(t)
case t :: ts1 =>
- val rest = elimSub0(ts1 filter (t1 => !isSubType(t1, t, decr(depth))))
- if (rest exists (t1 => isSubType(t, t1, decr(depth)))) rest else t :: rest
+ val rest = elimSub0(ts1 filter (t1 => !isSubType(t1, t, depth.decr)))
+ if (rest exists (t1 => isSubType(t, t1, depth.decr))) rest else t :: rest
}
val ts0 = elimSub0(ts)
if (ts0.isEmpty || ts0.tail.isEmpty) ts0
@@ -251,8 +251,8 @@ private[internal] trait GlbLubs {
else if (isNumericSubType(t2, t1)) t1
else IntTpe)
- private val lubResults = new mutable.HashMap[(Int, List[Type]), Type]
- private val glbResults = new mutable.HashMap[(Int, List[Type]), Type]
+ private val lubResults = new mutable.HashMap[(Depth, List[Type]), Type]
+ private val glbResults = new mutable.HashMap[(Depth, List[Type]), Type]
/** Given a list of types, finds all the base classes they have in
* common, then returns a list of type constructors derived directly
@@ -299,7 +299,7 @@ private[internal] trait GlbLubs {
}
/** The least upper bound wrt <:< of a list of types */
- protected[internal] def lub(ts: List[Type], depth: Int): Type = {
+ protected[internal] def lub(ts: List[Type], depth: Depth): Type = {
def lub0(ts0: List[Type]): Type = elimSub(ts0, depth) match {
case List() => NothingTpe
case List(t) => t
@@ -321,7 +321,7 @@ private[internal] trait GlbLubs {
lubType
case None =>
lubResults((depth, ts)) = AnyTpe
- val res = if (depth < 0) AnyTpe else lub1(ts)
+ val res = if (depth.isNegative) AnyTpe else lub1(ts)
lubResults((depth, ts)) = res
res
}
@@ -333,7 +333,7 @@ private[internal] trait GlbLubs {
val lubOwner = commonOwner(ts)
val lubBase = intersectionType(lubParents, lubOwner)
val lubType =
- if (phase.erasedTypes || depth == 0 ) lubBase
+ if (phase.erasedTypes || depth.isZero ) lubBase
else {
val lubRefined = refinedType(lubParents, lubOwner)
val lubThisType = lubRefined.typeSymbol.thisType
@@ -357,12 +357,12 @@ private[internal] trait GlbLubs {
val symtypes =
map2(narrowts, syms)((t, sym) => t.memberInfo(sym).substThis(t.typeSymbol, lubThisType))
if (proto.isTerm) // possible problem: owner of info is still the old one, instead of new refinement class
- proto.cloneSymbol(lubRefined.typeSymbol).setInfoOwnerAdjusted(lub(symtypes, decr(depth)))
+ proto.cloneSymbol(lubRefined.typeSymbol).setInfoOwnerAdjusted(lub(symtypes, depth.decr))
else if (symtypes.tail forall (symtypes.head =:= _))
proto.cloneSymbol(lubRefined.typeSymbol).setInfoOwnerAdjusted(symtypes.head)
else {
def lubBounds(bnds: List[TypeBounds]): TypeBounds =
- TypeBounds(glb(bnds map (_.lo), decr(depth)), lub(bnds map (_.hi), decr(depth)))
+ TypeBounds(glb(bnds map (_.lo), depth.decr), lub(bnds map (_.hi), depth.decr))
lubRefined.typeSymbol.newAbstractType(proto.name.toTypeName, proto.pos)
.setInfoOwnerAdjusted(lubBounds(symtypes map (_.bounds)))
}
@@ -432,8 +432,8 @@ private[internal] trait GlbLubs {
* The counter breaks this recursion after two calls.
* If the recursion is broken, no member is added to the glb.
*/
- private var globalGlbDepth = 0
- private final val globalGlbLimit = 2
+ private var globalGlbDepth = Depth.Zero
+ private final val globalGlbLimit = Depth(2)
/** The greatest lower bound of a list of types (as determined by `<:<`). */
def glb(ts: List[Type]): Type = elimSuper(ts) match {
@@ -451,7 +451,7 @@ private[internal] trait GlbLubs {
}
}
- protected[internal] def glb(ts: List[Type], depth: Int): Type = elimSuper(ts) match {
+ protected[internal] def glb(ts: List[Type], depth: Depth): Type = elimSuper(ts) match {
case List() => AnyTpe
case List(t) => t
case ts0 => glbNorm(ts0, depth)
@@ -459,7 +459,7 @@ private[internal] trait GlbLubs {
/** The greatest lower bound of a list of types (as determined by `<:<`), which have been normalized
* with regard to `elimSuper`. */
- protected def glbNorm(ts: List[Type], depth: Int): Type = {
+ protected def glbNorm(ts: List[Type], depth: Depth): Type = {
def glb0(ts0: List[Type]): Type = ts0 match {
case List() => AnyTpe
case List(t) => t
@@ -479,7 +479,7 @@ private[internal] trait GlbLubs {
glbType
case _ =>
glbResults((depth, ts)) = NothingTpe
- val res = if (depth < 0) NothingTpe else glb1(ts)
+ val res = if (depth.isNegative) NothingTpe else glb1(ts)
glbResults((depth, ts)) = res
res
}
@@ -501,7 +501,7 @@ private[internal] trait GlbLubs {
val ts1 = ts flatMap refinedToParents
val glbBase = intersectionType(ts1, glbOwner)
val glbType =
- if (phase.erasedTypes || depth == 0) glbBase
+ if (phase.erasedTypes || depth.isZero) glbBase
else {
val glbRefined = refinedType(ts1, glbOwner)
val glbThisType = glbRefined.typeSymbol.thisType
@@ -514,15 +514,15 @@ private[internal] trait GlbLubs {
val symtypes = syms map glbThisType.memberInfo
assert(!symtypes.isEmpty)
proto.cloneSymbol(glbRefined.typeSymbol).setInfoOwnerAdjusted(
- if (proto.isTerm) glb(symtypes, decr(depth))
+ if (proto.isTerm) glb(symtypes, depth.decr)
else {
def isTypeBound(tp: Type) = tp match {
case TypeBounds(_, _) => true
case _ => false
}
def glbBounds(bnds: List[Type]): TypeBounds = {
- val lo = lub(bnds map (_.bounds.lo), decr(depth))
- val hi = glb(bnds map (_.bounds.hi), decr(depth))
+ val lo = lub(bnds map (_.bounds.lo), depth.decr)
+ val hi = glb(bnds map (_.bounds.hi), depth.decr)
if (lo <:< hi) TypeBounds(lo, hi)
else throw GlbFailure
}
@@ -539,7 +539,7 @@ private[internal] trait GlbLubs {
}
if (globalGlbDepth < globalGlbLimit)
try {
- globalGlbDepth += 1
+ globalGlbDepth = globalGlbDepth.incr
val dss = ts flatMap refinedToDecls
for (ds <- dss; sym <- ds.iterator)
if (globalGlbDepth < globalGlbLimit && !specializesSym(glbThisType, sym, depth))
@@ -549,7 +549,7 @@ private[internal] trait GlbLubs {
case ex: NoCommonType =>
}
} finally {
- globalGlbDepth -= 1
+ globalGlbDepth = globalGlbDepth.decr
}
if (glbRefined.decls.isEmpty) glbBase else glbRefined
}
diff --git a/src/reflect/scala/reflect/internal/tpe/TypeComparers.scala b/src/reflect/scala/reflect/internal/tpe/TypeComparers.scala
index 63f17dff34..d8b3b04d0e 100644
--- a/src/reflect/scala/reflect/internal/tpe/TypeComparers.scala
+++ b/src/reflect/scala/reflect/internal/tpe/TypeComparers.scala
@@ -232,9 +232,7 @@ trait TypeComparers {
)
}
- def isSubType(tp1: Type, tp2: Type): Boolean = isSubType(tp1, tp2, AnyDepth)
-
- def isSubType(tp1: Type, tp2: Type, depth: Int): Boolean = try {
+ def isSubType(tp1: Type, tp2: Type, depth: Depth = Depth.AnyDepth): Boolean = try {
subsametypeRecursions += 1
//OPT cutdown on Function0 allocation
@@ -314,7 +312,7 @@ trait TypeComparers {
else TriState.Unknown
}
- private def isSubType1(tp1: Type, tp2: Type, depth: Int): Boolean = typeRelationPreCheck(tp1, tp2) match {
+ private def isSubType1(tp1: Type, tp2: Type, depth: Depth): Boolean = typeRelationPreCheck(tp1, tp2) match {
case state if state.isKnown => state.booleanValue
case _ if typeHasAnnotations(tp1) || typeHasAnnotations(tp2) => annotationsConform(tp1, tp2) && (tp1.withoutAnnotations <:< tp2.withoutAnnotations)
case _ => isSubType2(tp1, tp2, depth)
@@ -338,7 +336,7 @@ trait TypeComparers {
}
// @assume tp1.isHigherKinded || tp2.isHigherKinded
- def isHKSubType(tp1: Type, tp2: Type, depth: Int): Boolean = {
+ def isHKSubType(tp1: Type, tp2: Type, depth: Depth): Boolean = {
def isSub(ntp1: Type, ntp2: Type) = (ntp1.withoutAnnotations, ntp2.withoutAnnotations) match {
case (TypeRef(_, AnyClass, _), _) => false // avoid some warnings when Nothing/Any are on the other side
case (_, TypeRef(_, NothingClass, _)) => false
@@ -357,7 +355,7 @@ trait TypeComparers {
}
/** Does type `tp1` conform to `tp2`? */
- private def isSubType2(tp1: Type, tp2: Type, depth: Int): Boolean = {
+ private def isSubType2(tp1: Type, tp2: Type, depth: Depth): Boolean = {
def retry(lhs: Type, rhs: Type) = ((lhs ne tp1) || (rhs ne tp2)) && isSubType(lhs, rhs, depth)
if (isSingleType(tp1) && isSingleType(tp2) || isConstantType(tp1) && isConstantType(tp2))
diff --git a/src/reflect/scala/reflect/internal/tpe/TypeConstraints.scala b/src/reflect/scala/reflect/internal/tpe/TypeConstraints.scala
index 123c296f95..fdfe376c18 100644
--- a/src/reflect/scala/reflect/internal/tpe/TypeConstraints.scala
+++ b/src/reflect/scala/reflect/internal/tpe/TypeConstraints.scala
@@ -6,7 +6,6 @@ package tpe
import scala.collection.{ generic }
import generic.Clearable
-
private[internal] trait TypeConstraints {
self: SymbolTable =>
import definitions._
@@ -170,11 +169,14 @@ private[internal] trait TypeConstraints {
}
}
- def isWithinBounds(tp: Type): Boolean =
- lobounds.forall(_ <:< tp) &&
- hibounds.forall(tp <:< _) &&
- (numlo == NoType || (numlo weak_<:< tp)) &&
- (numhi == NoType || (tp weak_<:< numhi))
+ def instWithinBounds = instValid && isWithinBounds(inst)
+
+ def isWithinBounds(tp: Type): Boolean = (
+ lobounds.forall(_ <:< tp)
+ && hibounds.forall(tp <:< _)
+ && (numlo == NoType || (numlo weak_<:< tp))
+ && (numhi == NoType || (tp weak_<:< numhi))
+ )
var inst: Type = NoType // @M reduce visibility?
@@ -188,12 +190,17 @@ private[internal] trait TypeConstraints {
override def toString = {
val boundsStr = {
- val lo = loBounds filterNot typeIsNothing
- val hi = hiBounds filterNot typeIsAny
- val lostr = if (lo.isEmpty) Nil else List(lo.mkString(" >: (", ", ", ")"))
- val histr = if (hi.isEmpty) Nil else List(hi.mkString(" <: (", ", ", ")"))
-
- lostr ++ histr mkString ("[", " | ", "]")
+ val lo = loBounds filterNot typeIsNothing match {
+ case Nil => ""
+ case tp :: Nil => " >: " + tp
+ case tps => tps.mkString(" >: (", ", ", ")")
+ }
+ val hi = hiBounds filterNot typeIsAny match {
+ case Nil => ""
+ case tp :: Nil => " <: " + tp
+ case tps => tps.mkString(" <: (", ", ", ")")
+ }
+ lo + hi
}
if (inst eq NoType) boundsStr
else boundsStr + " _= " + inst.safeToString
@@ -208,12 +215,7 @@ private[internal] trait TypeConstraints {
* solution direction for all contravariant variables.
* @param upper When `true` search for max solution else min.
*/
- def solve(tvars: List[TypeVar], tparams: List[Symbol],
- variances: List[Variance], upper: Boolean): Boolean =
- solve(tvars, tparams, variances, upper, AnyDepth)
-
- def solve(tvars: List[TypeVar], tparams: List[Symbol],
- variances: List[Variance], upper: Boolean, depth: Int): Boolean = {
+ def solve(tvars: List[TypeVar], tparams: List[Symbol], variances: List[Variance], upper: Boolean, depth: Depth): Boolean = {
def solveOne(tvar: TypeVar, tparam: Symbol, variance: Variance) {
if (tvar.constr.inst == NoType) {
@@ -236,25 +238,25 @@ private[internal] trait TypeConstraints {
if (!cyclic) {
if (up) {
if (bound.typeSymbol != AnyClass) {
- log(s"$tvar addHiBound $bound.instantiateTypeParams($tparams, $tvars)")
+ debuglog(s"$tvar addHiBound $bound.instantiateTypeParams($tparams, $tvars)")
tvar addHiBound bound.instantiateTypeParams(tparams, tvars)
}
for (tparam2 <- tparams)
tparam2.info.bounds.lo.dealias match {
case TypeRef(_, `tparam`, _) =>
- log(s"$tvar addHiBound $tparam2.tpeHK.instantiateTypeParams($tparams, $tvars)")
+ debuglog(s"$tvar addHiBound $tparam2.tpeHK.instantiateTypeParams($tparams, $tvars)")
tvar addHiBound tparam2.tpeHK.instantiateTypeParams(tparams, tvars)
case _ =>
}
} else {
if (bound.typeSymbol != NothingClass && bound.typeSymbol != tparam) {
- log(s"$tvar addLoBound $bound.instantiateTypeParams($tparams, $tvars)")
+ debuglog(s"$tvar addLoBound $bound.instantiateTypeParams($tparams, $tvars)")
tvar addLoBound bound.instantiateTypeParams(tparams, tvars)
}
for (tparam2 <- tparams)
tparam2.info.bounds.hi.dealias match {
case TypeRef(_, `tparam`, _) =>
- log(s"$tvar addLoBound $tparam2.tpeHK.instantiateTypeParams($tparams, $tvars)")
+ debuglog(s"$tvar addLoBound $tparam2.tpeHK.instantiateTypeParams($tparams, $tvars)")
tvar addLoBound tparam2.tpeHK.instantiateTypeParams(tparams, tvars)
case _ =>
}
@@ -265,12 +267,16 @@ private[internal] trait TypeConstraints {
//println("solving "+tvar+" "+up+" "+(if (up) (tvar.constr.hiBounds) else tvar.constr.loBounds)+((if (up) (tvar.constr.hiBounds) else tvar.constr.loBounds) map (_.widen)))
val newInst = (
if (up) {
- if (depth != AnyDepth) glb(tvar.constr.hiBounds, depth) else glb(tvar.constr.hiBounds)
- } else {
- if (depth != AnyDepth) lub(tvar.constr.loBounds, depth) else lub(tvar.constr.loBounds)
+ if (depth.isAnyDepth) glb(tvar.constr.hiBounds)
+ else glb(tvar.constr.hiBounds, depth)
+ }
+ else {
+ if (depth.isAnyDepth) lub(tvar.constr.loBounds)
+ else lub(tvar.constr.loBounds, depth)
}
)
- log(s"$tvar setInst $newInst")
+
+ debuglog(s"$tvar setInst $newInst")
tvar setInst newInst
//Console.println("solving "+tvar+" "+up+" "+(if (up) (tvar.constr.hiBounds) else tvar.constr.loBounds)+((if (up) (tvar.constr.hiBounds) else tvar.constr.loBounds) map (_.widen))+" = "+tvar.constr.inst)//@MDEBUG
}
@@ -278,6 +284,6 @@ private[internal] trait TypeConstraints {
// println("solving "+tvars+"/"+tparams+"/"+(tparams map (_.info)))
foreach3(tvars, tparams, variances)(solveOne)
- tvars forall (tvar => tvar.constr.isWithinBounds(tvar.constr.inst))
+ tvars forall (tv => tv.instWithinBounds || util.andFalse(log(s"Inferred type for ${tv.originString} does not conform to bounds: ${tv.constr}")))
}
}
diff --git a/src/reflect/scala/reflect/internal/tpe/TypeMaps.scala b/src/reflect/scala/reflect/internal/tpe/TypeMaps.scala
index 0d9bbfa5e0..be61c45041 100644
--- a/src/reflect/scala/reflect/internal/tpe/TypeMaps.scala
+++ b/src/reflect/scala/reflect/internal/tpe/TypeMaps.scala
@@ -17,12 +17,11 @@ private[internal] trait TypeMaps {
* so it is no longer carries the too-stealthy name "deAlias".
*/
object normalizeAliases extends TypeMap {
- def apply(tp: Type): Type = tp match {
- case TypeRef(_, sym, _) if sym.isAliasType =>
- def msg = if (tp.isHigherKinded) s"Normalizing type alias function $tp" else s"Dealiasing type alias $tp"
- mapOver(logResult(msg)(tp.normalize))
- case _ => mapOver(tp)
- }
+ def apply(tp: Type): Type = mapOver(tp match {
+ case TypeRef(_, sym, _) if sym.isAliasType && tp.isHigherKinded => logResult(s"Normalized type alias function $tp")(tp.normalize)
+ case TypeRef(_, sym, _) if sym.isAliasType => tp.normalize
+ case tp => tp
+ })
}
/** Remove any occurrence of type <singleton> from this type and its parents */
@@ -944,7 +943,7 @@ private[internal] trait TypeMaps {
}
}
- /** A map to convert every occurrence of a type variable to a wildcard type. */
+ /** A map to convert each occurrence of a type variable to its origin. */
object typeVarToOriginMap extends TypeMap {
def apply(tp: Type): Type = tp match {
case TypeVar(origin, _) => origin
diff --git a/src/reflect/scala/reflect/internal/util/package.scala b/src/reflect/scala/reflect/internal/util/package.scala
index 49164d366c..df63a55090 100644
--- a/src/reflect/scala/reflect/internal/util/package.scala
+++ b/src/reflect/scala/reflect/internal/util/package.scala
@@ -7,6 +7,8 @@ import scala.language.existentials // SI-6541
package object util {
import StringOps.longestCommonPrefix
+ def andFalse(body: Unit): Boolean = false
+
// Shorten a name like Symbols$FooSymbol to FooSymbol.
private def shortenName(name: String): String = {
if (name == "") return ""
diff --git a/src/reflect/scala/reflect/io/ZipArchive.scala b/src/reflect/scala/reflect/io/ZipArchive.scala
index eabf1dcbab..8260189459 100644
--- a/src/reflect/scala/reflect/io/ZipArchive.scala
+++ b/src/reflect/scala/reflect/io/ZipArchive.scala
@@ -126,7 +126,11 @@ abstract class ZipArchive(override val file: JFile) extends AbstractFile with Eq
/** ''Note: This library is considered experimental and should not be used unless you know what you are doing.'' */
final class FileZipArchive(file: JFile) extends ZipArchive(file) {
def iterator: Iterator[Entry] = {
- val zipFile = new ZipFile(file)
+ val zipFile = try {
+ new ZipFile(file)
+ } catch {
+ case ioe: IOException => throw new IOException("Error accessing " + file.getPath, ioe)
+ }
val root = new DirEntry("/")
val dirs = mutable.HashMap[String, DirEntry]("/" -> root)
val enum = zipFile.entries()
diff --git a/src/reflect/scala/reflect/runtime/JavaMirrors.scala b/src/reflect/scala/reflect/runtime/JavaMirrors.scala
index 93861b0899..dd77b084c5 100644
--- a/src/reflect/scala/reflect/runtime/JavaMirrors.scala
+++ b/src/reflect/scala/reflect/runtime/JavaMirrors.scala
@@ -18,7 +18,7 @@ import internal.pickling.ByteCodecs
import internal.pickling.UnPickler
import scala.collection.mutable.{ HashMap, ListBuffer }
import internal.Flags._
-import ReflectionUtils.{staticSingletonInstance, innerSingletonInstance}
+import ReflectionUtils.{staticSingletonInstance, innerSingletonInstance, scalacShouldntLoadClass}
import scala.language.existentials
import scala.runtime.{ScalaRunTime, BoxesRunTime}
@@ -696,8 +696,10 @@ private[reflect] trait JavaMirrors extends internal.SymbolTable with api.JavaUni
val parents = try {
parentsLevel += 1
val jsuperclazz = jclazz.getGenericSuperclass
- val superclazz = if (jsuperclazz == null) AnyTpe else typeToScala(jsuperclazz)
- superclazz :: (jclazz.getGenericInterfaces.toList map typeToScala)
+ val ifaces = jclazz.getGenericInterfaces.toList map typeToScala
+ val isAnnotation = JavaAccFlags(jclazz).isAnnotation
+ if (isAnnotation) AnnotationClass.tpe :: ClassfileAnnotationClass.tpe :: ifaces
+ else (if (jsuperclazz == null) AnyTpe else typeToScala(jsuperclazz)) :: ifaces
} finally {
parentsLevel -= 1
}
@@ -709,14 +711,21 @@ private[reflect] trait JavaMirrors extends internal.SymbolTable with api.JavaUni
def enter(sym: Symbol, mods: JavaAccFlags) =
( if (mods.isStatic) module.moduleClass else clazz ).info.decls enter sym
- for (jinner <- jclazz.getDeclaredClasses)
+ def enterEmptyCtorIfNecessary(): Unit = {
+ if (jclazz.getConstructors.isEmpty)
+ clazz.info.decls.enter(clazz.newClassConstructor(NoPosition))
+ }
+
+ for (jinner <- jclazz.getDeclaredClasses) {
jclassAsScala(jinner) // inner class is entered as a side-effect
// no need to call enter explicitly
+ }
pendingLoadActions ::= { () =>
jclazz.getDeclaredFields foreach (f => enter(jfieldAsScala(f), f.javaFlags))
jclazz.getDeclaredMethods foreach (m => enter(jmethodAsScala(m), m.javaFlags))
jclazz.getConstructors foreach (c => enter(jconstrAsScala(c), c.javaFlags))
+ enterEmptyCtorIfNecessary()
}
if (parentsLevel == 0) {
@@ -949,7 +958,7 @@ private[reflect] trait JavaMirrors extends internal.SymbolTable with api.JavaUni
val cls =
if (jclazz.isMemberClass && !nme.isImplClassName(jname))
lookupClass
- else if (jclazz.isLocalClass0 || isInvalidClassName(jname))
+ else if (jclazz.isLocalClass0 || scalacShouldntLoadClass(jname))
// local classes and implementation classes not preserved by unpickling - treat as Java
//
// upd. but only if they cannot be loaded as top-level classes
diff --git a/src/reflect/scala/reflect/runtime/ReflectionUtils.scala b/src/reflect/scala/reflect/runtime/ReflectionUtils.scala
index 2db9706007..710ec02acd 100644
--- a/src/reflect/scala/reflect/runtime/ReflectionUtils.scala
+++ b/src/reflect/scala/reflect/runtime/ReflectionUtils.scala
@@ -78,4 +78,10 @@ private[scala] object ReflectionUtils {
accessor setAccessible true
accessor invoke outer
}
+
+ def isTraitImplementation(fileName: String) = fileName endsWith "$class.class"
+
+ def scalacShouldntLoadClassfile(fileName: String) = isTraitImplementation(fileName)
+
+ def scalacShouldntLoadClass(name: scala.reflect.internal.SymbolTable#Name) = scalacShouldntLoadClassfile(name + ".class")
}
diff --git a/src/reflect/scala/reflect/runtime/SymbolLoaders.scala b/src/reflect/scala/reflect/runtime/SymbolLoaders.scala
index 815cc0c885..3e01a6df02 100644
--- a/src/reflect/scala/reflect/runtime/SymbolLoaders.scala
+++ b/src/reflect/scala/reflect/runtime/SymbolLoaders.scala
@@ -5,6 +5,7 @@ package runtime
import internal.Flags
import java.lang.{Class => jClass, Package => jPackage}
import scala.collection.mutable
+import scala.reflect.runtime.ReflectionUtils.scalacShouldntLoadClass
private[reflect] trait SymbolLoaders { self: SymbolTable =>
@@ -90,14 +91,6 @@ private[reflect] trait SymbolLoaders { self: SymbolTable =>
}
}
- /** Is the given name valid for a top-level class? We exclude names with embedded $-signs, because
- * these are nested classes or anonymous classes,
- */
- def isInvalidClassName(name: Name) = {
- val dp = name pos '$'
- 0 < dp && dp < (name.length - 1)
- }
-
class PackageScope(pkgClass: Symbol) extends Scope(initFingerPrints = -1L) // disable fingerprinting as we do not know entries beforehand
with SynchronizedScope {
assert(pkgClass.isType)
@@ -107,7 +100,7 @@ private[reflect] trait SymbolLoaders { self: SymbolTable =>
val e = super.lookupEntry(name)
if (e != null)
e
- else if (isInvalidClassName(name) || (negatives contains name))
+ else if (scalacShouldntLoadClass(name) || (negatives contains name))
null
else {
val path =
diff --git a/src/reflect/scala/reflect/runtime/SynchronizedOps.scala b/src/reflect/scala/reflect/runtime/SynchronizedOps.scala
index 132470b2e7..6aa47a0405 100644
--- a/src/reflect/scala/reflect/runtime/SynchronizedOps.scala
+++ b/src/reflect/scala/reflect/runtime/SynchronizedOps.scala
@@ -9,10 +9,7 @@ private[reflect] trait SynchronizedOps extends internal.SymbolTable
// Names
- private lazy val nameLock = new Object
-
- override def newTermName(s: String): TermName = nameLock.synchronized { super.newTermName(s) }
- override def newTypeName(s: String): TypeName = nameLock.synchronized { super.newTypeName(s) }
+ override protected def synchronizeNames = true
// BaseTypeSeqs
diff --git a/src/reflect/scala/reflect/runtime/SynchronizedTypes.scala b/src/reflect/scala/reflect/runtime/SynchronizedTypes.scala
index f4b02c5bcd..c0146167df 100644
--- a/src/reflect/scala/reflect/runtime/SynchronizedTypes.scala
+++ b/src/reflect/scala/reflect/runtime/SynchronizedTypes.scala
@@ -4,6 +4,7 @@ package runtime
import scala.collection.mutable.WeakHashMap
import java.lang.ref.WeakReference
+import scala.reflect.internal.Depth
/** This trait overrides methods in reflect.internal, bracketing
* them in synchronized { ... } to make them thread-safe
@@ -57,7 +58,7 @@ private[reflect] trait SynchronizedTypes extends internal.Types { self: SymbolTa
override def isDifferentType(tp1: Type, tp2: Type): Boolean =
subsametypeLock.synchronized { super.isDifferentType(tp1, tp2) }
- override def isSubType(tp1: Type, tp2: Type, depth: Int): Boolean =
+ override def isSubType(tp1: Type, tp2: Type, depth: Depth): Boolean =
subsametypeLock.synchronized { super.isSubType(tp1, tp2, depth) }
private object lubglbLock
diff --git a/src/repl/scala/tools/nsc/interpreter/IMain.scala b/src/repl/scala/tools/nsc/interpreter/IMain.scala
index 3eafa563bc..ee4ff59498 100644
--- a/src/repl/scala/tools/nsc/interpreter/IMain.scala
+++ b/src/repl/scala/tools/nsc/interpreter/IMain.scala
@@ -22,7 +22,7 @@ import scala.reflect.internal.util.{ BatchSourceFile, SourceFile }
import scala.tools.util.PathResolver
import scala.tools.nsc.io.AbstractFile
import scala.tools.nsc.typechecker.{ TypeStrings, StructuredTypeStrings }
-import scala.tools.nsc.util.{ ScalaClassLoader, stringFromWriter, stackTracePrefixString }
+import scala.tools.nsc.util.{ ScalaClassLoader, stringFromWriter, StackTraceOps }
import scala.tools.nsc.util.Exceptional.unwrap
import javax.script.{AbstractScriptEngine, Bindings, ScriptContext, ScriptEngine, ScriptEngineFactory, ScriptException, CompiledScript, Compilable}
@@ -726,7 +726,7 @@ class IMain(@BeanProperty val factory: ScriptEngineFactory, initialSettings: Set
def isWrapperInit(x: StackTraceElement) = cond(x.getClassName) {
case classNameRegex() if x.getMethodName == nme.CONSTRUCTOR.decoded => true
}
- val stackTrace = util.stackTracePrefixString(unwrapped)(!isWrapperInit(_))
+ val stackTrace = unwrapped stackTracePrefixString (!isWrapperInit(_))
withLastExceptionLock[String]({
directBind[Throwable]("lastException", unwrapped)(StdReplTags.tagOfThrowable, classTag[Throwable])
diff --git a/test/files/neg/macro-abort.check b/test/files/neg/macro-abort.check
new file mode 100644
index 0000000000..1e58add533
--- /dev/null
+++ b/test/files/neg/macro-abort.check
@@ -0,0 +1,4 @@
+Test_2.scala:2: error: aborted
+ Macros.abort
+ ^
+one error found
diff --git a/test/files/neg/macro-abort/Macros_1.scala b/test/files/neg/macro-abort/Macros_1.scala
new file mode 100644
index 0000000000..676c112098
--- /dev/null
+++ b/test/files/neg/macro-abort/Macros_1.scala
@@ -0,0 +1,9 @@
+import scala.language.experimental.macros
+import scala.reflect.macros.Context
+
+object Macros {
+ def impl(c: Context) = {
+ c.abort(c.enclosingPosition, "aborted")
+ }
+ def abort = macro impl
+} \ No newline at end of file
diff --git a/test/files/neg/macro-abort/Test_2.scala b/test/files/neg/macro-abort/Test_2.scala
new file mode 100644
index 0000000000..1d0a7a25dc
--- /dev/null
+++ b/test/files/neg/macro-abort/Test_2.scala
@@ -0,0 +1,3 @@
+object Test extends App {
+ Macros.abort
+} \ No newline at end of file
diff --git a/test/files/neg/macro-exception.check b/test/files/neg/macro-exception.check
new file mode 100644
index 0000000000..cee8b32ebd
--- /dev/null
+++ b/test/files/neg/macro-exception.check
@@ -0,0 +1,7 @@
+Test_2.scala:2: error: exception during macro expansion:
+java.lang.Exception
+ at Macros$.impl(Macros_1.scala:6)
+
+ Macros.exception
+ ^
+one error found
diff --git a/test/files/neg/macro-exception/Macros_1.scala b/test/files/neg/macro-exception/Macros_1.scala
new file mode 100644
index 0000000000..60e4020aec
--- /dev/null
+++ b/test/files/neg/macro-exception/Macros_1.scala
@@ -0,0 +1,9 @@
+import scala.language.experimental.macros
+import scala.reflect.macros.Context
+
+object Macros {
+ def impl(c: Context) = {
+ throw new Exception()
+ }
+ def exception = macro impl
+} \ No newline at end of file
diff --git a/test/files/neg/macro-exception/Test_2.scala b/test/files/neg/macro-exception/Test_2.scala
new file mode 100644
index 0000000000..d82b21f2b2
--- /dev/null
+++ b/test/files/neg/macro-exception/Test_2.scala
@@ -0,0 +1,3 @@
+object Test extends App {
+ Macros.exception
+} \ No newline at end of file
diff --git a/test/files/neg/macro-invalidusage-presuper.check b/test/files/neg/macro-invalidusage-presuper.check
index f63a0eef80..c0b1ec0248 100644
--- a/test/files/neg/macro-invalidusage-presuper.check
+++ b/test/files/neg/macro-invalidusage-presuper.check
@@ -1,4 +1,4 @@
-Macros_Test_2.scala:3: error: only type definitions and concrete field definitions allowed in early object initialization section
+Macros_Test_2.scala:3: error: only concrete field definitions allowed in early object initialization section
class D extends { def x = macro impl } with AnyRef
^
one error found
diff --git a/test/files/neg/t2796.check b/test/files/neg/t2796.check
index 4456a7fc19..22ee35a7e6 100644
--- a/test/files/neg/t2796.check
+++ b/test/files/neg/t2796.check
@@ -1,6 +1,9 @@
+t2796.scala:11: warning: early type members are deprecated. Move them to the regular body: the semantics are the same.
+ type X = Int // warn
+ ^
t2796.scala:7: warning: Implementation restriction: early definitions in traits are not initialized before the super class is initialized.
val abstractVal = "T1.abstractVal" // warn
^
error: No warnings can be incurred under -Xfatal-warnings.
-one warning found
+two warnings found
one error found
diff --git a/test/files/neg/t2796.flags b/test/files/neg/t2796.flags
index e8fb65d50c..d1b831ea87 100644
--- a/test/files/neg/t2796.flags
+++ b/test/files/neg/t2796.flags
@@ -1 +1 @@
--Xfatal-warnings \ No newline at end of file
+-deprecation -Xfatal-warnings \ No newline at end of file
diff --git a/test/files/neg/t2796.scala b/test/files/neg/t2796.scala
index 3bcc9df562..fa2f2358b9 100644
--- a/test/files/neg/t2796.scala
+++ b/test/files/neg/t2796.scala
@@ -8,10 +8,9 @@ trait T1 extends {
} with Base
trait T2 extends {
- type X = Int // okay
+ type X = Int // warn
} with Base
-
class C1 extends {
val abstractVal = "C1.abstractVal" // okay
} with Base
diff --git a/test/files/neg/t7020.check b/test/files/neg/t7020.check
new file mode 100644
index 0000000000..f9600ca7fc
--- /dev/null
+++ b/test/files/neg/t7020.check
@@ -0,0 +1,19 @@
+t7020.scala:3: warning: match may not be exhaustive.
+It would fail on the following inputs: List((x: Int forSome x not in (1, 2, 4, 5, 6, 7))), List((x: Int forSome x not in (1, 2, 4, 5, 6, 7)), _), List(1, _), List(2, _), List(4, _), List(5, _), List(6, _), List(7, _), List(??, _), List(_, _)
+ List(5) match {
+ ^
+t7020.scala:10: warning: match may not be exhaustive.
+It would fail on the following inputs: List((x: Int forSome x not in (1, 2, 4, 5, 6, 7))), List((x: Int forSome x not in (1, 2, 4, 5, 6, 7)), _), List(1, _), List(2, _), List(4, _), List(5, _), List(6, _), List(7, _), List(??, _), List(_, _)
+ List(5) match {
+ ^
+t7020.scala:17: warning: match may not be exhaustive.
+It would fail on the following inputs: List((x: Int forSome x not in (1, 2, 4, 5, 6, 7))), List((x: Int forSome x not in (1, 2, 4, 5, 6, 7)), _), List(1, _), List(2, _), List(4, _), List(5, _), List(6, _), List(7, _), List(??, _), List(_, _)
+ List(5) match {
+ ^
+t7020.scala:24: warning: match may not be exhaustive.
+It would fail on the following inputs: List((x: Int forSome x not in (1, 2, 4, 5, 6, 7))), List((x: Int forSome x not in (1, 2, 4, 5, 6, 7)), _), List(1, _), List(2, _), List(4, _), List(5, _), List(6, _), List(7, _), List(??, _), List(_, _)
+ List(5) match {
+ ^
+error: No warnings can be incurred under -Xfatal-warnings.
+four warnings found
+one error found
diff --git a/test/files/neg/t7020.flags b/test/files/neg/t7020.flags
new file mode 100644
index 0000000000..e8fb65d50c
--- /dev/null
+++ b/test/files/neg/t7020.flags
@@ -0,0 +1 @@
+-Xfatal-warnings \ No newline at end of file
diff --git a/test/files/neg/t7020.scala b/test/files/neg/t7020.scala
new file mode 100644
index 0000000000..cc5421bab1
--- /dev/null
+++ b/test/files/neg/t7020.scala
@@ -0,0 +1,30 @@
+object Test {
+ // warning was non-deterministic
+ List(5) match {
+ case 1 :: Nil | 2 :: Nil =>
+ case (x@(4 | 5 | 6)) :: Nil =>
+ case 7 :: Nil =>
+ case Nil =>
+ }
+
+ List(5) match {
+ case 1 :: Nil | 2 :: Nil =>
+ case (x@(4 | 5 | 6)) :: Nil =>
+ case 7 :: Nil =>
+ case Nil =>
+ }
+
+ List(5) match {
+ case 1 :: Nil | 2 :: Nil =>
+ case (x@(4 | 5 | 6)) :: Nil =>
+ case 7 :: Nil =>
+ case Nil =>
+ }
+
+ List(5) match {
+ case 1 :: Nil | 2 :: Nil =>
+ case (x@(4 | 5 | 6)) :: Nil =>
+ case 7 :: Nil =>
+ case Nil =>
+ }
+}
diff --git a/test/files/neg/t7501.check b/test/files/neg/t7501.check
new file mode 100644
index 0000000000..2ded07c7ed
--- /dev/null
+++ b/test/files/neg/t7501.check
@@ -0,0 +1,7 @@
+t7501_2.scala:2: error: value name is not a member of A
+ def foo(a: A) = a.name
+ ^
+t7501_2.scala:4: error: not found: type X
+ type TP = X // already failed before this fix
+ ^
+two errors found
diff --git a/test/files/neg/t7501/t7501_1.scala b/test/files/neg/t7501/t7501_1.scala
new file mode 100644
index 0000000000..323c327623
--- /dev/null
+++ b/test/files/neg/t7501/t7501_1.scala
@@ -0,0 +1,12 @@
+object Test2 {
+ def test[X](name: String) = 12
+}
+class strangeTest(x: Int) extends scala.annotation.StaticAnnotation
+
+trait A {
+ // When picking the type of `test`, the value parameter
+ // `x` was pickled with the owner `trait A`. On unpickling,
+ // it was taken to be a member!
+ @strangeTest(Test2.test("test"))
+ def test(x: String): Unit
+}
diff --git a/test/files/neg/t7501/t7501_2.scala b/test/files/neg/t7501/t7501_2.scala
new file mode 100644
index 0000000000..044caea3c3
--- /dev/null
+++ b/test/files/neg/t7501/t7501_2.scala
@@ -0,0 +1,5 @@
+object Test {
+ def foo(a: A) = a.name
+
+ type TP = X // already failed before this fix
+}
diff --git a/test/files/neg/t7694b.check b/test/files/neg/t7694b.check
new file mode 100644
index 0000000000..ea3d7736f8
--- /dev/null
+++ b/test/files/neg/t7694b.check
@@ -0,0 +1,7 @@
+t7694b.scala:8: error: type arguments [_3,_4] do not conform to trait L's type parameter bounds [A2,B2 <: A2]
+ def d = if (true) (null: L[A, A]) else (null: L[B, B])
+ ^
+t7694b.scala:9: error: type arguments [_1,_2] do not conform to trait L's type parameter bounds [A2,B2 <: A2]
+ val v = if (true) (null: L[A, A]) else (null: L[B, B])
+ ^
+two errors found
diff --git a/test/files/neg/t7752.check b/test/files/neg/t7752.check
new file mode 100644
index 0000000000..0a015d3f37
--- /dev/null
+++ b/test/files/neg/t7752.check
@@ -0,0 +1,27 @@
+t7752.scala:25: error: overloaded method value foo with alternatives:
+ [A](heading: String, rows: A*)(A,) <and>
+ [A, B](heading: (String, String), rows: (A, B)*)(A, B) <and>
+ [A, B, C](heading: (String, String, String), rows: (A, B, C)*)(A, B, C) <and>
+ [A, B, C, D](heading: (String, String, String, String), rows: (A, B, C, D)*)(A, B, C, D) <and>
+ [A, B, C, D, E](heading: (String, String, String, String, String), rows: (A, B, C, D, E)*)(A, B, C, D, E) <and>
+ [A, B, C, D, E, F](heading: (String, String, String, String, String, String), rows: (A, B, C, D, E, F)*)(A, B, C, D, E, F) <and>
+ [A, B, C, D, E, F, G](heading: (String, String, String, String, String, String, String), rows: (A, B, C, D, E, F, G)*)(A, B, C, D, E, F, G) <and>
+ [A, B, C, D, E, F, G, H](heading: (String, String, String, String, String, String, String, String), rows: (A, B, C, D, E, F, G, H)*)(A, B, C, D, E, F, G, H) <and>
+ [A, B, C, D, E, F, G, H, I](heading: (String, String, String, String, String, String, String, String, String), rows: (A, B, C, D, E, F, G, H, I)*)(A, B, C, D, E, F, G, H, I) <and>
+ [A, B, C, D, E, F, G, H, I, J](heading: (String, String, String, String, String, String, String, String, String, String), rows: (A, B, C, D, E, F, G, H, I, J)*)(A, B, C, D, E, F, G, H, I, J) <and>
+ [A, B, C, D, E, F, G, H, I, J, K](heading: (String, String, String, String, String, String, String, String, String, String, String), rows: (A, B, C, D, E, F, G, H, I, J, K)*)(A, B, C, D, E, F, G, H, I, J, K) <and>
+ [A, B, C, D, E, F, G, H, I, J, K, L](heading: (String, String, String, String, String, String, String, String, String, String, String, String), rows: (A, B, C, D, E, F, G, H, I, J, K, L)*)(A, B, C, D, E, F, G, H, I, J, K, L) <and>
+ [A, B, C, D, E, F, G, H, I, J, K, L, M](heading: (String, String, String, String, String, String, String, String, String, String, String, String, String), rows: (A, B, C, D, E, F, G, H, I, J, K, L, M)*)(A, B, C, D, E, F, G, H, I, J, K, L, M) <and>
+ [A, B, C, D, E, F, G, H, I, J, K, L, M, N](heading: (String, String, String, String, String, String, String, String, String, String, String, String, String, String), rows: (A, B, C, D, E, F, G, H, I, J, K, L, M, N)*)(A, B, C, D, E, F, G, H, I, J, K, L, M, N) <and>
+ [A, B, C, D, E, F, G, H, I, J, K, L, M, N, O](heading: (String, String, String, String, String, String, String, String, String, String, String, String, String, String, String), rows: (A, B, C, D, E, F, G, H, I, J, K, L, M, N, O)*)(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O) <and>
+ [A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P](heading: (String, String, String, String, String, String, String, String, String, String, String, String, String, String, String, String), rows: (A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P)*)(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P) <and>
+ [A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q](heading: (String, String, String, String, String, String, String, String, String, String, String, String, String, String, String, String, String), rows: (A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q)*)(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q) <and>
+ [A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R](heading: (String, String, String, String, String, String, String, String, String, String, String, String, String, String, String, String, String, String), rows: (A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R)*)(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R) <and>
+ [A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S](heading: (String, String, String, String, String, String, String, String, String, String, String, String, String, String, String, String, String, String, String), rows: (A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S)*)(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S) <and>
+ [A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T](heading: (String, String, String, String, String, String, String, String, String, String, String, String, String, String, String, String, String, String, String, String), rows: (A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T)*)(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T) <and>
+ [A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U](heading: (String, String, String, String, String, String, String, String, String, String, String, String, String, String, String, String, String, String, String, String, String), rows: (A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U)*)(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U) <and>
+ [A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V](heading: (String, String, String, String, String, String, String, String, String, String, String, String, String, String, String, String, String, String, String, String, String, String), rows: (A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V)*)(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V)
+ cannot be applied to (Int)
+ foo((1))
+ ^
+one error found
diff --git a/test/files/neg/t7752.scala b/test/files/neg/t7752.scala
new file mode 100644
index 0000000000..40ba2103b1
--- /dev/null
+++ b/test/files/neg/t7752.scala
@@ -0,0 +1,26 @@
+object Test {
+ def foo[A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V](heading: (String, String, String, String, String, String, String, String, String, String, String, String, String, String, String, String, String, String, String, String, String, String), rows: (A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V)*): Tuple22[A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V] = null
+ def foo[A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U](heading: (String, String, String, String, String, String, String, String, String, String, String, String, String, String, String, String, String, String, String, String, String), rows: (A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U)*): Tuple21[A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U] = null
+ def foo[A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T](heading: (String, String, String, String, String, String, String, String, String, String, String, String, String, String, String, String, String, String, String, String), rows: (A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T)*): Tuple20[A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T] = null
+ def foo[A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S](heading: (String, String, String, String, String, String, String, String, String, String, String, String, String, String, String, String, String, String, String), rows: (A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S)*): Tuple19[A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S] = null
+ def foo[A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R](heading: (String, String, String, String, String, String, String, String, String, String, String, String, String, String, String, String, String, String), rows: (A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R)*): Tuple18[A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R] = null
+ def foo[A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q](heading: (String, String, String, String, String, String, String, String, String, String, String, String, String, String, String, String, String), rows: (A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q)*): Tuple17[A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q] = null
+ def foo[A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P](heading: (String, String, String, String, String, String, String, String, String, String, String, String, String, String, String, String), rows: (A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P)*): Tuple16[A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P] = null
+ def foo[A, B, C, D, E, F, G, H, I, J, K, L, M, N, O](heading: (String, String, String, String, String, String, String, String, String, String, String, String, String, String, String), rows: (A, B, C, D, E, F, G, H, I, J, K, L, M, N, O)*): Tuple15[A,B,C,D,E,F,G,H,I,J,K,L,M,N,O] = null
+ def foo[A, B, C, D, E, F, G, H, I, J, K, L, M, N](heading: (String, String, String, String, String, String, String, String, String, String, String, String, String, String), rows: (A, B, C, D, E, F, G, H, I, J, K, L, M, N)*): Tuple14[A,B,C,D,E,F,G,H,I,J,K,L,M,N] = null
+ def foo[A, B, C, D, E, F, G, H, I, J, K, L, M](heading: (String, String, String, String, String, String, String, String, String, String, String, String, String), rows: (A, B, C, D, E, F, G, H, I, J, K, L, M)*): Tuple13[A,B,C,D,E,F,G,H,I,J,K,L,M] = null
+ def foo[A, B, C, D, E, F, G, H, I, J, K, L](heading: (String, String, String, String, String, String, String, String, String, String, String, String), rows: (A, B, C, D, E, F, G, H, I, J, K, L)*): Tuple12[A,B,C,D,E,F,G,H,I,J,K,L] = null
+ def foo[A, B, C, D, E, F, G, H, I, J, K](heading: (String, String, String, String, String, String, String, String, String, String, String), rows: (A, B, C, D, E, F, G, H, I, J, K)*): Tuple11[A,B,C,D,E,F,G,H,I,J,K] = null
+ def foo[A, B, C, D, E, F, G, H, I, J](heading: (String, String, String, String, String, String, String, String, String, String), rows: (A, B, C, D, E, F, G, H, I, J)*): Tuple10[A,B,C,D,E,F,G,H,I,J] = null
+ def foo[A, B, C, D, E, F, G, H, I](heading: (String, String, String, String, String, String, String, String, String), rows: (A, B, C, D, E, F, G, H, I)*): Tuple9[A,B,C,D,E,F,G,H,I] = null
+ def foo[A, B, C, D, E, F, G, H](heading: (String, String, String, String, String, String, String, String), rows: (A, B, C, D, E, F, G, H)*): Tuple8[A,B,C,D,E,F,G,H] = null
+ def foo[A, B, C, D, E, F, G](heading: (String, String, String, String, String, String, String), rows: (A, B, C, D, E, F, G)*): Tuple7[A,B,C,D,E,F,G] = null
+ def foo[A, B, C, D, E, F](heading: (String, String, String, String, String, String), rows: (A, B, C, D, E, F)*): Tuple6[A,B,C,D,E,F] = null
+ def foo[A, B, C, D, E](heading: (String, String, String, String, String), rows: (A, B, C, D, E)*): Tuple5[A,B,C,D,E] = null
+ def foo[A, B, C, D](heading: (String, String, String, String), rows: (A, B, C, D)*): Tuple4[A,B,C,D] = null
+ def foo[A, B, C](heading: (String, String, String), rows: (A, B, C)*): Tuple3[A,B,C] = null
+ def foo[A, B](heading: (String, String), rows: (A, B)*): Tuple2[A,B] = null
+ def foo[A](heading: String, rows: A*): Tuple1[A] = null
+
+ foo((1))
+} \ No newline at end of file
diff --git a/test/files/pos/t7014/ThreadSafety.java b/test/files/pos/t7014/ThreadSafety.java
new file mode 100644
index 0000000000..ed508804e3
--- /dev/null
+++ b/test/files/pos/t7014/ThreadSafety.java
@@ -0,0 +1,9 @@
+package t7014;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+@Retention(RetentionPolicy.RUNTIME) // must be exactly RUNTIME retention (those we parse)
+public @interface ThreadSafety {
+ ThreadSafetyLevel level();
+} \ No newline at end of file
diff --git a/test/files/pos/t7014/ThreadSafetyLevel.java b/test/files/pos/t7014/ThreadSafetyLevel.java
new file mode 100644
index 0000000000..4df1dc787a
--- /dev/null
+++ b/test/files/pos/t7014/ThreadSafetyLevel.java
@@ -0,0 +1,8 @@
+package t7014; // package needed due to other bug in scalac's java parser
+
+// since we parse eagerly, we have not yet parsed the classfile when parsing the annotation,
+// and on doing so, fail to find a symbol for the COMPLETELY_THREADSAFE reference
+// from the annotation's argument to the enum's member
+// for now, let's just not crash -- should implement lazy completing at some point
+@ThreadSafety(level=ThreadSafetyLevel.COMPLETELY_THREADSAFE)
+public enum ThreadSafetyLevel { COMPLETELY_THREADSAFE }
diff --git a/test/files/pos/t7014/t7014.scala b/test/files/pos/t7014/t7014.scala
new file mode 100644
index 0000000000..faec4c7740
--- /dev/null
+++ b/test/files/pos/t7014/t7014.scala
@@ -0,0 +1,4 @@
+package t7014
+
+import ThreadSafetyLevel.COMPLETELY_THREADSAFE // refer to annotation so it gets parsed
+ \ No newline at end of file
diff --git a/test/files/pos/t7486-named.scala b/test/files/pos/t7486-named.scala
new file mode 100644
index 0000000000..253293e5f1
--- /dev/null
+++ b/test/files/pos/t7486-named.scala
@@ -0,0 +1,8 @@
+
+object Test {
+ def fold(empty: Any) = ()
+ implicit val notAnnotatedImplicit = new {
+ fold(empty = 0)
+ def empty[A]: Any = ???
+ }
+}
diff --git a/test/pending/pos/t7486.scala b/test/files/pos/t7486.scala
index 6dd7f4c4ac..6dd7f4c4ac 100644
--- a/test/pending/pos/t7486.scala
+++ b/test/files/pos/t7486.scala
diff --git a/test/files/pos/t7694.scala b/test/files/pos/t7694.scala
new file mode 100644
index 0000000000..9852d5ec79
--- /dev/null
+++ b/test/files/pos/t7694.scala
@@ -0,0 +1,40 @@
+trait A
+trait B
+
+trait L[A2, B2 <: A2] {
+ def bar(a: Any, b: Any) = 0
+}
+
+object Lub {
+ // use named args transforms to include TypeTree(<lub.tpe>) in the AST before refchecks.
+ def foo(a: L[_, _], b: Any) = 0
+
+ foo(b = 0, a = if (true) (null: L[A, A]) else (null: L[B, B]))
+
+ (if (true) (null: L[A, A]) else (null: L[B, B])).bar(b = 0, a = 0)
+}
+
+/*
+The LUB ends up as:
+
+TypeRef(
+ TypeSymbol(
+ abstract trait L#7038[A2#7039, B2#7040 <: A2#7039] extends AnyRef#2197
+
+ )
+ args = List(
+ AbstractTypeRef(
+ AbstractType(
+ type _1#13680 >: A#7036 with B#7037 <: Object#1752
+ )
+ )
+ AbstractTypeRef(
+ AbstractType(
+ type _2#13681 >: A#7036 with B#7037 <: Object#1752
+ )
+ )
+ )
+)
+
+Note that type _2#13681 is *not* bound by _1#13680
+*/
diff --git a/test/files/pos/t7716.scala b/test/files/pos/t7716.scala
new file mode 100644
index 0000000000..40117051ed
--- /dev/null
+++ b/test/files/pos/t7716.scala
@@ -0,0 +1,16 @@
+object Test {
+ def test: Unit = {
+ val e: java.lang.Enum[_] = java.util.concurrent.TimeUnit.SECONDS
+ e match { case x => println(x) }
+
+
+ trait TA[X <: CharSequence]
+ val ta: TA[_] = new TA[String] {}
+
+ ta match {
+ case _ => println("hi")
+ }
+
+ def f(ta: TA[_]) = ta match { case _ => "hi" }
+ }
+}
diff --git a/test/files/pos/t7785.scala b/test/files/pos/t7785.scala
new file mode 100644
index 0000000000..1de693d137
--- /dev/null
+++ b/test/files/pos/t7785.scala
@@ -0,0 +1,34 @@
+import scala.language._
+
+trait R[+Repr]
+
+trait TraversableOps {
+ implicit val R: R[Nothing] = ???
+
+ // Removing the implicit parameter in both fixes the crash
+ // removing it into one only gives a valid compiler error.
+ trait OpsDup1[Repr] {
+ def force(implicit bf: R[Repr]): Any
+ }
+
+ trait Ops[Repr] extends OpsDup1[Repr] {
+ def force(implicit bf: R[Repr], dummy: DummyImplicit): Any
+ }
+
+ implicit def ct2ops[T, C[+X]](t: C[T]):
+ Ops[C[T]]
+
+ def force[T](t: Option[T]) =
+ // ct2ops(t).force
+ t.force //Fails compilation on 2.10.2.
+
+
+ /* To get a closer look at the crash:
+ :power
+ val foo = typeOf[C].member(TermName("foo"))
+ val pt = analyzer.HasMember(TermName("force"))
+ val instantiated = foo.info.finalResultType.instantiateTypeParams(foo.typeParams, foo.typeParams.map(TypeVar(_)))
+ instantiated <:< pt
+ */
+ def foo[T, C[+X]]: Ops[C[T]]
+}
diff --git a/test/files/pos/t942/Amount_1.java b/test/files/pos/t942/Amount_1.java
new file mode 100644
index 0000000000..d9d37d127b
--- /dev/null
+++ b/test/files/pos/t942/Amount_1.java
@@ -0,0 +1,5 @@
+import java.util.concurrent.Callable;
+
+public abstract class Amount_1<Q> extends Object
+ implements Callable<Amount_1<?>> {
+}
diff --git a/test/files/pos/t942/Test_2.scala b/test/files/pos/t942/Test_2.scala
new file mode 100644
index 0000000000..3cc84dae3c
--- /dev/null
+++ b/test/files/pos/t942/Test_2.scala
@@ -0,0 +1,3 @@
+abstract class Foo {
+ val x: Amount_1[Foo]
+}
diff --git a/test/files/run/analyzerPlugins.scala b/test/files/run/analyzerPlugins.scala
index b20a734fe6..4b297ff220 100644
--- a/test/files/run/analyzerPlugins.scala
+++ b/test/files/run/analyzerPlugins.scala
@@ -8,7 +8,9 @@ object Test extends DirectTest {
def code = """
class testAnn extends annotation.TypeConstraint
- class A(param: Double) extends { val x: Int = 1; val y = "two"; type T = A } with AnyRef {
+ class A(param: Double) extends { val x: Int = 1; val y = "two" } with AnyRef {
+ type T = A
+
val inferField = ("str": @testAnn)
val annotField: Boolean @testAnn = false
@@ -81,7 +83,7 @@ object Test extends DirectTest {
output += s"pluginsPt($pt, ${treeClass(tree)})"
pt
}
-
+
override def pluginsTyped(tpe: Type, typer: Typer, tree: Tree, mode: Mode, pt: Type): Type = {
output += s"pluginsTyped($tpe, ${treeClass(tree)})"
tpe
diff --git a/test/files/run/deprecate-early-type-defs.check b/test/files/run/deprecate-early-type-defs.check
new file mode 100644
index 0000000000..1ee01df13e
--- /dev/null
+++ b/test/files/run/deprecate-early-type-defs.check
@@ -0,0 +1,3 @@
+deprecate-early-type-defs.scala:1: warning: early type members are deprecated. Move them to the regular body: the semantics are the same.
+object Test extends { type T = Int } with App
+ ^
diff --git a/test/files/run/deprecate-early-type-defs.flags b/test/files/run/deprecate-early-type-defs.flags
new file mode 100644
index 0000000000..c36e713ab8
--- /dev/null
+++ b/test/files/run/deprecate-early-type-defs.flags
@@ -0,0 +1 @@
+-deprecation \ No newline at end of file
diff --git a/test/files/run/deprecate-early-type-defs.scala b/test/files/run/deprecate-early-type-defs.scala
new file mode 100644
index 0000000000..99e42166f2
--- /dev/null
+++ b/test/files/run/deprecate-early-type-defs.scala
@@ -0,0 +1 @@
+object Test extends { type T = Int } with App \ No newline at end of file
diff --git a/test/files/run/macro-auto-duplicate.check b/test/files/run/macro-auto-duplicate.check
new file mode 100644
index 0000000000..d81cc0710e
--- /dev/null
+++ b/test/files/run/macro-auto-duplicate.check
@@ -0,0 +1 @@
+42
diff --git a/test/files/run/macro-auto-duplicate/Macros_1.scala b/test/files/run/macro-auto-duplicate/Macros_1.scala
new file mode 100644
index 0000000000..e3df05ba50
--- /dev/null
+++ b/test/files/run/macro-auto-duplicate/Macros_1.scala
@@ -0,0 +1,17 @@
+import scala.reflect.macros.Context
+import language.experimental.macros
+
+object Macros {
+ def impl(c: Context) = {
+ import c.universe._
+ val x = Ident(newTermName("x"))
+ def defAndUseX(rhs: Tree) = {
+ Block(List(ValDef(NoMods, newTermName("x"), TypeTree(), rhs)), x)
+ }
+ val xi4 = defAndUseX(Literal(Constant(4)))
+ val xs2 = defAndUseX(Literal(Constant("2")))
+ c.Expr[String](Apply(Select(xi4, newTermName("$plus")), List(xs2)))
+ }
+
+ def foo = macro impl
+} \ No newline at end of file
diff --git a/test/files/run/macro-auto-duplicate/Test_2.scala b/test/files/run/macro-auto-duplicate/Test_2.scala
new file mode 100644
index 0000000000..f697da6020
--- /dev/null
+++ b/test/files/run/macro-auto-duplicate/Test_2.scala
@@ -0,0 +1,3 @@
+object Test extends App {
+ println(Macros.foo)
+} \ No newline at end of file
diff --git a/test/files/run/macro-duplicate/Impls_Macros_1.scala b/test/files/run/macro-duplicate/Impls_Macros_1.scala
index af80147a90..85a581585f 100644
--- a/test/files/run/macro-duplicate/Impls_Macros_1.scala
+++ b/test/files/run/macro-duplicate/Impls_Macros_1.scala
@@ -26,4 +26,4 @@ object Macros {
}
def foo = macro impl
-} \ No newline at end of file
+}
diff --git a/test/files/run/reflection-magicsymbols-invoke.check b/test/files/run/reflection-magicsymbols-invoke.check
index f5258efeb7..352aefaf25 100644
--- a/test/files/run/reflection-magicsymbols-invoke.check
+++ b/test/files/run/reflection-magicsymbols-invoke.check
@@ -82,7 +82,7 @@ Array
it's important to print the list of Array's members
if some of them change (possibly, adding and/or removing magic symbols), we must update this test
constructor Array: (_length: Int)Array[T]
-constructor Object: ()java.lang.Object
+constructor Cloneable: ()java.lang.Cloneable
method !=: (x$1: Any)Boolean
method !=: (x$1: AnyRef)Boolean
method ##: ()Int
diff --git a/test/files/run/repl-trim-stack-trace.scala b/test/files/run/repl-trim-stack-trace.scala
index bbf46f2f19..0f4a43bc85 100644
--- a/test/files/run/repl-trim-stack-trace.scala
+++ b/test/files/run/repl-trim-stack-trace.scala
@@ -13,6 +13,7 @@ f: Nothing
scala> f
java.lang.Exception: Uh-oh
at .f(<console>:7)
+ ... 69 elided
scala> def f = throw new Exception("")
f: Nothing
@@ -20,6 +21,7 @@ f: Nothing
scala> f
java.lang.Exception:
at .f(<console>:7)
+ ... 69 elided
scala> def f = throw new Exception
f: Nothing
@@ -27,7 +29,16 @@ f: Nothing
scala> f
java.lang.Exception
at .f(<console>:7)
+ ... 69 elided
scala> """
+ // normalize the "elided" lines because the frame count depends on test context
+ lazy val elided = """(\s+\.{3} )\d+( elided)""".r
+ def normalize(line: String) = line match {
+ case elided(ellipsis, suffix) => s"$ellipsis???$suffix"
+ case s => s
+ }
+ override def eval() = super.eval() map normalize
+ override def expected = super.expected map normalize
}
diff --git a/test/files/run/t6392b.check b/test/files/run/t6392b.check
index 2afc48495f..1ccfced1c6 100644
--- a/test/files/run/t6392b.check
+++ b/test/files/run/t6392b.check
@@ -1 +1 @@
-ModuleDef(Modifiers(), TermName("C"), Template(List(Select(Ident(scala#PK), TypeName("AnyRef")#TPE)), emptyValDef, List(DefDef(Modifiers(), nme.CONSTRUCTOR, List(), List(List()), TypeTree(), Block(List(Apply(Select(Super(This(TypeName("C")), tpnme.EMPTY), nme.CONSTRUCTOR#PCTOR), List())), Literal(Constant(())))))))
+ModuleDef(Modifiers(), TermName("C")#MOD, Template(List(Select(Ident(scala#PK), TypeName("AnyRef")#TPE)), emptyValDef, List(DefDef(Modifiers(), nme.CONSTRUCTOR#PCTOR, List(), List(List()), TypeTree(), Block(List(Apply(Select(Super(This(TypeName("C")), tpnme.EMPTY), nme.CONSTRUCTOR#PCTOR), List())), Literal(Constant(())))))))
diff --git a/test/files/run/t6989.check b/test/files/run/t6989.check
index 8943792115..43d4bbaf02 100644
--- a/test/files/run/t6989.check
+++ b/test/files/run/t6989.check
@@ -101,6 +101,12 @@ isProtected = false
isPublic = false
privateWithin = <none>
============
+sym = constructor $PrivateJavaClass, signature = ()JavaClass_1.this.$PrivateJavaClass, owner = class $PrivateJavaClass
+isPrivate = false
+isProtected = false
+isPublic = true
+privateWithin = <none>
+============
sym = value this$0, signature = foo.JavaClass_1, owner = class $PrivateJavaClass
isPrivate = false
isProtected = false
@@ -119,6 +125,12 @@ isProtected = true
isPublic = false
privateWithin = package foo
============
+sym = constructor $ProtectedJavaClass, signature = ()JavaClass_1.this.$ProtectedJavaClass, owner = class $ProtectedJavaClass
+isPrivate = false
+isProtected = false
+isPublic = true
+privateWithin = <none>
+============
sym = value this$0, signature = foo.JavaClass_1, owner = class $ProtectedJavaClass
isPrivate = false
isProtected = false
@@ -173,6 +185,12 @@ isProtected = false
isPublic = false
privateWithin = <none>
============
+sym = constructor PrivateStaticJavaClass, signature = ()foo.JavaClass_1.PrivateStaticJavaClass, owner = class PrivateStaticJavaClass
+isPrivate = false
+isProtected = false
+isPublic = true
+privateWithin = <none>
+============
sym = object PrivateStaticJavaClass, signature = foo.JavaClass_1.PrivateStaticJavaClass.type, owner = object JavaClass_1
isPrivate = true
isProtected = false
@@ -185,6 +203,12 @@ isProtected = false
isPublic = false
privateWithin = <none>
============
+sym = constructor ProtectedStaticJavaClass, signature = ()foo.JavaClass_1.ProtectedStaticJavaClass, owner = class ProtectedStaticJavaClass
+isPrivate = false
+isProtected = false
+isPublic = true
+privateWithin = <none>
+============
sym = object ProtectedStaticJavaClass, signature = foo.JavaClass_1.ProtectedStaticJavaClass.type, owner = object JavaClass_1
isPrivate = true
isProtected = false
diff --git a/test/files/run/t7407.check b/test/files/run/t7407.check
new file mode 100644
index 0000000000..e965047ad7
--- /dev/null
+++ b/test/files/run/t7407.check
@@ -0,0 +1 @@
+Hello
diff --git a/test/files/run/t7407.flags b/test/files/run/t7407.flags
new file mode 100644
index 0000000000..c8547a27dc
--- /dev/null
+++ b/test/files/run/t7407.flags
@@ -0,0 +1 @@
+-Ynooptimise -Ybackend:GenBCode
diff --git a/test/files/run/t7407.scala b/test/files/run/t7407.scala
new file mode 100644
index 0000000000..cf67602126
--- /dev/null
+++ b/test/files/run/t7407.scala
@@ -0,0 +1,11 @@
+// SI-7407
+object Test {
+
+ def main(args: Array[String]) { println(foo) }
+
+ def foo: String = {
+ try return "Hello" finally 10 match {case x => ()}
+ }
+
+}
+
diff --git a/test/files/run/t7407b.check b/test/files/run/t7407b.check
new file mode 100644
index 0000000000..f30294447b
--- /dev/null
+++ b/test/files/run/t7407b.check
@@ -0,0 +1,2 @@
+Hello
+abc
diff --git a/test/files/run/t7407b.flags b/test/files/run/t7407b.flags
new file mode 100644
index 0000000000..c8547a27dc
--- /dev/null
+++ b/test/files/run/t7407b.flags
@@ -0,0 +1 @@
+-Ynooptimise -Ybackend:GenBCode
diff --git a/test/files/run/t7407b.scala b/test/files/run/t7407b.scala
new file mode 100644
index 0000000000..b0c00878b5
--- /dev/null
+++ b/test/files/run/t7407b.scala
@@ -0,0 +1,20 @@
+object Test {
+
+ def main(args: Array[String]) {
+ println(foo(true))
+ println(foo(false))
+ }
+
+ def foo(b: Boolean): String = {
+ try {
+ if(b)
+ return "Hello"
+ else
+ "abc"
+ } finally {
+ 10 match {case x => ()}
+ }
+ }
+
+}
+
diff --git a/test/files/run/t7510.check b/test/files/run/t7510.check
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/test/files/run/t7510.check
diff --git a/test/files/run/t7510/Ann_1.java b/test/files/run/t7510/Ann_1.java
new file mode 100644
index 0000000000..c8c5b2035f
--- /dev/null
+++ b/test/files/run/t7510/Ann_1.java
@@ -0,0 +1,4 @@
+package foo;
+
+public @interface Ann_1 {
+} \ No newline at end of file
diff --git a/test/files/run/t7510/Test_2.scala b/test/files/run/t7510/Test_2.scala
new file mode 100644
index 0000000000..7d7a95e0f2
--- /dev/null
+++ b/test/files/run/t7510/Test_2.scala
@@ -0,0 +1,9 @@
+import scala.reflect.runtime.universe._
+import scala.reflect.runtime.{currentMirror => cm}
+import scala.tools.reflect.ToolBox
+
+object Test extends App {
+ val tb = cm.mkToolBox()
+ tb.compile(tb.parse("@foo.Ann_1 class C"))
+}
+
diff --git a/test/files/run/t7763.scala b/test/files/run/t7763.scala
new file mode 100644
index 0000000000..638077e64a
--- /dev/null
+++ b/test/files/run/t7763.scala
@@ -0,0 +1,20 @@
+object Test {
+ class A; class B
+ def main(args: Array[String]) {
+ def noExpectedType() {
+ a().asInstanceOf[B] // cast elided!
+ }
+ def withExpectedType(): B = {
+ a().asInstanceOf[B]
+ }
+ def test(a: => Any) = try {
+ a
+ sys.error("no CCE!")
+ } catch {case _: ClassCastException => }
+
+ test(noExpectedType())
+ test(withExpectedType())
+ }
+
+ def a(): Object = new A
+}
diff --git a/test/files/run/toolbox_current_run_compiles.check b/test/files/run/toolbox_current_run_compiles.check
new file mode 100644
index 0000000000..da29283aaa
--- /dev/null
+++ b/test/files/run/toolbox_current_run_compiles.check
@@ -0,0 +1,2 @@
+true
+false
diff --git a/test/files/run/toolbox_current_run_compiles.scala b/test/files/run/toolbox_current_run_compiles.scala
new file mode 100644
index 0000000000..b48c998e64
--- /dev/null
+++ b/test/files/run/toolbox_current_run_compiles.scala
@@ -0,0 +1,28 @@
+package pkg {
+ import scala.reflect.macros.Context
+ import scala.language.experimental.macros
+
+ object Macros {
+ def impl[T: c.WeakTypeTag](c: Context) = {
+ import c.universe._
+ val sym = c.weakTypeOf[T].typeSymbol
+ val g = c.universe.asInstanceOf[scala.tools.nsc.Global]
+ c.Expr[Boolean](Literal(Constant(g.currentRun.compiles(sym.asInstanceOf[g.Symbol]))))
+ }
+ def compiles[T] = macro impl[T]
+ }
+}
+
+import scala.reflect.runtime.universe._
+import scala.reflect.runtime.{universe => ru}
+import scala.tools.reflect.ToolBox
+
+object Test extends App {
+ val cm = ru.runtimeMirror(getClass.getClassLoader)
+ val toolbox = cm.mkToolBox()
+ toolbox.eval(toolbox.parse("""{
+ class C
+ println(pkg.Macros.compiles[C])
+ println(pkg.Macros.compiles[Object])
+ }"""))
+} \ No newline at end of file
diff --git a/test/junit/scala/reflect/io/ZipArchiveTest.scala b/test/junit/scala/reflect/io/ZipArchiveTest.scala
new file mode 100644
index 0000000000..1bcd06f5a7
--- /dev/null
+++ b/test/junit/scala/reflect/io/ZipArchiveTest.scala
@@ -0,0 +1,37 @@
+package scala.reflect.io
+
+import java.io.{IOException, File => JFile}
+import org.junit.Assert._
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.JUnit4
+
+@RunWith(classOf[JUnit4])
+class ZipArchiveTest {
+
+ @Test
+ def corruptZip {
+ val f = JFile.createTempFile("test", ".jar")
+ val fza = new FileZipArchive(f)
+ try {
+ fza.iterator
+ } catch {
+ case x: IOException =>
+ assertTrue(x.getMessage, x.getMessage.contains(f.getPath))
+ } finally {
+ f.delete()
+ }
+ }
+
+ @Test
+ def missingFile {
+ val f = new JFile("xxx.does.not.exist")
+ val fza = new FileZipArchive(f)
+ try {
+ fza.iterator
+ } catch {
+ case x: IOException =>
+ assertTrue(x.getMessage, x.getMessage.contains(f.getPath))
+ }
+ }
+}
diff --git a/test/junit/scala/tools/nsc/util/StackTraceTest.scala b/test/junit/scala/tools/nsc/util/StackTraceTest.scala
new file mode 100644
index 0000000000..e7654244c5
--- /dev/null
+++ b/test/junit/scala/tools/nsc/util/StackTraceTest.scala
@@ -0,0 +1,159 @@
+
+package scala.tools.nsc.util
+
+import scala.language.reflectiveCalls
+import scala.util._
+import PartialFunction.cond
+import Properties.isJavaAtLeast
+
+import org.junit.Assert._
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.JUnit4
+
+trait Expecting {
+ /*
+ import org.expecty.Expecty
+ final val expect = new Expecty
+ */
+}
+
+
+@RunWith(classOf[JUnit4])
+class StackTraceTest extends Expecting {
+ // formerly an enum
+ val CausedBy = "Caused by: "
+ val Suppressed = "Suppressed: "
+
+ // throws
+ def sample = throw new RuntimeException("Point of failure")
+ def sampler: String = sample
+
+ // repackage with message
+ def resample: String = try { sample } catch { case e: Throwable => throw new RuntimeException("resample", e) }
+ def resampler: String = resample
+
+ // simple wrapper
+ def wrapper: String = try { sample } catch { case e: Throwable => throw new RuntimeException(e) }
+ // another onion skin
+ def rewrapper: String = try { wrapper } catch { case e: Throwable => throw new RuntimeException(e) }
+ def rewrapperer: String = rewrapper
+
+ // only an insane wretch would do this
+ def insane: String = try { sample } catch {
+ case e: Throwable =>
+ val t = new RuntimeException(e)
+ e initCause t
+ throw t
+ }
+ def insaner: String = insane
+
+ /** Java 7 */
+ val suppressable = isJavaAtLeast("1.7")
+ type Suppressing = { def addSuppressed(t: Throwable): Unit }
+
+ def repressed: String = try { sample } catch {
+ case e: Throwable =>
+ val t = new RuntimeException("My problem")
+ if (suppressable) {
+ t.asInstanceOf[Suppressing] addSuppressed e
+ }
+ throw t
+ }
+ def represser: String = repressed
+
+ // evaluating s should throw, p trims stack trace, t is the test of resulting trace string
+ def probe(s: =>String)(p: StackTraceElement => Boolean)(t: String => Unit): Unit = {
+ Try(s) recover { case e => e stackTracePrefixString p } match {
+ case Success(s) => t(s)
+ case Failure(e) => throw e
+ }
+ }
+
+ @Test def showsAllTrace() {
+ probe(sampler)(_ => true) { s =>
+ val res = s.lines.toList
+ /*
+ expect {
+ res.length > 5 // many lines
+ // these expectations may be framework-specific
+ //s contains "sbt.TestFramework"
+ //res.last contains "java.lang.Thread"
+ }
+ */
+ assert (res.length > 5)
+ }
+ }
+ @Test def showsOnlyPrefix() = probe(sample)(_.getMethodName == "sample") { s =>
+ val res = s.lines.toList
+ /*
+ expect {
+ res.length == 3 // summary + one frame + elision
+ }
+ */
+ assert (res.length == 3)
+ }
+ @Test def showsCause() = probe(resampler)(_.getMethodName != "resampler") { s =>
+ val res = s.lines.toList
+ /*
+ expect {
+ res.length == 6 // summary + one frame + elision, caused by + one frame + elision
+ res exists (_ startsWith CausedBy.toString)
+ }
+ */
+ assert (res.length == 6)
+ assert (res exists (_ startsWith CausedBy.toString))
+ }
+ @Test def showsWrappedExceptions() = probe(rewrapperer)(_.getMethodName != "rewrapperer") { s =>
+ val res = s.lines.toList
+ /*
+ expect {
+ res.length == 9 // summary + one frame + elision times three
+ res exists (_ startsWith CausedBy.toString)
+ (res collect {
+ case s if s startsWith CausedBy.toString => s
+ }).size == 2
+ }
+ */
+ assert (res.length == 9)
+ assert (res exists (_ startsWith CausedBy.toString))
+ assert ((res collect {
+ case s if s startsWith CausedBy.toString => s
+ }).size == 2)
+ }
+ @Test def dontBlowOnCycle() = probe(insaner)(_.getMethodName != "insaner") { s =>
+ val res = s.lines.toList
+ /*
+ expect {
+ res.length == 7 // summary + one frame + elision times two with extra frame
+ res exists (_ startsWith CausedBy.toString)
+ }
+ */
+ assert (res.length == 7)
+ assert (res exists (_ startsWith CausedBy.toString))
+ }
+
+ /** Java 7, but shouldn't bomb on Java 6.
+ *
+java.lang.RuntimeException: My problem
+ at scala.tools.nsc.util.StackTraceTest.repressed(StackTraceTest.scala:56)
+ ... 27 elided
+ Suppressed: java.lang.RuntimeException: Point of failure
+ at scala.tools.nsc.util.StackTraceTest.sample(StackTraceTest.scala:29)
+ at scala.tools.nsc.util.StackTraceTest.repressed(StackTraceTest.scala:54)
+ ... 27 more
+ */
+ @Test def showsSuppressed() = probe(represser)(_.getMethodName != "represser") { s =>
+ val res = s.lines.toList
+ if (suppressable) {
+ assert (res.length == 7)
+ assert (res exists (_.trim startsWith Suppressed.toString))
+ }
+ /*
+ expect {
+ res.length == 7
+ res exists (_ startsWith " " + Suppressed.toString)
+ }
+ */
+ }
+}
diff --git a/test/pending/pos/t7778/Foo_1.java b/test/pending/pos/t7778/Foo_1.java
new file mode 100644
index 0000000000..65431ffd46
--- /dev/null
+++ b/test/pending/pos/t7778/Foo_1.java
@@ -0,0 +1,6 @@
+import java.util.concurrent.Callable;
+
+public abstract class Foo_1<T> implements Callable<Foo_1<Object>.Inner> {
+ public abstract class Inner {
+ }
+}
diff --git a/test/pending/pos/t7778/Test_2.scala b/test/pending/pos/t7778/Test_2.scala
new file mode 100644
index 0000000000..306303a99e
--- /dev/null
+++ b/test/pending/pos/t7778/Test_2.scala
@@ -0,0 +1,3 @@
+class Test {
+ null: Foo_1[_]
+}
diff --git a/test/pending/run/t7733.check b/test/pending/run/t7733.check
new file mode 100644
index 0000000000..19765bd501
--- /dev/null
+++ b/test/pending/run/t7733.check
@@ -0,0 +1 @@
+null
diff --git a/test/pending/run/t7733/Separate_1.scala b/test/pending/run/t7733/Separate_1.scala
new file mode 100644
index 0000000000..a326ecd53e
--- /dev/null
+++ b/test/pending/run/t7733/Separate_1.scala
@@ -0,0 +1,5 @@
+package test
+
+class Separate {
+ for (i <- 1 to 10) println(i)
+} \ No newline at end of file
diff --git a/test/pending/run/t7733/Test_2.scala b/test/pending/run/t7733/Test_2.scala
new file mode 100644
index 0000000000..28358574ec
--- /dev/null
+++ b/test/pending/run/t7733/Test_2.scala
@@ -0,0 +1,9 @@
+import scala.reflect.runtime.universe._
+import scala.reflect.runtime.{currentMirror => cm}
+import scala.tools.reflect.ToolBox
+
+object Test extends App {
+ val tb = cm.mkToolBox()
+ val code = tb.parse("{ val x: test.Separate$$anonfun$1 = null; x }")
+ println(tb.eval(code))
+} \ No newline at end of file
diff --git a/tools/binary-repo-lib.sh b/tools/binary-repo-lib.sh
index 704bf4944d..654ba21547 100755
--- a/tools/binary-repo-lib.sh
+++ b/tools/binary-repo-lib.sh
@@ -4,7 +4,7 @@
remote_urlget="http://repo.typesafe.com/typesafe/scala-sha-bootstrap/org/scala-lang/bootstrap"
-remote_urlpush="http://typesafe.artifactoryonline.com/typesafe/scala-sha-bootstrap/org/scala-lang/bootstrap"
+remote_urlpush="http://private-repo.typesafe.com/typesafe/scala-sha-bootstrap/org/scala-lang/bootstrap"
libraryJar="$(pwd)/lib/scala-library.jar"
desired_ext=".desired.sha1"
push_jar="$(pwd)/tools/push.jar"