summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/compiler/scala/reflect/makro/runtime/Enclosures.scala1
-rw-r--r--src/compiler/scala/tools/nsc/Driver.scala4
-rw-r--r--src/compiler/scala/tools/nsc/Main.scala6
-rw-r--r--src/compiler/scala/tools/nsc/MainBench.scala48
-rw-r--r--src/compiler/scala/tools/nsc/symtab/SymbolLoaders.scala21
-rw-r--r--src/compiler/scala/tools/nsc/transform/LambdaLift.scala85
-rw-r--r--src/compiler/scala/tools/nsc/transform/PostErasure.scala2
-rw-r--r--src/compiler/scala/tools/nsc/transform/TailCalls.scala16
-rw-r--r--src/compiler/scala/tools/nsc/transform/UnCurry.scala21
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Contexts.scala6
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Macros.scala4
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Namers.scala4
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/PatternMatching.scala328
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/RefChecks.scala2
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala13
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Typers.scala7
-rw-r--r--src/compiler/scala/tools/reflect/FastTrack.scala2
-rw-r--r--src/compiler/scala/tools/reflect/MacroImplementations.scala9
-rw-r--r--src/eclipse/partest/.classpath14
-rw-r--r--src/eclipse/partest/.project35
-rw-r--r--src/eclipse/reflect/.classpath1
-rw-r--r--src/eclipse/scala-compiler/.classpath1
-rw-r--r--src/eclipse/scalap/.classpath12
-rw-r--r--src/eclipse/scalap/.project35
-rw-r--r--src/library/scala/Double.scala3
-rw-r--r--src/library/scala/Enumeration.scala7
-rw-r--r--src/library/scala/Float.scala3
-rw-r--r--src/library/scala/collection/immutable/Vector.scala26
-rw-r--r--src/library/scala/concurrent/ExecutionContext.scala2
-rw-r--r--src/library/scala/concurrent/Future.scala22
-rw-r--r--src/library/scala/concurrent/FutureTaskRunner.scala3
-rw-r--r--src/library/scala/concurrent/ManagedBlocker.scala1
-rw-r--r--src/library/scala/concurrent/Scheduler.scala54
-rw-r--r--src/library/scala/concurrent/Task.scala13
-rw-r--r--src/library/scala/concurrent/TaskRunner.scala2
-rw-r--r--src/library/scala/concurrent/TaskRunners.scala2
-rw-r--r--src/library/scala/concurrent/ThreadPoolRunner.scala3
-rw-r--r--src/library/scala/concurrent/ThreadRunner.scala2
-rw-r--r--src/library/scala/concurrent/impl/Future.scala15
-rw-r--r--src/library/scala/concurrent/impl/Promise.scala9
-rw-r--r--src/library/scala/concurrent/ops.scala2
-rw-r--r--src/library/scala/reflect/ClassManifest.scala8
-rw-r--r--src/partest/scala/tools/partest/nest/DirectRunner.scala3
-rw-r--r--src/reflect/scala/reflect/api/StandardNames.scala1
-rw-r--r--src/reflect/scala/reflect/internal/AnnotationInfos.scala7
-rw-r--r--src/reflect/scala/reflect/internal/Constants.scala7
-rw-r--r--src/reflect/scala/reflect/internal/Mirrors.scala3
-rw-r--r--src/reflect/scala/reflect/internal/Names.scala3
-rw-r--r--src/reflect/scala/reflect/internal/Scopes.scala20
-rw-r--r--src/reflect/scala/reflect/internal/StdNames.scala2
-rw-r--r--src/reflect/scala/reflect/internal/Symbols.scala11
-rw-r--r--src/reflect/scala/reflect/internal/Types.scala202
-rw-r--r--src/reflect/scala/reflect/makro/Enclosures.scala4
-rw-r--r--src/reflect/scala/reflect/runtime/SymbolLoaders.scala4
-rw-r--r--test/files/neg/t5892.check17
-rw-r--r--test/files/neg/t5892.scala25
-rw-r--r--test/files/pos/t5892.scala5
-rw-r--r--test/files/pos/t6028/t6028_1.scala3
-rw-r--r--test/files/pos/t6028/t6028_2.scala4
-rw-r--r--test/files/run/nullable-lazyvals.check3
-rw-r--r--test/files/run/nullable-lazyvals.scala36
-rw-r--r--test/files/run/reflect-resolveoverload-invalid.scala2
-rw-r--r--test/files/run/reflect-resolveoverload2.scala31
-rw-r--r--test/files/run/t5588.check2
-rw-r--r--test/files/run/t5588.scala14
-rw-r--r--test/files/run/t5937.scala12
-rw-r--r--test/files/run/t6028.check84
-rw-r--r--test/files/run/t6028.scala21
-rw-r--r--test/files/run/t6077_patmat_cse_irrefutable.check1
-rw-r--r--test/files/run/t6077_patmat_cse_irrefutable.scala13
-rw-r--r--test/files/run/t6089.check1
-rw-r--r--test/files/run/t6089.scala13
-rw-r--r--test/files/run/valueclasses-classmanifest-basic.check1
-rw-r--r--test/files/run/valueclasses-classmanifest-basic.scala5
-rw-r--r--test/files/run/valueclasses-classmanifest-existential.check1
-rw-r--r--test/files/run/valueclasses-classmanifest-existential.scala5
-rw-r--r--test/files/run/valueclasses-classmanifest-generic.check1
-rw-r--r--test/files/run/valueclasses-classmanifest-generic.scala5
-rw-r--r--test/files/run/valueclasses-classtag-basic.check1
-rw-r--r--test/files/run/valueclasses-classtag-basic.scala5
-rw-r--r--test/files/run/valueclasses-classtag-existential.check1
-rw-r--r--test/files/run/valueclasses-classtag-existential.scala5
-rw-r--r--test/files/run/valueclasses-classtag-generic.check1
-rw-r--r--test/files/run/valueclasses-classtag-generic.scala5
-rw-r--r--test/files/run/valueclasses-manifest-basic.check1
-rw-r--r--test/files/run/valueclasses-manifest-basic.scala5
-rw-r--r--test/files/run/valueclasses-manifest-existential.check1
-rw-r--r--test/files/run/valueclasses-manifest-existential.scala5
-rw-r--r--test/files/run/valueclasses-manifest-generic.check1
-rw-r--r--test/files/run/valueclasses-manifest-generic.scala5
-rw-r--r--test/files/run/valueclasses-typetag-basic.check1
-rw-r--r--test/files/run/valueclasses-typetag-basic.scala5
-rw-r--r--test/files/run/valueclasses-typetag-existential.check1
-rw-r--r--test/files/run/valueclasses-typetag-existential.scala5
-rw-r--r--test/files/run/valueclasses-typetag-generic.check1
-rw-r--r--test/files/run/valueclasses-typetag-generic.scala5
-rw-r--r--test/files/specialized/t6035.check1
-rw-r--r--test/files/specialized/t6035/first_1.scala5
-rw-r--r--test/files/specialized/t6035/second_2.scala13
-rw-r--r--test/pending/pos/t1751.cmds (renamed from test/files/pos/t1751.cmds)0
-rw-r--r--test/pending/pos/t1751/A1_2.scala (renamed from test/files/pos/t1751/A1_2.scala)0
-rw-r--r--test/pending/pos/t1751/A2_1.scala (renamed from test/files/pos/t1751/A2_1.scala)0
-rw-r--r--test/pending/pos/t1751/SuiteClasses.java (renamed from test/files/pos/t1751/SuiteClasses.java)0
-rw-r--r--test/pending/pos/t1782.cmds (renamed from test/files/pos/t1782.cmds)0
-rw-r--r--test/pending/pos/t1782/Ann.java (renamed from test/files/pos/t1782/Ann.java)0
-rw-r--r--test/pending/pos/t1782/Days.java (renamed from test/files/pos/t1782/Days.java)0
-rw-r--r--test/pending/pos/t1782/ImplementedBy.java (renamed from test/files/pos/t1782/ImplementedBy.java)0
-rw-r--r--test/pending/pos/t1782/Test_1.scala (renamed from test/files/pos/t1782/Test_1.scala)0
-rw-r--r--test/pending/pos/t294.cmds (renamed from test/files/pos/t294.cmds)0
-rw-r--r--test/pending/pos/t294/Ann.java (renamed from test/files/pos/t294/Ann.java)0
-rw-r--r--test/pending/pos/t294/Ann2.java (renamed from test/files/pos/t294/Ann2.java)0
-rw-r--r--test/pending/pos/t294/Test_1.scala (renamed from test/files/pos/t294/Test_1.scala)0
-rw-r--r--test/pending/pos/t294/Test_2.scala (renamed from test/files/pos/t294/Test_2.scala)0
-rw-r--r--test/pending/run/t3897.check (renamed from test/files/run/t3897.check)0
-rw-r--r--test/pending/run/t3897/J_2.java (renamed from test/files/run/t3897/J_2.java)0
-rw-r--r--test/pending/run/t3897/a_1.scala (renamed from test/files/run/t3897/a_1.scala)0
-rw-r--r--test/pending/run/t3897/a_2.scala (renamed from test/files/run/t3897/a_2.scala)0
-rw-r--r--test/pending/run/t5293-map.scala (renamed from test/files/run/t5293-map.scala)0
-rw-r--r--test/pending/run/t5293.scala (renamed from test/files/run/t5293.scala)0
-rw-r--r--test/pending/run/t5695.check2
-rw-r--r--test/pending/run/t5695/part_1.scala12
-rw-r--r--test/pending/run/t5695/part_2.scala8
122 files changed, 1051 insertions, 470 deletions
diff --git a/src/compiler/scala/reflect/makro/runtime/Enclosures.scala b/src/compiler/scala/reflect/makro/runtime/Enclosures.scala
index 80c35d22ff..360a4b8e8a 100644
--- a/src/compiler/scala/reflect/makro/runtime/Enclosures.scala
+++ b/src/compiler/scala/reflect/makro/runtime/Enclosures.scala
@@ -14,7 +14,6 @@ trait Enclosures {
// vals are eager to simplify debugging
// after all we wouldn't save that much time by making them lazy
val macroApplication: Tree = expandee
- val enclosingApplication: Tree = enclTrees collectFirst { case t: Apply => t } getOrElse EmptyTree
val enclosingClass: Tree = site.enclClass.tree
val enclosingImplicits: List[(Type, Tree)] = site.openImplicits
val enclosingMacros: List[Context] = this :: universe.analyzer.openMacros // include self
diff --git a/src/compiler/scala/tools/nsc/Driver.scala b/src/compiler/scala/tools/nsc/Driver.scala
index 0051c3bdec..15e2929ff1 100644
--- a/src/compiler/scala/tools/nsc/Driver.scala
+++ b/src/compiler/scala/tools/nsc/Driver.scala
@@ -1,10 +1,12 @@
package scala.tools.nsc
import scala.tools.nsc.reporters.{Reporter, ConsoleReporter}
-import Properties.{ versionString, copyrightString }
+import Properties.{ versionString, copyrightString, residentPromptString }
import scala.reflect.internal.util.{ BatchSourceFile, FakePos }
abstract class Driver {
+
+ val prompt = residentPromptString
val versionMsg = "Scala compiler " +
versionString + " -- " +
diff --git a/src/compiler/scala/tools/nsc/Main.scala b/src/compiler/scala/tools/nsc/Main.scala
index 19c872b6d3..8b7e76e994 100644
--- a/src/compiler/scala/tools/nsc/Main.scala
+++ b/src/compiler/scala/tools/nsc/Main.scala
@@ -12,15 +12,13 @@ import scala.tools.nsc.interactive.{ RefinedBuildManager, SimpleBuildManager }
import scala.tools.nsc.io.AbstractFile
import scala.tools.nsc.reporters.{Reporter, ConsoleReporter}
import scala.reflect.internal.util.{ BatchSourceFile, FakePos } //{Position}
-import Properties.{ versionString, copyrightString, residentPromptString, msilLibPath }
+import Properties.msilLibPath
/** The main class for NSC, a compiler for the programming
- * language Scala.
+ * language Scala.
*/
object Main extends Driver with EvalLoop {
- val prompt = residentPromptString
-
def resident(compiler: Global) {
loop { line =>
val args = line.split(' ').toList
diff --git a/src/compiler/scala/tools/nsc/MainBench.scala b/src/compiler/scala/tools/nsc/MainBench.scala
new file mode 100644
index 0000000000..0037de7b94
--- /dev/null
+++ b/src/compiler/scala/tools/nsc/MainBench.scala
@@ -0,0 +1,48 @@
+/* NSC -- new Scala compiler
+ * Copyright 2005-2011 LAMP/EPFL
+ * @author Martin Odersky
+ */
+
+package scala.tools.nsc
+
+import java.io.File
+import File.pathSeparator
+
+import scala.tools.nsc.interactive.{ RefinedBuildManager, SimpleBuildManager }
+import scala.tools.nsc.io.AbstractFile
+import scala.tools.nsc.reporters.{Reporter, ConsoleReporter}
+import scala.reflect.internal.util.{ BatchSourceFile, FakePos } //{Position}
+import Properties.{ versionString, copyrightString, residentPromptString, msilLibPath }
+import scala.reflect.internal.util.Statistics
+
+/** The main class for NSC, a compiler for the programming
+ * language Scala.
+ */
+object MainBench extends Driver with EvalLoop {
+
+ lazy val theCompiler = Global(settings, reporter)
+
+ override def newCompiler() = theCompiler
+
+ val NIter = 50
+ val NBest = 10
+
+ override def main(args: Array[String]) = {
+ val times = new Array[Long](NIter)
+ var start = System.nanoTime()
+ for (i <- 0 until NIter) {
+ if (i == NIter-1) {
+ theCompiler.settings.Ystatistics.value = true
+ Statistics.enabled = true
+ }
+ process(args)
+ val end = System.nanoTime()
+ val duration = (end-start)/1000000
+ println(s"${duration}ms")
+ times(i) = duration
+ start = end
+ }
+ val avg = times.sorted.take(NBest).sum / NBest
+ println(s"avg shortest $NBest times ${avg}ms")
+ }
+}
diff --git a/src/compiler/scala/tools/nsc/symtab/SymbolLoaders.scala b/src/compiler/scala/tools/nsc/symtab/SymbolLoaders.scala
index 0c988ceae4..9b4e793241 100644
--- a/src/compiler/scala/tools/nsc/symtab/SymbolLoaders.scala
+++ b/src/compiler/scala/tools/nsc/symtab/SymbolLoaders.scala
@@ -34,8 +34,7 @@ abstract class SymbolLoaders {
/** Enter class with given `name` into scope of `root`
* and give them `completer` as type.
*/
- def enterClass(root: Symbol, name: String, completer: SymbolLoader): Symbol = {
- val owner = root.ownerOfNewSymbols
+ def enterClass(owner: Symbol, name: String, completer: SymbolLoader): Symbol = {
val clazz = owner.newClass(newTypeName(name))
clazz setInfo completer
enterIfNew(owner, clazz, completer)
@@ -44,8 +43,7 @@ abstract class SymbolLoaders {
/** Enter module with given `name` into scope of `root`
* and give them `completer` as type.
*/
- def enterModule(root: Symbol, name: String, completer: SymbolLoader): Symbol = {
- val owner = root.ownerOfNewSymbols
+ def enterModule(owner: Symbol, name: String, completer: SymbolLoader): Symbol = {
val module = owner.newModule(newTermName(name))
module setInfo completer
module.moduleClass setInfo moduleClassLoader
@@ -217,15 +215,18 @@ abstract class SymbolLoaders {
root.setInfo(new PackageClassInfoType(newScope, root))
val sourcepaths = classpath.sourcepaths
- for (classRep <- classpath.classes if platform.doLoad(classRep)) {
- initializeFromClassPath(root, classRep)
+ if (!root.isRoot) {
+ for (classRep <- classpath.classes if platform.doLoad(classRep)) {
+ initializeFromClassPath(root, classRep)
+ }
}
+ if (!root.isEmptyPackageClass) {
+ for (pkg <- classpath.packages) {
+ enterPackage(root, pkg.name, new PackageLoader(pkg))
+ }
- for (pkg <- classpath.packages) {
- enterPackage(root, pkg.name, new PackageLoader(pkg))
+ openPackageModule(root)
}
-
- openPackageModule(root)
}
}
diff --git a/src/compiler/scala/tools/nsc/transform/LambdaLift.scala b/src/compiler/scala/tools/nsc/transform/LambdaLift.scala
index fad41ae98d..bee5aa5f4f 100644
--- a/src/compiler/scala/tools/nsc/transform/LambdaLift.scala
+++ b/src/compiler/scala/tools/nsc/transform/LambdaLift.scala
@@ -56,6 +56,31 @@ abstract class LambdaLift extends InfoTransform {
/** The set of symbols that need to be renamed. */
private val renamable = newSymSet
+ /**
+ * The new names for free variables proxies. If we simply renamed the
+ * free variables, we would transform:
+ * {{{
+ * def closure(x: Int) = { () => x }
+ * }}}
+ *
+ * To:
+ * {{{
+ * def closure(x$1: Int) = new anonFun$1(this, x$1)
+ * class anonFun$1(outer$: Outer, x$1: Int) { def apply() => x$1 }
+ * }}}
+ *
+ * This is fatally bad for named arguments (0e170e4b), extremely impolite to tools
+ * reflecting on the method parameter names in the generated bytecode (SI-6028),
+ * and needlessly bothersome to anyone using a debugger.
+ *
+ * Instead, we transform to:
+ * {{{
+ * def closure(x: Int) = new anonFun$1(this, x)
+ * class anonFun$1(outer$: Outer, x$1: Int) { def apply() => x$1 }
+ * }}}
+ */
+ private val proxyNames = mutable.HashMap[Symbol, Name]()
+
// (trait, name) -> owner
private val localTraits = mutable.HashMap[(Symbol, Name), Symbol]()
// (owner, name) -> implClass
@@ -117,15 +142,6 @@ abstract class LambdaLift extends InfoTransform {
if (!ss(sym)) {
ss addEntry sym
renamable addEntry sym
- beforePickler {
- // The param symbol in the MethodType should not be renamed, only the symbol in scope. This way,
- // parameter names for named arguments are not changed. Example: without cloning the MethodType,
- // def closure(x: Int) = { () => x }
- // would have the signature
- // closure: (x$1: Int)() => Int
- if (sym.isParameter && sym.owner.info.paramss.exists(_ contains sym))
- sym.owner modifyInfo (_ cloneInfo sym.owner)
- }
changedFreeVars = true
debuglog("" + sym + " is free in " + enclosure);
if (sym.isVariable) sym setFlag CAPTURED
@@ -215,24 +231,26 @@ abstract class LambdaLift extends InfoTransform {
def renameSym(sym: Symbol) {
val originalName = sym.name
+ sym setName newName(sym)
+ debuglog("renaming in %s: %s => %s".format(sym.owner.fullLocationString, originalName, sym.name))
+ }
+
+ def newName(sym: Symbol): Name = {
+ val originalName = sym.name
def freshen(prefix: String): Name =
if (originalName.isTypeName) unit.freshTypeName(prefix)
else unit.freshTermName(prefix)
- val newName: Name = (
- if (sym.isAnonymousFunction && sym.owner.isMethod) {
- freshen(sym.name + nme.NAME_JOIN_STRING + sym.owner.name + nme.NAME_JOIN_STRING)
- } else {
- // SI-5652 If the lifted symbol is accessed from an inner class, it will be made public. (where?)
- // Generating a a unique name, mangled with the enclosing class name, avoids a VerifyError
- // in the case that a sub-class happens to lifts out a method with the *same* name.
- val name = freshen(sym.name + nme.NAME_JOIN_STRING)
- if (originalName.isTermName && !sym.enclClass.isImplClass && calledFromInner(sym)) nme.expandedName(name, sym.enclClass)
- else name
- }
- )
- sym setName newName
- debuglog("renaming in %s: %s => %s".format(sym.owner.fullLocationString, originalName, sym.name))
+ if (sym.isAnonymousFunction && sym.owner.isMethod) {
+ freshen(sym.name + nme.NAME_JOIN_STRING + sym.owner.name + nme.NAME_JOIN_STRING)
+ } else {
+ // SI-5652 If the lifted symbol is accessed from an inner class, it will be made public. (where?)
+ // Generating a a unique name, mangled with the enclosing class name, avoids a VerifyError
+ // in the case that a sub-class happens to lifts out a method with the *same* name.
+ val name = freshen(sym.name + nme.NAME_JOIN_STRING)
+ if (originalName.isTermName && !sym.enclClass.isImplClass && calledFromInner(sym)) nme.expandedName(name, sym.enclClass)
+ else name
+ }
}
/** Rename a trait's interface and implementation class in coordinated fashion.
@@ -245,6 +263,8 @@ abstract class LambdaLift extends InfoTransform {
debuglog("renaming impl class in step with %s: %s => %s".format(traitSym, originalImplName, implSym.name))
}
+ val allFree: Set[Symbol] = free.values.flatMap(_.iterator).toSet
+
for (sym <- renamable) {
// If we renamed a trait from Foo to Foo$1, we must rename the implementation
// class from Foo$class to Foo$1$class. (Without special consideration it would
@@ -252,7 +272,9 @@ abstract class LambdaLift extends InfoTransform {
// under us, and there's no reliable link between trait symbol and impl symbol,
// we have maps from ((trait, name)) -> owner and ((owner, name)) -> impl.
localTraits remove ((sym, sym.name)) match {
- case None => renameSym(sym)
+ case None =>
+ if (allFree(sym)) proxyNames(sym) = newName(sym)
+ else renameSym(sym)
case Some(owner) =>
localImplClasses remove ((owner, sym.name)) match {
case Some(implSym) => renameTrait(sym, implSym)
@@ -267,7 +289,8 @@ abstract class LambdaLift extends InfoTransform {
debuglog("free var proxy: %s, %s".format(owner.fullLocationString, freeValues.toList.mkString(", ")))
proxies(owner) =
for (fv <- freeValues.toList) yield {
- val proxy = owner.newValue(fv.name, owner.pos, newFlags) setInfo fv.info
+ val proxyName = proxyNames.getOrElse(fv, fv.name)
+ val proxy = owner.newValue(proxyName, owner.pos, newFlags) setInfo fv.info
if (owner.isClass) owner.info.decls enter proxy
proxy
}
@@ -280,9 +303,9 @@ abstract class LambdaLift extends InfoTransform {
if (enclosure eq NoSymbol) throw new IllegalArgumentException("Could not find proxy for "+ sym.defString +" in "+ sym.ownerChain +" (currentOwner= "+ currentOwner +" )")
debuglog("searching for " + sym + "(" + sym.owner + ") in " + enclosure + " " + enclosure.logicallyEnclosingMember)
- val ps = (proxies get enclosure.logicallyEnclosingMember).toList.flatten filter (_.name == sym.name)
- if (ps.isEmpty) searchIn(enclosure.skipConstructor.owner)
- else ps.head
+ val proxyName = proxyNames.getOrElse(sym, sym.name)
+ val ps = (proxies get enclosure.logicallyEnclosingMember).toList.flatten find (_.name == proxyName)
+ ps getOrElse searchIn(enclosure.skipConstructor.owner)
}
debuglog("proxy %s from %s has logical enclosure %s".format(
sym.debugLocationString,
@@ -501,8 +524,10 @@ abstract class LambdaLift extends InfoTransform {
}
override def transformUnit(unit: CompilationUnit) {
- computeFreeVars
- afterOwnPhase(super.transformUnit(unit))
+ computeFreeVars()
+ afterOwnPhase {
+ super.transformUnit(unit)
+ }
assert(liftedDefs.isEmpty, liftedDefs.keys mkString ", ")
}
} // class LambdaLifter
diff --git a/src/compiler/scala/tools/nsc/transform/PostErasure.scala b/src/compiler/scala/tools/nsc/transform/PostErasure.scala
index 999d00520d..151bc66a79 100644
--- a/src/compiler/scala/tools/nsc/transform/PostErasure.scala
+++ b/src/compiler/scala/tools/nsc/transform/PostErasure.scala
@@ -21,6 +21,8 @@ trait PostErasure extends InfoTransform with TypingTransformers {
object elimErasedValueType extends TypeMap {
def apply(tp: Type) = tp match {
+ case ConstantType(Constant(tp: Type)) =>
+ ConstantType(Constant(apply(tp)))
case ErasedValueType(tref) =>
atPhase(currentRun.erasurePhase)(erasure.erasedValueClassArg(tref))
case _ => mapOver(tp)
diff --git a/src/compiler/scala/tools/nsc/transform/TailCalls.scala b/src/compiler/scala/tools/nsc/transform/TailCalls.scala
index 4c9d855413..d5bbc578fc 100644
--- a/src/compiler/scala/tools/nsc/transform/TailCalls.scala
+++ b/src/compiler/scala/tools/nsc/transform/TailCalls.scala
@@ -373,7 +373,7 @@ abstract class TailCalls extends Transform {
// the labels all look like: matchEnd(x) {x}
// then, in a forward jump `matchEnd(expr)`, `expr` is considered in tail position (and the matchEnd jump is replaced by the jump generated by expr)
class TailPosLabelsTraverser extends Traverser {
- val tailLabels = new collection.mutable.ListBuffer[Symbol]()
+ val tailLabels = new collection.mutable.HashSet[Symbol]()
private var maybeTail: Boolean = true // since we start in the rhs of a DefDef
@@ -388,9 +388,15 @@ abstract class TailCalls extends Transform {
def traverseTreesNoTail(trees: List[Tree]) = trees foreach traverseNoTail
override def traverse(tree: Tree) = tree match {
- case LabelDef(_, List(arg), body@Ident(_)) if arg.symbol == body.symbol => // we're looking for label(x){x} in tail position, since that means `a` is in tail position in a call `label(a)`
+ // we're looking for label(x){x} in tail position, since that means `a` is in tail position in a call `label(a)`
+ case LabelDef(_, List(arg), body@Ident(_)) if arg.symbol == body.symbol =>
if (maybeTail) tailLabels += tree.symbol
+ // jumps to matchEnd are transparent; need this case for nested matches
+ // (and the translated match case below does things in reverse for this case's sake)
+ case Apply(fun, arg :: Nil) if hasSynthCaseSymbol(fun) && tailLabels(fun.symbol) =>
+ traverse(arg)
+
// a translated casedef
case LabelDef(_, _, body) if hasSynthCaseSymbol(tree) =>
traverse(body)
@@ -400,9 +406,9 @@ abstract class TailCalls extends Transform {
// the assumption is once we encounter a case, the remainder of the block will consist of cases
// the prologue may be empty, usually it is the valdef that stores the scrut
val (prologue, cases) = stats span (s => !s.isInstanceOf[LabelDef])
- traverseTreesNoTail(prologue) // selector (may be absent)
- traverseTrees(cases)
traverse(expr)
+ traverseTrees(cases.reverse) // reverse so that we enter the matchEnd LabelDef before we see jumps to it
+ traverseTreesNoTail(prologue) // selector (may be absent)
case CaseDef(pat, guard, body) =>
traverse(body)
@@ -426,7 +432,7 @@ abstract class TailCalls extends Transform {
traverseTreesNoTail(catches)
traverseNoTail(finalizer)
- case EmptyTree | Super(_, _) | This(_) | Select(_, _) | Ident(_) | Literal(_) | Function(_, _) | TypeTree() =>
+ case Apply(_, _) | EmptyTree | Super(_, _) | This(_) | Select(_, _) | Ident(_) | Literal(_) | Function(_, _) | TypeTree() =>
case _ => super.traverse(tree)
}
}
diff --git a/src/compiler/scala/tools/nsc/transform/UnCurry.scala b/src/compiler/scala/tools/nsc/transform/UnCurry.scala
index 663b3dd2e9..efc3d25ed0 100644
--- a/src/compiler/scala/tools/nsc/transform/UnCurry.scala
+++ b/src/compiler/scala/tools/nsc/transform/UnCurry.scala
@@ -33,6 +33,14 @@ import language.postfixOps
* - convert implicit method types to method types
* - convert non-trivial catches in try statements to matches
* - convert non-local returns to throws with enclosing try statements.
+ * - convert try-catch expressions in contexts where there might be values on the stack to
+ * a local method and a call to it (since an exception empties the evaluation stack):
+ *
+ * meth(x_1,..., try { x_i } catch { ..}, .. x_b0) ==>
+ * {
+ * def liftedTry$1 = try { x_i } catch { .. }
+ * meth(x_1, .., liftedTry$1(), .. )
+ * }
*/
/*</export> */
abstract class UnCurry extends InfoTransform
@@ -564,12 +572,6 @@ abstract class UnCurry extends InfoTransform
}
val sym = tree.symbol
- // Take a pass looking for @specialize annotations and set all
- // their SPECIALIZE flags for cheaper recognition.
- if ((sym ne null) && (sym.isClass || sym.isMethod)) {
- for (tp <- sym.typeParams ; if tp hasAnnotation SpecializedClass)
- tp setFlag SPECIALIZED
- }
val result = (
// TODO - settings.noassertions.value temporarily retained to avoid
// breakage until a reasonable interface is settled upon.
@@ -640,6 +642,13 @@ abstract class UnCurry extends InfoTransform
case ret @ Return(_) if (isNonLocalReturn(ret)) =>
withNeedLift(true) { super.transform(ret) }
+ case Try(_, Nil, _) =>
+ // try-finally does not need lifting: lifting is needed only for try-catch
+ // expressions that are evaluated in a context where the stack might not be empty.
+ // `finally` does not attempt to continue evaluation after an exception, so the fact
+ // that values on the stack are 'lost' does not matter
+ super.transform(tree)
+
case Try(block, catches, finalizer) =>
if (needTryLift || shouldBeLiftedAnyway(tree)) transform(liftTree(tree))
else super.transform(tree)
diff --git a/src/compiler/scala/tools/nsc/typechecker/Contexts.scala b/src/compiler/scala/tools/nsc/typechecker/Contexts.scala
index bcf529ecd2..805f60ba87 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Contexts.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Contexts.scala
@@ -636,6 +636,12 @@ trait Contexts { self: Analyzer =>
collect(imp.tree.selectors)
}
+ /* SI-5892 / SI-4270: `implicitss` can return results which are not accessible at the
+ * point where implicit search is triggered. Example: implicits in (annotations of)
+ * class type parameters (SI-5892). The `context.owner` is the class symbol, therefore
+ * `implicitss` will return implicit conversions defined inside the class. These are
+ * filtered out later by `eligibleInfos` (SI-4270 / 9129cfe9), as they don't type-check.
+ */
def implicitss: List[List[ImplicitInfo]] = {
if (implicitsRunId != currentRunId) {
implicitsRunId = currentRunId
diff --git a/src/compiler/scala/tools/nsc/typechecker/Macros.scala b/src/compiler/scala/tools/nsc/typechecker/Macros.scala
index 322b9ebb25..b7043e58de 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Macros.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Macros.scala
@@ -26,7 +26,7 @@ import java.lang.reflect.{Array => jArray, Method => jMethod}
* def fooBar[T: c.TypeTag]
* (c: scala.reflect.makro.Context)
* (xs: c.Expr[List[T]])
- * : c.Tree = {
+ * : c.Expr[T] = {
* ...
* }
*
@@ -601,7 +601,7 @@ trait Macros extends scala.tools.reflect.FastTrack with Traces {
if (settings.XmacroPrimaryClasspath.value != "") {
macroLogVerbose("primary macro classloader: initializing from -Xmacro-primary-classpath: %s".format(settings.XmacroPrimaryClasspath.value))
- val classpath = toURLs(settings.XmacroFallbackClasspath.value)
+ val classpath = toURLs(settings.XmacroPrimaryClasspath.value)
ScalaClassLoader.fromURLs(classpath, self.getClass.getClassLoader)
} else {
macroLogVerbose("primary macro classloader: initializing from -cp: %s".format(global.classPath.asURLs))
diff --git a/src/compiler/scala/tools/nsc/typechecker/Namers.scala b/src/compiler/scala/tools/nsc/typechecker/Namers.scala
index 48fd6ba928..dc9f07cad9 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Namers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Namers.scala
@@ -1214,8 +1214,8 @@ trait Namers extends MethodSynthesis {
if (!annotated.isInitialized) tree match {
case defn: MemberDef =>
val ainfos = defn.mods.annotations filterNot (_ eq null) map { ann =>
- // need to be lazy, #1782
- AnnotationInfo lazily (typer typedAnnotation ann)
+ // need to be lazy, #1782. beforeTyper to allow inferView in annotation args, SI-5892.
+ AnnotationInfo lazily beforeTyper(typer typedAnnotation ann)
}
if (ainfos.nonEmpty) {
annotated setAnnotations ainfos
diff --git a/src/compiler/scala/tools/nsc/typechecker/PatternMatching.scala b/src/compiler/scala/tools/nsc/typechecker/PatternMatching.scala
index da45b9bde3..4e4176e531 100644
--- a/src/compiler/scala/tools/nsc/typechecker/PatternMatching.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/PatternMatching.scala
@@ -47,8 +47,11 @@ trait PatternMatching extends Transform with TypingTransformers with ast.TreeDSL
val phaseName: String = "patmat"
// TODO: the inliner fails to inline the closures to patmatDebug
- // private val printPatmat = settings.Ypatmatdebug.value
- // @inline final def patmatDebug(s: => String) = if (printPatmat) println(s)
+ object debugging {
+ val printPatmat = settings.Ypatmatdebug.value
+ @inline final def patmatDebug(s: => String) = if (printPatmat) println(s)
+ }
+ import debugging.patmatDebug
def newTransformer(unit: CompilationUnit): Transformer =
if (opt.virtPatmat) new MatchTransformer(unit)
@@ -185,7 +188,7 @@ trait PatternMatching extends Transform with TypingTransformers with ast.TreeDSL
// (that would require more sophistication when generating trees,
// and the only place that emits Matches after typers is for exception handling anyway)
if(phase.id >= currentRun.uncurryPhase.id) debugwarn("running translateMatch at "+ phase +" on "+ selector +" match "+ cases)
- // patmatDebug ("translating "+ cases.mkString("{", "\n", "}"))
+ patmatDebug("translating "+ cases.mkString("{", "\n", "}"))
def repeatedToSeq(tp: Type): Type = (tp baseType RepeatedParamClass) match {
case TypeRef(_, RepeatedParamClass, arg :: Nil) => seqType(arg)
@@ -310,14 +313,14 @@ trait PatternMatching extends Transform with TypingTransformers with ast.TreeDSL
if (!extractor.isTyped) ErrorUtils.issueNormalTypeError(patTree, "Could not typecheck extractor call: "+ extractor)(context)
// if (extractor.resultInMonad == ErrorType) throw new TypeError(pos, "Unsupported extractor type: "+ extractor.tpe)
- // patmatDebug ("translateExtractorPattern checking parameter type: "+ (patBinder, patBinder.info.widen, extractor.paramType, patBinder.info.widen <:< extractor.paramType))
+ patmatDebug("translateExtractorPattern checking parameter type: "+ (patBinder, patBinder.info.widen, extractor.paramType, patBinder.info.widen <:< extractor.paramType))
// must use type `tp`, which is provided by extractor's result, not the type expected by binder,
// as b.info may be based on a Typed type ascription, which has not been taken into account yet by the translation
// (it will later result in a type test when `tp` is not a subtype of `b.info`)
// TODO: can we simplify this, together with the Bound case?
(extractor.subPatBinders, extractor.subPatTypes).zipped foreach { case (b, tp) =>
- // patmatDebug ("changing "+ b +" : "+ b.info +" -> "+ tp)
+ patmatDebug("changing "+ b +" : "+ b.info +" -> "+ tp)
b setInfo tp
}
@@ -424,7 +427,7 @@ trait PatternMatching extends Transform with TypingTransformers with ast.TreeDSL
*/
case Bind(n, p) => // this happens in certain ill-formed programs, there'll be an error later
- // patmatDebug ("WARNING: Bind tree with unbound symbol "+ patTree)
+ patmatDebug("WARNING: Bind tree with unbound symbol "+ patTree)
noFurtherSubPats() // there's no symbol -- something's wrong... don't fail here though (or should we?)
// case Star(_) | ArrayValue | This => error("stone age pattern relics encountered!")
@@ -634,7 +637,7 @@ trait PatternMatching extends Transform with TypingTransformers with ast.TreeDSL
// binder has type paramType
def treeMaker(binder: Symbol, pos: Position): TreeMaker = {
// checks binder ne null before chaining to the next extractor
- ProductExtractorTreeMaker(binder, lengthGuard(binder), Substitution(subPatBinders, subPatRefs(binder)))
+ ProductExtractorTreeMaker(binder, lengthGuard(binder))(Substitution(subPatBinders, subPatRefs(binder)))
}
// reference the (i-1)th case accessor if it exists, otherwise the (i-1)th tuple component
@@ -678,7 +681,7 @@ trait PatternMatching extends Transform with TypingTransformers with ast.TreeDSL
// the extractor call (applied to the binder bound by the flatMap corresponding to the previous (i.e., enclosing/outer) pattern)
val extractorApply = atPos(pos)(spliceApply(patBinderOrCasted))
val binder = freshSym(pos, pureType(resultInMonad)) // can't simplify this when subPatBinders.isEmpty, since UnitClass.tpe is definitely wrong when isSeq, and resultInMonad should always be correct since it comes directly from the extractor's result type
- ExtractorTreeMaker(extractorApply, lengthGuard(binder), binder, Substitution(subPatBinders, subPatRefs(binder)))(resultType.typeSymbol == BooleanClass, checkedLength, patBinderOrCasted)
+ ExtractorTreeMaker(extractorApply, lengthGuard(binder), binder)(Substitution(subPatBinders, subPatRefs(binder)), resultType.typeSymbol == BooleanClass, checkedLength, patBinderOrCasted)
}
override protected def seqTree(binder: Symbol): Tree =
@@ -827,7 +830,7 @@ trait PatternMatching extends Transform with TypingTransformers with ast.TreeDSL
private[TreeMakers] def incorporateOuterSubstitution(outerSubst: Substitution): Unit = {
if (currSub ne null) {
- // patmatDebug ("BUG: incorporateOuterSubstitution called more than once for "+ (this, currSub, outerSubst))
+ patmatDebug("BUG: incorporateOuterSubstitution called more than once for "+ (this, currSub, outerSubst))
Thread.dumpStack()
}
else currSub = outerSubst >> substitution
@@ -889,7 +892,7 @@ trait PatternMatching extends Transform with TypingTransformers with ast.TreeDSL
* the function's body is determined by the next TreeMaker
* in this function's body, and all the subsequent ones, references to the symbols in `from` will be replaced by the corresponding tree in `to`
*/
- case class ExtractorTreeMaker(extractor: Tree, extraCond: Option[Tree], nextBinder: Symbol, localSubstitution: Substitution)(extractorReturnsBoolean: Boolean, val checkedLength: Option[Int], val prevBinder: Symbol) extends FunTreeMaker {
+ case class ExtractorTreeMaker(extractor: Tree, extraCond: Option[Tree], nextBinder: Symbol)(val localSubstitution: Substitution, extractorReturnsBoolean: Boolean, val checkedLength: Option[Int], val prevBinder: Symbol) extends FunTreeMaker {
def chainBefore(next: Tree)(casegen: Casegen): Tree = {
val condAndNext = extraCond map (casegen.ifThenElseZero(_, next)) getOrElse next
atPos(extractor.pos)(
@@ -902,7 +905,7 @@ trait PatternMatching extends Transform with TypingTransformers with ast.TreeDSL
}
// TODO: allow user-defined unapplyProduct
- case class ProductExtractorTreeMaker(prevBinder: Symbol, extraCond: Option[Tree], localSubstitution: Substitution) extends FunTreeMaker { import CODE._
+ case class ProductExtractorTreeMaker(prevBinder: Symbol, extraCond: Option[Tree])(val localSubstitution: Substitution) extends FunTreeMaker { import CODE._
val nextBinder = prevBinder // just passing through
def chainBefore(next: Tree)(casegen: Casegen): Tree = {
val nullCheck = REF(prevBinder) OBJ_NE NULL
@@ -993,7 +996,7 @@ trait PatternMatching extends Transform with TypingTransformers with ast.TreeDSL
**/
case class TypeTestTreeMaker(prevBinder: Symbol, testedBinder: Symbol, expectedTp: Type, nextBinderTp: Type)(override val pos: Position, extractorArgTypeTest: Boolean = false) extends CondTreeMaker {
import TypeTestTreeMaker._
- // patmatDebug ("TTTM"+(prevBinder, extractorArgTypeTest, testedBinder, expectedTp, nextBinderTp))
+ patmatDebug("TTTM"+(prevBinder, extractorArgTypeTest, testedBinder, expectedTp, nextBinderTp))
lazy val outerTestNeeded = (
!((expectedTp.prefix eq NoPrefix) || expectedTp.prefix.typeSymbol.isPackageClass)
@@ -1121,7 +1124,7 @@ trait PatternMatching extends Transform with TypingTransformers with ast.TreeDSL
def combineCasesNoSubstOnly(scrut: Tree, scrutSym: Symbol, casesNoSubstOnly: List[List[TreeMaker]], pt: Type, owner: Symbol, matchFailGenOverride: Option[Tree => Tree]): Tree =
fixerUpper(owner, scrut.pos){
def matchFailGen = (matchFailGenOverride orElse Some(CODE.MATCHERROR(_: Tree)))
- // patmatDebug ("combining cases: "+ (casesNoSubstOnly.map(_.mkString(" >> ")).mkString("{", "\n", "}")))
+ patmatDebug("combining cases: "+ (casesNoSubstOnly.map(_.mkString(" >> ")).mkString("{", "\n", "}")))
val (unchecked, requireSwitch) =
if (settings.XnoPatmatAnalysis.value) (true, false)
@@ -1175,12 +1178,12 @@ trait PatternMatching extends Transform with TypingTransformers with ast.TreeDSL
t match {
case Function(_, _) if t.symbol == NoSymbol =>
t.symbol = currentOwner.newAnonymousFunctionValue(t.pos)
- // patmatDebug ("new symbol for "+ (t, t.symbol.ownerChain))
+ patmatDebug("new symbol for "+ (t, t.symbol.ownerChain))
case Function(_, _) if (t.symbol.owner == NoSymbol) || (t.symbol.owner == origOwner) =>
- // patmatDebug ("fundef: "+ (t, t.symbol.ownerChain, currentOwner.ownerChain))
+ patmatDebug("fundef: "+ (t, t.symbol.ownerChain, currentOwner.ownerChain))
t.symbol.owner = currentOwner
case d : DefTree if (d.symbol != NoSymbol) && ((d.symbol.owner == NoSymbol) || (d.symbol.owner == origOwner)) => // don't indiscriminately change existing owners! (see e.g., pos/t3440, pos/t3534, pos/unapplyContexts2)
- // patmatDebug ("def: "+ (d, d.symbol.ownerChain, currentOwner.ownerChain))
+ patmatDebug("def: "+ (d, d.symbol.ownerChain, currentOwner.ownerChain))
if(d.symbol.isLazy) { // for lazy val's accessor -- is there no tree??
assert(d.symbol.lazyAccessor != NoSymbol && d.symbol.lazyAccessor.owner == d.symbol.owner, d.symbol.lazyAccessor)
d.symbol.lazyAccessor.owner = currentOwner
@@ -1190,7 +1193,7 @@ trait PatternMatching extends Transform with TypingTransformers with ast.TreeDSL
d.symbol.owner = currentOwner
// case _ if (t.symbol != NoSymbol) && (t.symbol ne null) =>
- // patmatDebug ("untouched "+ (t, t.getClass, t.symbol.ownerChain, currentOwner.ownerChain))
+ patmatDebug("untouched "+ (t, t.getClass, t.symbol.ownerChain, currentOwner.ownerChain))
case _ =>
}
super.traverse(t)
@@ -1386,7 +1389,7 @@ trait PatternMatching extends Transform with TypingTransformers with ast.TreeDSL
case object FalseCond extends Cond {override def toString = "F"}
case class AndCond(a: Cond, b: Cond) extends Cond {override def toString = a +"/\\"+ b}
- case class OrCond(a: Cond, b: Cond) extends Cond {override def toString = "("+a+") \\/ ("+ b +")"}
+ case class OrCond(a: Cond, b: Cond) extends Cond {override def toString = "("+a+") \\/ ("+ b +")"}
object EqualityCond {
private val uniques = new collection.mutable.HashMap[(Tree, Tree), EqualityCond]
@@ -1445,9 +1448,9 @@ trait PatternMatching extends Transform with TypingTransformers with ast.TreeDSL
case _ => false
}
- def unapply(xtm: ExtractorTreeMaker): Option[(Tree, Symbol, Substitution)] = xtm match {
- case ExtractorTreeMaker(extractor, None, nextBinder, subst) if irrefutableExtractorType(extractor.tpe) =>
- Some(extractor, nextBinder, subst)
+ def unapply(xtm: ExtractorTreeMaker): Option[(Tree, Symbol)] = xtm match {
+ case ExtractorTreeMaker(extractor, None, nextBinder) if irrefutableExtractorType(extractor.tpe) =>
+ Some(extractor, nextBinder)
case _ =>
None
}
@@ -1455,18 +1458,13 @@ trait PatternMatching extends Transform with TypingTransformers with ast.TreeDSL
// returns (tree, tests), where `tree` will be used to refer to `root` in `tests`
class TreeMakersToConds(val root: Symbol) {
- def discard() = {
- pointsToBound.clear()
- trees.clear()
- normalize = EmptySubstitution
- accumSubst = EmptySubstitution
- }
// a variable in this set should never be replaced by a tree that "does not consist of a selection on a variable in this set" (intuitively)
private val pointsToBound = collection.mutable.HashSet(root)
private val trees = collection.mutable.HashSet.empty[Tree]
// the substitution that renames variables to variables in pointsToBound
private var normalize: Substitution = EmptySubstitution
+ private var substitutionComputed = false
// replaces a variable (in pointsToBound) by a selection on another variable in pointsToBound
// in the end, instead of having x1, x1.hd, x2, x2.hd, ... flying around,
@@ -1476,29 +1474,6 @@ trait PatternMatching extends Transform with TypingTransformers with ast.TreeDSL
// pointsToBound -- accumSubst.from == Set(root) && (accumSubst.from.toSet -- pointsToBound) isEmpty
private var accumSubst: Substitution = EmptySubstitution
- private def updateSubstitution(subst: Substitution) = {
- // find part of substitution that replaces bound symbols by new symbols, and reverse that part
- // so that we don't introduce new aliases for existing symbols, thus keeping the set of bound symbols minimal
- val (boundSubst, unboundSubst) = (subst.from zip subst.to) partition {
- case (f, t) =>
- t.isInstanceOf[Ident] && (t.symbol ne NoSymbol) && pointsToBound(f)
- }
- val (boundFrom, boundTo) = boundSubst.unzip
- val (unboundFrom, unboundTo) = unboundSubst.unzip
-
- // reverse substitution that would otherwise replace a variable we already encountered by a new variable
- // NOTE: this forgets the more precise type we have for these later variables, but that's probably okay
- normalize >>= Substitution(boundTo map (_.symbol), boundFrom map (CODE.REF(_)))
- // patmatDebug ("normalize subst: "+ normalize)
-
- val okSubst = Substitution(unboundFrom, unboundTo map (normalize(_))) // it's important substitution does not duplicate trees here -- it helps to keep hash consing simple, anyway
- pointsToBound ++= ((okSubst.from, okSubst.to).zipped filter { (f, t) => pointsToBound exists (sym => t.exists(_.symbol == sym)) })._1
- // patmatDebug ("pointsToBound: "+ pointsToBound)
-
- accumSubst >>= okSubst
- // patmatDebug ("accumSubst: "+ accumSubst)
- }
-
// hashconsing trees (modulo value-equality)
def unique(t: Tree, tpOverride: Type = NoType): Tree =
trees find (a => a.correspondsStructure(t)(sameValue)) match {
@@ -1529,74 +1504,120 @@ trait PatternMatching extends Transform with TypingTransformers with ast.TreeDSL
// note that the sequencing of operations is important: must visit in same order as match execution
// binderToUniqueTree uses the type of the first symbol that was encountered as the type for all future binders
- final def treeMakerToCond(tm: TreeMaker, handleUnknown: TreeMaker => Cond, updateSubst: Boolean, rewriteNil: Boolean = false): Cond = {
- if (updateSubst) updateSubstitution(tm.substitution)
-
- tm match {
- case ttm@TypeTestTreeMaker(prevBinder, testedBinder, pt, _) =>
- object condStrategy extends TypeTestTreeMaker.TypeTestCondStrategy {
- type Result = Cond
- def and(a: Result, b: Result) = AndCond(a, b)
- def outerTest(testedBinder: Symbol, expectedTp: Type) = TrueCond // TODO OuterEqCond(testedBinder, expectedType)
- def typeTest(b: Symbol, pt: Type) = { // a type test implies the tested path is non-null (null.isInstanceOf[T] is false for all T)
- val p = binderToUniqueTree(b); AndCond(NonNullCond(p), TypeCond(p, uniqueTp(pt)))
+ abstract class TreeMakerToCond extends (TreeMaker => Cond) {
+ // requires(if (!substitutionComputed))
+ def updateSubstitution(subst: Substitution): Unit = {
+ // find part of substitution that replaces bound symbols by new symbols, and reverse that part
+ // so that we don't introduce new aliases for existing symbols, thus keeping the set of bound symbols minimal
+ val (boundSubst, unboundSubst) = (subst.from zip subst.to) partition {
+ case (f, t) =>
+ t.isInstanceOf[Ident] && (t.symbol ne NoSymbol) && pointsToBound(f)
+ }
+ val (boundFrom, boundTo) = boundSubst.unzip
+ val (unboundFrom, unboundTo) = unboundSubst.unzip
+
+ // reverse substitution that would otherwise replace a variable we already encountered by a new variable
+ // NOTE: this forgets the more precise type we have for these later variables, but that's probably okay
+ normalize >>= Substitution(boundTo map (_.symbol), boundFrom map (CODE.REF(_)))
+ // patmatDebug ("normalize subst: "+ normalize)
+
+ val okSubst = Substitution(unboundFrom, unboundTo map (normalize(_))) // it's important substitution does not duplicate trees here -- it helps to keep hash consing simple, anyway
+ pointsToBound ++= ((okSubst.from, okSubst.to).zipped filter { (f, t) => pointsToBound exists (sym => t.exists(_.symbol == sym)) })._1
+ // patmatDebug("pointsToBound: "+ pointsToBound)
+
+ accumSubst >>= okSubst
+ // patmatDebug("accumSubst: "+ accumSubst)
+ }
+
+ def handleUnknown(tm: TreeMaker): Cond
+
+ /** apply itself must render a faithful representation of the TreeMaker
+ *
+ * Concretely, TrueCond must only be used to represent a TreeMaker that is sure to match and that does not do any computation at all
+ * e.g., doCSE relies on apply itself being sound in this sense (since it drops TreeMakers that are approximated to TrueCond -- SI-6077)
+ *
+ * handleUnknown may be customized by the caller to approximate further
+ *
+ * TODO: don't ignore outer-checks
+ */
+ def apply(tm: TreeMaker): Cond = {
+ if (!substitutionComputed) updateSubstitution(tm.substitution)
+
+ tm match {
+ case ttm@TypeTestTreeMaker(prevBinder, testedBinder, pt, _) =>
+ object condStrategy extends TypeTestTreeMaker.TypeTestCondStrategy {
+ type Result = Cond
+ def and(a: Result, b: Result) = AndCond(a, b)
+ def outerTest(testedBinder: Symbol, expectedTp: Type) = TrueCond // TODO OuterEqCond(testedBinder, expectedType)
+ def typeTest(b: Symbol, pt: Type) = { // a type test implies the tested path is non-null (null.isInstanceOf[T] is false for all T)
+ val p = binderToUniqueTree(b); AndCond(NonNullCond(p), TypeCond(p, uniqueTp(pt)))
+ }
+ def nonNullTest(testedBinder: Symbol) = NonNullCond(binderToUniqueTree(testedBinder))
+ def equalsTest(pat: Tree, testedBinder: Symbol) = EqualityCond(binderToUniqueTree(testedBinder), unique(pat))
+ def eqTest(pat: Tree, testedBinder: Symbol) = EqualityCond(binderToUniqueTree(testedBinder), unique(pat)) // TODO: eq, not ==
}
- def nonNullTest(testedBinder: Symbol) = NonNullCond(binderToUniqueTree(testedBinder))
- def equalsTest(pat: Tree, testedBinder: Symbol) = EqualityCond(binderToUniqueTree(testedBinder), unique(pat))
- def eqTest(pat: Tree, testedBinder: Symbol) = EqualityCond(binderToUniqueTree(testedBinder), unique(pat)) // TODO: eq, not ==
- }
- ttm.renderCondition(condStrategy)
- case EqualityTestTreeMaker(prevBinder, patTree, _) => EqualityCond(binderToUniqueTree(prevBinder), unique(patTree))
- case AlternativesTreeMaker(_, altss, _) => \/(altss map (alts => /\(alts map (treeMakerToCond(_, handleUnknown, updateSubst)))))
- case ProductExtractorTreeMaker(testedBinder, None, subst) => NonNullCond(binderToUniqueTree(testedBinder))
- case IrrefutableExtractorTreeMaker(_, _, _) =>
- // the extra condition is None, the extractor's result indicates it always succeeds,
- // and the potential type-test for the argument is represented by a separate TypeTestTreeMaker
- TrueCond
- case GuardTreeMaker(guard) =>
- guard.tpe match {
- case ConstantType(Constant(true)) => TrueCond
- case ConstantType(Constant(false)) => FalseCond
- case _ => handleUnknown(tm)
- }
- case p @ ExtractorTreeMaker(extractor, Some(lenCheck), testedBinder, _) =>
- p.checkedLength match {
- // special-case: interpret pattern `List()` as `Nil`
- // TODO: make it more general List(1, 2) => 1 :: 2 :: Nil -- not sure this is a good idea...
- case Some(0) if rewriteNil && testedBinder.tpe.typeSymbol == ListClass => // extractor.symbol.owner == SeqFactory
- EqualityCond(binderToUniqueTree(p.prevBinder), unique(Ident(NilModule) setType NilModule.tpe))
- case _ => handleUnknown(tm)
- }
- case SubstOnlyTreeMaker(_, _) => TrueCond
- case ProductExtractorTreeMaker(_, Some(_), _) |
- ExtractorTreeMaker(_, _, _, _) | BodyTreeMaker(_, _) => handleUnknown(tm)
+ ttm.renderCondition(condStrategy)
+ case EqualityTestTreeMaker(prevBinder, patTree, _) => EqualityCond(binderToUniqueTree(prevBinder), unique(patTree))
+ case AlternativesTreeMaker(_, altss, _) => \/(altss map (alts => /\(alts map this)))
+ case ProductExtractorTreeMaker(testedBinder, None) => NonNullCond(binderToUniqueTree(testedBinder))
+ case SubstOnlyTreeMaker(_, _) => TrueCond
+ case GuardTreeMaker(guard) =>
+ guard.tpe match {
+ case ConstantType(Constant(true)) => TrueCond
+ case ConstantType(Constant(false)) => FalseCond
+ case _ => handleUnknown(tm)
+ }
+ case ExtractorTreeMaker(_, _, _) |
+ ProductExtractorTreeMaker(_, _) |
+ BodyTreeMaker(_, _) => handleUnknown(tm)
+ }
}
}
- val constFalse = (_: TreeMaker) => FalseCond
- val constTrue = (_: TreeMaker) => TrueCond
- final def approximateMatch(cases: List[List[TreeMaker]], handleUnknown: TreeMaker => Cond = constFalse, rewriteNil: Boolean = false): List[List[Test]] =
- cases.map { _ map (tm => Test(treeMakerToCond(tm, handleUnknown, updateSubst = true, rewriteNil), tm)) }
+ private val irrefutableExtractor: PartialFunction[TreeMaker, Cond] = {
+ // the extra condition is None, the extractor's result indicates it always succeeds,
+ // (the potential type-test for the argument is represented by a separate TypeTestTreeMaker)
+ case IrrefutableExtractorTreeMaker(_, _) => TrueCond
+ }
- final def approximateMatchAgain(cases: List[List[TreeMaker]], handleUnknown: TreeMaker => Cond = constFalse, rewriteNil: Boolean = false): List[List[Test]] =
- cases.map { _ map (tm => Test(treeMakerToCond(tm, handleUnknown, updateSubst = false, rewriteNil), tm)) }
- }
+ // special-case: interpret pattern `List()` as `Nil`
+ // TODO: make it more general List(1, 2) => 1 :: 2 :: Nil -- not sure this is a good idea...
+ private val rewriteListPattern: PartialFunction[TreeMaker, Cond] = {
+ case p @ ExtractorTreeMaker(_, _, testedBinder)
+ if testedBinder.tpe.typeSymbol == ListClass && p.checkedLength == Some(0) =>
+ EqualityCond(binderToUniqueTree(p.prevBinder), unique(Ident(NilModule) setType NilModule.tpe))
+ }
+ val fullRewrite = (irrefutableExtractor orElse rewriteListPattern)
+ val refutableRewrite = irrefutableExtractor
+ @inline def onUnknown(handler: TreeMaker => Cond) = new TreeMakerToCond {
+ def handleUnknown(tm: TreeMaker) = handler(tm)
+ }
- def approximateMatch(root: Symbol, cases: List[List[TreeMaker]]): List[List[Test]] = {
- object approximator extends TreeMakersToConds(root)
- approximator.approximateMatch(cases)
+ // used for CSE -- rewrite all unknowns to False (the most conserative option)
+ object conservative extends TreeMakerToCond {
+ def handleUnknown(tm: TreeMaker) = FalseCond
+ }
+
+ final def approximateMatch(cases: List[List[TreeMaker]], treeMakerToCond: TreeMakerToCond = conservative) ={
+ val testss = cases.map { _ map (tm => Test(treeMakerToCond(tm), tm)) }
+ substitutionComputed = true // a second call to approximateMatch should not re-compute the substitution (would be wrong)
+ testss
+ }
}
+ def approximateMatchConservative(root: Symbol, cases: List[List[TreeMaker]]): List[List[Test]] =
+ (new TreeMakersToConds(root)).approximateMatch(cases)
+
def showTreeMakers(cases: List[List[TreeMaker]]) = {
- // patmatDebug ("treeMakers:")
- // patmatDebug (alignAcrossRows(cases, ">>"))
+ patmatDebug("treeMakers:")
+ patmatDebug(alignAcrossRows(cases, ">>"))
}
def showTests(testss: List[List[Test]]) = {
- // patmatDebug ("tests: ")
- // patmatDebug (alignAcrossRows(testss, "&"))
+ patmatDebug("tests: ")
+ patmatDebug(alignAcrossRows(testss, "&"))
}
}
@@ -1788,7 +1809,7 @@ trait PatternMatching extends Transform with TypingTransformers with ast.TreeDSL
override def hashCode = a.hashCode ^ b.hashCode
}
- // patmatDebug ("removeVarEq vars: "+ vars)
+ patmatDebug("removeVarEq vars: "+ vars)
vars.foreach { v =>
val excludedPair = new collection.mutable.HashSet[ExcludedPair]
@@ -1807,16 +1828,17 @@ trait PatternMatching extends Transform with TypingTransformers with ast.TreeDSL
}
val syms = v.equalitySyms
- // patmatDebug ("eqSyms "+(v, syms))
+ patmatDebug("eqSyms "+(v, syms))
syms foreach { sym =>
// if we've already excluded the pair at some point (-A \/ -B), then don't exclude the symmetric one (-B \/ -A)
// (nor the positive implications -B \/ A, or -A \/ B, which would entail the equality axioms falsifying the whole formula)
val todo = syms filterNot (b => (b.const == sym.const) || excludedPair(ExcludedPair(b.const, sym.const)))
val (excluded, notExcluded) = todo partition (b => sym.const.excludes(b.const))
val implied = notExcluded filter (b => sym.const.implies(b.const))
- // patmatDebug ("eq axioms for: "+ sym.const)
- // patmatDebug ("excluded: "+ excluded)
- // patmatDebug ("implied: "+ implied)
+
+ patmatDebug("eq axioms for: "+ sym.const)
+ patmatDebug("excluded: "+ excluded)
+ patmatDebug("implied: "+ implied)
// when this symbol is true, what must hold...
implied foreach (impliedSym => addAxiom(Or(Not(sym), impliedSym)))
@@ -1829,8 +1851,8 @@ trait PatternMatching extends Transform with TypingTransformers with ast.TreeDSL
}
}
- // patmatDebug ("eqAxioms:\n"+ cnfString(eqFreePropToSolvable(eqAxioms)))
- // patmatDebug ("pure:"+ pure.map(p => cnfString(eqFreePropToSolvable(p))).mkString("\n"))
+ patmatDebug("eqAxioms:\n"+ cnfString(eqFreePropToSolvable(eqAxioms)))
+ patmatDebug("pure:"+ pure.map(p => cnfString(eqFreePropToSolvable(p))).mkString("\n"))
Statistics.stopTimer(patmatAnaVarEq, start)
@@ -1972,12 +1994,12 @@ trait PatternMatching extends Transform with TypingTransformers with ast.TreeDSL
def findAllModels(f: Formula, models: List[Model], recursionDepthAllowed: Int = 10): List[Model]=
if (recursionDepthAllowed == 0) models
else {
- // patmatDebug ("find all models for\n"+ cnfString(f))
+ patmatDebug("find all models for\n"+ cnfString(f))
val model = findModelFor(f)
// if we found a solution, conjunct the formula with the model's negation and recurse
if (model ne NoModel) {
val unassigned = (vars -- model.keySet).toList
- // patmatDebug ("unassigned "+ unassigned +" in "+ model)
+ patmatDebug("unassigned "+ unassigned +" in "+ model)
def force(lit: Lit) = {
val model = withLit(findModelFor(dropUnit(f, lit)), lit)
if (model ne NoModel) List(model)
@@ -1986,7 +2008,7 @@ trait PatternMatching extends Transform with TypingTransformers with ast.TreeDSL
val forced = unassigned flatMap { s =>
force(Lit(s, true)) ++ force(Lit(s, false))
}
- // patmatDebug ("forced "+ forced)
+ patmatDebug("forced "+ forced)
val negated = negateModel(model)
findAllModels(f :+ negated, model :: (forced ++ models), recursionDepthAllowed - 1)
}
@@ -2009,7 +2031,7 @@ trait PatternMatching extends Transform with TypingTransformers with ast.TreeDSL
def findModelFor(f: Formula): Model = {
@inline def orElse(a: Model, b: => Model) = if (a ne NoModel) a else b
- // patmatDebug ("DPLL\n"+ cnfString(f))
+ patmatDebug("DPLL\n"+ cnfString(f))
val start = Statistics.startTimer(patmatAnaDPLL)
@@ -2153,11 +2175,11 @@ trait PatternMatching extends Transform with TypingTransformers with ast.TreeDSL
uniques.get(tp).getOrElse(
uniques.find {case (oldTp, oldC) => oldTp =:= tp} match {
case Some((_, c)) =>
- // patmatDebug ("unique const: "+ (tp, c))
+ patmatDebug("unique const: "+ (tp, c))
c
case _ =>
val fresh = mkFresh
- // patmatDebug ("uniqued const: "+ (tp, fresh))
+ patmatDebug("uniqued const: "+ (tp, fresh))
uniques(tp) = fresh
fresh
})
@@ -2173,12 +2195,12 @@ trait PatternMatching extends Transform with TypingTransformers with ast.TreeDSL
if (!t.symbol.isStable) t.tpe.narrow
else trees find (a => a.correspondsStructure(t)(sameValue)) match {
case Some(orig) =>
- // patmatDebug ("unique tp for tree: "+ (orig, orig.tpe))
+ patmatDebug("unique tp for tree: "+ (orig, orig.tpe))
orig.tpe
case _ =>
// duplicate, don't mutate old tree (TODO: use a map tree -> type instead?)
val treeWithNarrowedType = t.duplicate setType t.tpe.narrow
- // patmatDebug ("uniqued: "+ (t, t.tpe, treeWithNarrowedType.tpe))
+ patmatDebug("uniqued: "+ (t, t.tpe, treeWithNarrowedType.tpe))
trees += treeWithNarrowedType
treeWithNarrowedType.tpe
}
@@ -2349,11 +2371,15 @@ trait PatternMatching extends Transform with TypingTransformers with ast.TreeDSL
// use the same approximator so we share variables,
// but need different conditions depending on whether we're conservatively looking for failure or success
- val reachabilityApproximation = new TreeMakersToConds(prevBinder)
- val testCasesOk = reachabilityApproximation.approximateMatch(cases, reachabilityApproximation.constTrue)
- val testCasesFail = reachabilityApproximation.approximateMatchAgain(cases, reachabilityApproximation.constFalse)
+ // don't rewrite List-like patterns, as List() and Nil need to distinguished for unreachability
+ val approx = new TreeMakersToConds(prevBinder)
+ def approximate(default: Cond) = approx.approximateMatch(cases, approx.onUnknown { tm =>
+ approx.refutableRewrite.applyOrElse(tm, (_: TreeMaker) => default )
+ })
+
+ val testCasesOk = approximate(TrueCond)
+ val testCasesFail = approximate(FalseCond)
- reachabilityApproximation.discard()
prepareNewAnalysis()
val propsCasesOk = testCasesOk map (t => symbolicCase(t, modelNull = true))
@@ -2373,8 +2399,8 @@ trait PatternMatching extends Transform with TypingTransformers with ast.TreeDSL
var reachable = true
var caseIndex = 0
- // patmatDebug ("reachability, vars:\n"+ ((propsCasesFail flatMap gatherVariables) map (_.describe) mkString ("\n")))
- // patmatDebug ("equality axioms:\n"+ cnfString(eqAxiomsCNF))
+ patmatDebug("reachability, vars:\n"+ ((propsCasesFail flatMap gatherVariables) map (_.describe) mkString ("\n")))
+ patmatDebug("equality axioms:\n"+ cnfString(eqAxiomsCNF))
// invariant (prefixRest.length == current.length) && (prefix.reverse ++ prefixRest == symbolicCasesFail)
// termination: prefixRest.length decreases by 1
@@ -2421,7 +2447,7 @@ trait PatternMatching extends Transform with TypingTransformers with ast.TreeDSL
Some(List(tp))
// make sure it's not a primitive, else (5: Byte) match { case 5 => ... } sees no Byte
case sym if !sym.isSealed || isPrimitiveValueClass(sym) =>
- // patmatDebug ("enum unsealed "+ (tp, sym, sym.isSealed, isPrimitiveValueClass(sym)))
+ patmatDebug("enum unsealed "+ (tp, sym, sym.isSealed, isPrimitiveValueClass(sym)))
None
case sym =>
val subclasses = (
@@ -2429,7 +2455,7 @@ trait PatternMatching extends Transform with TypingTransformers with ast.TreeDSL
// symbols which are both sealed and abstract need not be covered themselves, because
// all of their children must be and they cannot otherwise be created.
filterNot (x => x.isSealed && x.isAbstractClass && !isPrimitiveValueClass(x)))
- // patmatDebug ("enum sealed -- subclasses: "+ (sym, subclasses))
+ patmatDebug("enum sealed -- subclasses: "+ (sym, subclasses))
val tpApprox = typer.infer.approximateAbstracts(tp)
val pre = tpApprox.prefix
@@ -2445,7 +2471,7 @@ trait PatternMatching extends Transform with TypingTransformers with ast.TreeDSL
if (subTpApprox <:< tpApprox) Some(checkableType(subTp))
else None
})
- // patmatDebug ("enum sealed "+ (tp, tpApprox) + " as "+ validSubTypes)
+ patmatDebug("enum sealed "+ (tp, tpApprox) + " as "+ validSubTypes)
Some(validSubTypes)
}
@@ -2465,7 +2491,7 @@ trait PatternMatching extends Transform with TypingTransformers with ast.TreeDSL
}
}
val res = toCheckable(tp)
- // patmatDebug ("checkable "+(tp, res))
+ patmatDebug("checkable "+(tp, res))
res
}
@@ -2490,19 +2516,19 @@ trait PatternMatching extends Transform with TypingTransformers with ast.TreeDSL
val start = Statistics.startTimer(patmatAnaExhaust)
var backoff = false
- val exhaustivityApproximation = new TreeMakersToConds(prevBinder)
- val tests = exhaustivityApproximation.approximateMatch(cases, {
- case BodyTreeMaker(_, _) => TrueCond // will be discarded by symbolCase later
- case tm =>
- // patmatDebug("backing off due to "+ tm)
+ val approx = new TreeMakersToConds(prevBinder)
+ val tests = approx.approximateMatch(cases, approx.onUnknown { tm =>
+ approx.fullRewrite.applyOrElse[TreeMaker, Cond](tm, {
+ case BodyTreeMaker(_, _) => TrueCond // irrelevant -- will be discarded by symbolCase later
+ case _ => // patmatDebug("backing off due to "+ tm)
backoff = true
FalseCond
- }, rewriteNil = true)
+ })
+ })
if (backoff) Nil else {
- val prevBinderTree = exhaustivityApproximation.binderToUniqueTree(prevBinder)
+ val prevBinderTree = approx.binderToUniqueTree(prevBinder)
- exhaustivityApproximation.discard()
prepareNewAnalysis()
val symbolicCases = tests map (symbolicCase(_, modelNull = false))
@@ -2523,7 +2549,7 @@ trait PatternMatching extends Transform with TypingTransformers with ast.TreeDSL
val vars = gatherVariables(matchFails)
// debug output:
- // patmatDebug ("analysing:")
+ patmatDebug("analysing:")
showTreeMakers(cases)
showTests(tests)
@@ -2543,7 +2569,7 @@ trait PatternMatching extends Transform with TypingTransformers with ast.TreeDSL
pruned
} catch {
case e : CNFBudgetExceeded =>
- // patmatDebug (util.Position.formatMessage(prevBinder.pos, "Cannot check match for exhaustivity", false))
+ patmatDebug(util.Position.formatMessage(prevBinder.pos, "Cannot check match for exhaustivity", false))
// e.printStackTrace()
Nil // CNF budget exceeded
}
@@ -2633,7 +2659,7 @@ trait PatternMatching extends Transform with TypingTransformers with ast.TreeDSL
// ...
val varAssignment = modelToVarAssignment(model)
- // patmatDebug ("var assignment for model "+ model +":\n"+ varAssignmentString(varAssignment))
+ patmatDebug("var assignment for model "+ model +":\n"+ varAssignmentString(varAssignment))
// chop a path into a list of symbols
def chop(path: Tree): List[Symbol] = path match {
@@ -2700,7 +2726,7 @@ trait PatternMatching extends Transform with TypingTransformers with ast.TreeDSL
def toCounterExample(beBrief: Boolean = false): CounterExample =
if (!allFieldAssignmentsLegal) NoExample
else {
- // patmatDebug ("describing "+ (variable, equalTo, notEqualTo, fields, cls, allFieldAssignmentsLegal))
+ patmatDebug("describing "+ (variable, equalTo, notEqualTo, fields, cls, allFieldAssignmentsLegal))
val res = prunedEqualTo match {
// a definite assignment to a value
case List(eq: ValueConst) if fields.isEmpty => ValueExample(eq)
@@ -2741,7 +2767,7 @@ trait PatternMatching extends Transform with TypingTransformers with ast.TreeDSL
// TODO: improve reasoning -- in the mean time, a false negative is better than an annoying false positive
case _ => NoExample
}
- // patmatDebug ("described as: "+ res)
+ patmatDebug("described as: "+ res)
res
}
@@ -2766,7 +2792,10 @@ trait PatternMatching extends Transform with TypingTransformers with ast.TreeDSL
* we generalize sharing to implication, where b reuses a if a => b and priors(a) => priors(b) (the priors of a sub expression form the path through the decision tree)
*/
def doCSE(prevBinder: Symbol, cases: List[List[TreeMaker]], pt: Type): List[List[TreeMaker]] = {
- val testss = approximateMatch(prevBinder, cases)
+ patmatDebug("before CSE:")
+ showTreeMakers(cases)
+
+ val testss = approximateMatchConservative(prevBinder, cases)
// interpret:
val dependencies = new collection.mutable.LinkedHashMap[Test, Set[Cond]]
@@ -2776,10 +2805,10 @@ trait PatternMatching extends Transform with TypingTransformers with ast.TreeDSL
val cond = test.cond
def simplify(c: Cond): Set[Cond] = c match {
- case AndCond(a, b) => simplify(a) ++ simplify(b)
+ case AndCond(a, b) => simplify(a) ++ simplify(b)
case OrCond(_, _) => Set(FalseCond) // TODO: make more precise
case NonNullCond(_) => Set(TrueCond) // not worth remembering
- case _ => Set(c)
+ case _ => Set(c)
}
val conds = simplify(cond)
@@ -2794,7 +2823,7 @@ trait PatternMatching extends Transform with TypingTransformers with ast.TreeDSL
case (priorTest, deps) =>
((simplify(priorTest.cond) == nonTrivial) || // our conditions are implied by priorTest if it checks the same thing directly
(nonTrivial subsetOf deps) // or if it depends on a superset of our conditions
- ) && (deps subsetOf tested) // the conditions we've tested when we are here in the match satisfy the prior test, and hence what it tested
+ ) && (deps subsetOf tested) // the conditions we've tested when we are here in the match satisfy the prior test, and hence what it tested
} foreach {
case (priorTest, _) =>
// if so, note the dependency in both tests
@@ -2812,7 +2841,7 @@ trait PatternMatching extends Transform with TypingTransformers with ast.TreeDSL
tested.clear()
tests dropWhile storeDependencies
}
- // patmatDebug ("dependencies: "+ dependencies)
+ patmatDebug("dependencies: "+ dependencies)
// find longest prefix of tests that reuse a prior test, and whose dependent conditions monotonically increase
// then, collapse these contiguous sequences of reusing tests
@@ -2846,7 +2875,8 @@ trait PatternMatching extends Transform with TypingTransformers with ast.TreeDSL
case _ =>
}
- // patmatDebug("sharedPrefix: "+ sharedPrefix)
+ patmatDebug("sharedPrefix: "+ sharedPrefix)
+ patmatDebug("suffix: "+ sharedPrefix)
// if the shared prefix contains interesting conditions (!= TrueCond)
// and the last of such interesting shared conditions reuses another treemaker's test
// replace the whole sharedPrefix by a ReusingCondTreeMaker
@@ -2862,7 +2892,7 @@ trait PatternMatching extends Transform with TypingTransformers with ast.TreeDSL
// replace original treemakers that are reused (as determined when computing collapsed),
// by ReusedCondTreeMakers
val reusedMakers = collapsed mapConserve (_ mapConserve reusedOrOrig)
- // patmatDebug ("after CSE:")
+ patmatDebug("after CSE:")
showTreeMakers(reusedMakers)
reusedMakers
}
diff --git a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala
index 7318538de7..3518316fbb 100644
--- a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala
@@ -119,7 +119,7 @@ abstract class RefChecks extends InfoTransform with reflect.internal.transform.R
// those with the DEFAULTPARAM flag, and infer the methods. Looking for the methods
// directly requires inspecting the parameter list of every one. That modification
// shaved 95% off the time spent in this method.
- val defaultGetters = clazz.info.findMember(nme.ANYNAME, 0L, DEFAULTPARAM, false).alternatives
+ val defaultGetters = clazz.info.findMembers(0L, DEFAULTPARAM)
val defaultMethodNames = defaultGetters map (sym => nme.defaultGetterToMethod(sym.name))
defaultMethodNames.distinct foreach { name =>
diff --git a/src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala b/src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala
index f67cec730b..b544407286 100644
--- a/src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala
@@ -19,6 +19,10 @@ import symtab.Flags._
* of class-members which are private up to an enclosing non-package
* class, in order to avoid overriding conflicts.
*
+ * This phase also sets SPECIALIZED flag on type parameters with
+ * `@specialized` annotation. We put this logic here because the
+ * flag must be set before pickling.
+ *
* @author Martin Odersky
* @version 1.0
*/
@@ -208,6 +212,15 @@ abstract class SuperAccessors extends transform.Transform with transform.TypingT
case TypeApply(sel @ Select(This(_), name), args) =>
mayNeedProtectedAccessor(sel, args, false)
+ // set a flag for all type parameters with `@specialized` annotation so it can be pickled
+ case typeDef: TypeDef if typeDef.symbol.deSkolemize.hasAnnotation(definitions.SpecializedClass) =>
+ debuglog("setting SPECIALIZED flag on typeDef.symbol.deSkolemize where typeDef = " + typeDef)
+ // we need to deSkolemize symbol so we get the same symbol as others would get when
+ // inspecting type parameter from "outside"; see the discussion of skolems here:
+ // https://groups.google.com/d/topic/scala-internals/0j8laVNTQsI/discussion
+ typeDef.symbol.deSkolemize.setFlag(SPECIALIZED)
+ typeDef
+
case sel @ Select(qual @ This(_), name) =>
// warn if they are selecting a private[this] member which
// also exists in a superclass, because they may be surprised
diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
index a570cd74d6..9371af4848 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
@@ -4509,6 +4509,8 @@ trait Typers extends Modes with Adaptations with Tags {
assert(errorContainer == null, "Cannot set ambiguous error twice for identifier")
errorContainer = tree
}
+
+ val fingerPrint: Long = name.fingerPrint
var defSym: Symbol = tree.symbol // the directly found symbol
var pre: Type = NoPrefix // the prefix type of defSym, if a class member
@@ -4547,7 +4549,10 @@ trait Typers extends Modes with Adaptations with Tags {
var cx = startingIdentContext
while (defSym == NoSymbol && cx != NoContext && (cx.scope ne null)) { // cx.scope eq null arises during FixInvalidSyms in Duplicators
pre = cx.enclClass.prefix
- defEntry = cx.scope.lookupEntry(name)
+ defEntry = {
+ val scope = cx.scope
+ if ((fingerPrint & scope.fingerPrints) != 0) scope.lookupEntry(name) else null
+ }
if ((defEntry ne null) && qualifies(defEntry.sym)) {
// Right here is where SI-1987, overloading in package objects, can be
// seen to go wrong. There is an overloaded symbol, but when referring
diff --git a/src/compiler/scala/tools/reflect/FastTrack.scala b/src/compiler/scala/tools/reflect/FastTrack.scala
index 8ea66979bc..63ecfa32b2 100644
--- a/src/compiler/scala/tools/reflect/FastTrack.scala
+++ b/src/compiler/scala/tools/reflect/FastTrack.scala
@@ -43,7 +43,7 @@ trait FastTrack {
ApiUniverseReify bindTo { case (c, Apply(TypeApply(_, List(tt)), List(expr))) => c.materializeExpr(c.prefix.tree, EmptyTree, expr) }
MacroContextReify bindTo { case (c, Apply(TypeApply(_, List(tt)), List(expr))) => c.materializeExprForMacroContext(c.prefix.tree, expr) }
ReflectRuntimeCurrentMirror bindTo { case (c, _) => scala.reflect.runtime.Macros.currentMirror(c).tree }
- StringContext_f bindTo { case (c, Apply(Select(Apply(_, parts), _), args)) => c.macro_StringInterpolation_f(parts, args) }
+ StringContext_f bindTo { case (c, app@Apply(Select(Apply(_, parts), _), args)) => c.macro_StringInterpolation_f(parts, args, app.pos) }
registry
}
} \ No newline at end of file
diff --git a/src/compiler/scala/tools/reflect/MacroImplementations.scala b/src/compiler/scala/tools/reflect/MacroImplementations.scala
index a5f7928f55..604bd7cd1a 100644
--- a/src/compiler/scala/tools/reflect/MacroImplementations.scala
+++ b/src/compiler/scala/tools/reflect/MacroImplementations.scala
@@ -8,9 +8,9 @@ import scala.collection.mutable.Stack
abstract class MacroImplementations {
val c: Context
- import c.universe._
+ import c.universe.{Position => SPosition, _}
- def macro_StringInterpolation_f(parts: List[Tree], args: List[Tree]): Tree = {
+ def macro_StringInterpolation_f(parts: List[Tree], args: List[Tree], origApplyPos: SPosition): Tree = {
// the parts all have the same position information (as the expression is generated by the compiler)
// the args have correct position information
@@ -25,7 +25,6 @@ abstract class MacroImplementations {
c.abort(args(parts.length-1).pos,
"too many arguments for interpolated string")
}
-
val stringParts = parts map {
case Literal(Constant(s: String)) => s;
case _ => throw new IllegalArgumentException("argument parts must be a list of string literals")
@@ -39,7 +38,7 @@ abstract class MacroImplementations {
def defval(value: Tree, tpe: Type): Unit = {
val freshName = newTermName(c.fresh("arg$"))
- evals += ValDef(Modifiers(), freshName, TypeTree(tpe), value)
+ evals += ValDef(Modifiers(), freshName, TypeTree(tpe) setPos value.pos.focus, value) setPos value.pos
ids += Ident(freshName)
}
@@ -141,7 +140,7 @@ abstract class MacroImplementations {
List(ids: _* )
);
- Block(evals.toList, expr)
+ Block(evals.toList, atPos(origApplyPos.focus)(expr)) setPos origApplyPos.makeTransparent
}
} \ No newline at end of file
diff --git a/src/eclipse/partest/.classpath b/src/eclipse/partest/.classpath
new file mode 100644
index 0000000000..b14e465aa6
--- /dev/null
+++ b/src/eclipse/partest/.classpath
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+ <classpathentry kind="src" path="partest"/>
+ <classpathentry combineaccessrules="false" kind="src" path="/reflect"/>
+ <classpathentry combineaccessrules="false" kind="src" path="/scala-library"/>
+ <classpathentry combineaccessrules="false" kind="src" path="/scala-compiler"/>
+ <classpathentry combineaccessrules="false" kind="src" path="/scalap"/>
+ <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
+ <classpathentry kind="lib" path="lib/ant/ant.jar"/>
+ <classpathentry kind="lib" path="lib/jline.jar"/>
+ <classpathentry kind="lib" path="lib/msil.jar"/>
+ <classpathentry combineaccessrules="false" kind="src" path="/asm"/>
+ <classpathentry kind="output" path="build-quick-partest"/>
+</classpath>
diff --git a/src/eclipse/partest/.project b/src/eclipse/partest/.project
new file mode 100644
index 0000000000..45c24332ba
--- /dev/null
+++ b/src/eclipse/partest/.project
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>partest</name>
+ <comment></comment>
+ <projects>
+ </projects>
+ <buildSpec>
+ <buildCommand>
+ <name>org.scala-ide.sdt.core.scalabuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ </buildSpec>
+ <natures>
+ <nature>org.scala-ide.sdt.core.scalanature</nature>
+ <nature>org.eclipse.jdt.core.javanature</nature>
+ </natures>
+ <linkedResources>
+ <link>
+ <name>build-quick-partest</name>
+ <type>2</type>
+ <locationURI>SCALA_BASEDIR/build/quick/classes/partest</locationURI>
+ </link>
+ <link>
+ <name>lib</name>
+ <type>2</type>
+ <locationURI>SCALA_BASEDIR/lib</locationURI>
+ </link>
+ <link>
+ <name>partest</name>
+ <type>2</type>
+ <locationURI>SCALA_BASEDIR/src/partest</locationURI>
+ </link>
+ </linkedResources>
+</projectDescription>
diff --git a/src/eclipse/reflect/.classpath b/src/eclipse/reflect/.classpath
index 3fb1d08d4d..57a3928dc3 100644
--- a/src/eclipse/reflect/.classpath
+++ b/src/eclipse/reflect/.classpath
@@ -2,7 +2,6 @@
<classpath>
<classpathentry kind="src" path="reflect"/>
<classpathentry combineaccessrules="false" kind="src" path="/scala-library"/>
- <classpathentry kind="con" path="org.scala-ide.sdt.launching.SCALA_CONTAINER"/>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6"/>
<classpathentry kind="output" path="build-quick-reflect"/>
</classpath>
diff --git a/src/eclipse/scala-compiler/.classpath b/src/eclipse/scala-compiler/.classpath
index e0264b9856..40a4ed9996 100644
--- a/src/eclipse/scala-compiler/.classpath
+++ b/src/eclipse/scala-compiler/.classpath
@@ -5,7 +5,6 @@
<classpathentry combineaccessrules="false" kind="src" path="/scala-library"/>
<classpathentry combineaccessrules="false" kind="src" path="/fjbg"/>
<classpathentry combineaccessrules="false" kind="src" path="/asm"/>
- <classpathentry kind="con" path="org.scala-ide.sdt.launching.SCALA_CONTAINER"/>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
<classpathentry kind="lib" path="lib/ant/ant.jar"/>
<classpathentry kind="lib" path="lib/jline.jar"/>
diff --git a/src/eclipse/scalap/.classpath b/src/eclipse/scalap/.classpath
new file mode 100644
index 0000000000..2b44ad19b2
--- /dev/null
+++ b/src/eclipse/scalap/.classpath
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+ <classpathentry kind="src" path="scalap"/>
+ <classpathentry combineaccessrules="false" kind="src" path="/reflect"/>
+ <classpathentry combineaccessrules="false" kind="src" path="/scala-library"/>
+ <classpathentry combineaccessrules="false" kind="src" path="/scala-compiler"/>
+ <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
+ <classpathentry kind="lib" path="lib/ant/ant.jar"/>
+ <classpathentry kind="lib" path="lib/jline.jar"/>
+ <classpathentry kind="lib" path="lib/msil.jar"/>
+ <classpathentry kind="output" path="build-quick-scalap"/>
+</classpath>
diff --git a/src/eclipse/scalap/.project b/src/eclipse/scalap/.project
new file mode 100644
index 0000000000..3599168e32
--- /dev/null
+++ b/src/eclipse/scalap/.project
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>scalap</name>
+ <comment></comment>
+ <projects>
+ </projects>
+ <buildSpec>
+ <buildCommand>
+ <name>org.scala-ide.sdt.core.scalabuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ </buildSpec>
+ <natures>
+ <nature>org.scala-ide.sdt.core.scalanature</nature>
+ <nature>org.eclipse.jdt.core.javanature</nature>
+ </natures>
+ <linkedResources>
+ <link>
+ <name>build-quick-scalap</name>
+ <type>2</type>
+ <locationURI>SCALA_BASEDIR/build/quick/classes/scalap</locationURI>
+ </link>
+ <link>
+ <name>lib</name>
+ <type>2</type>
+ <locationURI>SCALA_BASEDIR/lib</locationURI>
+ </link>
+ <link>
+ <name>scalap</name>
+ <type>2</type>
+ <locationURI>SCALA_BASEDIR/src/scalap</locationURI>
+ </link>
+ </linkedResources>
+</projectDescription>
diff --git a/src/library/scala/Double.scala b/src/library/scala/Double.scala
index 2ff46c433d..510de92a2a 100644
--- a/src/library/scala/Double.scala
+++ b/src/library/scala/Double.scala
@@ -370,9 +370,6 @@ object Double extends AnyValCompanion {
final val PositiveInfinity = java.lang.Double.POSITIVE_INFINITY
final val NegativeInfinity = java.lang.Double.NEGATIVE_INFINITY
- @deprecated("use Double.MinPositiveValue instead", "2.9.0")
- final val Epsilon = MinPositiveValue
-
/** The negative number with the greatest (finite) absolute value which is representable
* by a Double. Note that it differs from [[java.lang.Double.MIN_VALUE]], which
* is the smallest positive value representable by a Double. In Scala that number
diff --git a/src/library/scala/Enumeration.scala b/src/library/scala/Enumeration.scala
index 2b658ee4f7..1151b04ca0 100644
--- a/src/library/scala/Enumeration.scala
+++ b/src/library/scala/Enumeration.scala
@@ -194,7 +194,10 @@ abstract class Enumeration (initial: Int) extends Serializable {
/** a marker so we can tell whose values belong to whom come reflective-naming time */
private[Enumeration] val outerEnum = thisenum
- override def compare(that: Value): Int = this.id - that.id
+ override def compare(that: Value): Int =
+ if (this.id < that.id) -1
+ else if (this.id == that.id) 0
+ else 1
override def equals(other: Any) = other match {
case that: Enumeration#Value => (outerEnum eq that.outerEnum) && (id == that.id)
case _ => false
@@ -236,7 +239,7 @@ abstract class Enumeration (initial: Int) extends Serializable {
/** An ordering by id for values of this set */
object ValueOrdering extends Ordering[Value] {
- def compare(x: Value, y: Value): Int = x.id - y.id
+ def compare(x: Value, y: Value): Int = x compare y
}
/** A class for sets of values.
diff --git a/src/library/scala/Float.scala b/src/library/scala/Float.scala
index bd7a07fece..b9c116da0b 100644
--- a/src/library/scala/Float.scala
+++ b/src/library/scala/Float.scala
@@ -370,9 +370,6 @@ object Float extends AnyValCompanion {
final val PositiveInfinity = java.lang.Float.POSITIVE_INFINITY
final val NegativeInfinity = java.lang.Float.NEGATIVE_INFINITY
- @deprecated("use Float.MinPositiveValue instead", "2.9.0")
- final val Epsilon = MinPositiveValue
-
/** The negative number with the greatest (finite) absolute value which is representable
* by a Float. Note that it differs from [[java.lang.Float.MIN_VALUE]], which
* is the smallest positive value representable by a Float. In Scala that number
diff --git a/src/library/scala/collection/immutable/Vector.scala b/src/library/scala/collection/immutable/Vector.scala
index d100bf93df..4dfe147a65 100644
--- a/src/library/scala/collection/immutable/Vector.scala
+++ b/src/library/scala/collection/immutable/Vector.scala
@@ -18,8 +18,14 @@ import scala.collection.parallel.immutable.ParVector
/** Companion object to the Vector class
*/
object Vector extends SeqFactory[Vector] {
+ private[collection] class VectorReusableCBF extends GenericCanBuildFrom[Nothing] {
+ override def apply() = newBuilder[Nothing]
+ }
+
+ private val VectorReusableCBF: GenericCanBuildFrom[Nothing] = new VectorReusableCBF
+
@inline implicit def canBuildFrom[A]: CanBuildFrom[Coll, A, Vector[A]] =
- ReusableCBF.asInstanceOf[CanBuildFrom[Coll, A, Vector[A]]]
+ VectorReusableCBF.asInstanceOf[CanBuildFrom[Coll, A, Vector[A]]]
def newBuilder[A]: Builder[A, Vector[A]] = new VectorBuilder[A]
private[immutable] val NIL = new Vector[Nothing](0, 0, 0)
@inline override def empty[A]: Vector[A] = NIL
@@ -140,19 +146,19 @@ override def companion: GenericCompanion[Vector] = Vector
// SeqLike api
- @inline override def updated[B >: A, That](index: Int, elem: B)(implicit bf: CanBuildFrom[Vector[A], B, That]): That = {
- // just ignore bf
- updateAt(index, elem).asInstanceOf[That]
+ @inline override def updated[B >: A, That](index: Int, elem: B)(implicit bf: CanBuildFrom[Vector[A], B, That]): That = bf match {
+ case _: Vector.VectorReusableCBF => updateAt(index, elem).asInstanceOf[That] // just ignore bf
+ case _ => super.updated(index, elem)(bf)
}
- @inline override def +:[B >: A, That](elem: B)(implicit bf: CanBuildFrom[Vector[A], B, That]): That = {
- // just ignore bf
- appendFront(elem).asInstanceOf[That]
+ @inline override def +:[B >: A, That](elem: B)(implicit bf: CanBuildFrom[Vector[A], B, That]): That = bf match {
+ case _: Vector.VectorReusableCBF => appendFront(elem).asInstanceOf[That] // just ignore bf
+ case _ => super.+:(elem)(bf)
}
- @inline override def :+[B >: A, That](elem: B)(implicit bf: CanBuildFrom[Vector[A], B, That]): That = {
- // just ignore bf
- appendBack(elem).asInstanceOf[That]
+ @inline override def :+[B >: A, That](elem: B)(implicit bf: CanBuildFrom[Vector[A], B, That]): That = bf match {
+ case _: Vector.VectorReusableCBF => appendBack(elem).asInstanceOf[That] // just ignore bf
+ case _ => super.:+(elem)(bf)
}
override def take(n: Int): Vector[A] = {
diff --git a/src/library/scala/concurrent/ExecutionContext.scala b/src/library/scala/concurrent/ExecutionContext.scala
index debfc226db..8081bb32da 100644
--- a/src/library/scala/concurrent/ExecutionContext.scala
+++ b/src/library/scala/concurrent/ExecutionContext.scala
@@ -77,7 +77,7 @@ object ExecutionContext {
/** The default reporter simply prints the stack trace of the `Throwable` to System.err.
*/
- def defaultReporter: Throwable => Unit = { case t => t.printStackTrace() }
+ def defaultReporter: Throwable => Unit = (t: Throwable) => t.printStackTrace()
}
diff --git a/src/library/scala/concurrent/Future.scala b/src/library/scala/concurrent/Future.scala
index e556be4fe3..f82b79cb18 100644
--- a/src/library/scala/concurrent/Future.scala
+++ b/src/library/scala/concurrent/Future.scala
@@ -14,7 +14,6 @@ import java.util.concurrent.{ ConcurrentLinkedQueue, TimeUnit, Callable }
import java.util.concurrent.TimeUnit.{ NANOSECONDS => NANOS, MILLISECONDS ⇒ MILLIS }
import java.lang.{ Iterable => JIterable }
import java.util.{ LinkedList => JLinkedList }
-import java.{ lang => jl }
import java.util.concurrent.atomic.{ AtomicReferenceFieldUpdater, AtomicInteger, AtomicBoolean }
import scala.concurrent.util.Duration
@@ -565,17 +564,15 @@ trait Future[+T] extends Awaitable[T] {
*/
object Future {
- import java.{ lang => jl }
-
private[concurrent] val toBoxed = Map[Class[_], Class[_]](
- classOf[Boolean] -> classOf[jl.Boolean],
- classOf[Byte] -> classOf[jl.Byte],
- classOf[Char] -> classOf[jl.Character],
- classOf[Short] -> classOf[jl.Short],
- classOf[Int] -> classOf[jl.Integer],
- classOf[Long] -> classOf[jl.Long],
- classOf[Float] -> classOf[jl.Float],
- classOf[Double] -> classOf[jl.Double],
+ classOf[Boolean] -> classOf[java.lang.Boolean],
+ classOf[Byte] -> classOf[java.lang.Byte],
+ classOf[Char] -> classOf[java.lang.Character],
+ classOf[Short] -> classOf[java.lang.Short],
+ classOf[Int] -> classOf[java.lang.Integer],
+ classOf[Long] -> classOf[java.lang.Long],
+ classOf[Float] -> classOf[java.lang.Float],
+ classOf[Double] -> classOf[java.lang.Double],
classOf[Unit] -> classOf[scala.runtime.BoxedUnit]
)
@@ -604,9 +601,6 @@ object Future {
*/
def apply[T](body: =>T)(implicit execctx: ExecutionContext): Future[T] = impl.Future(body)
- import scala.collection.mutable.Builder
- import scala.collection.generic.CanBuildFrom
-
/** Simple version of `Futures.traverse`. Transforms a `TraversableOnce[Future[A]]` into a `Future[TraversableOnce[A]]`.
* Useful for reducing many `Future`s into a single `Future`.
*/
diff --git a/src/library/scala/concurrent/FutureTaskRunner.scala b/src/library/scala/concurrent/FutureTaskRunner.scala
index 9d6f8a7a88..d7f1e1c2f9 100644
--- a/src/library/scala/concurrent/FutureTaskRunner.scala
+++ b/src/library/scala/concurrent/FutureTaskRunner.scala
@@ -15,7 +15,7 @@ import language.{implicitConversions, higherKinds}
*
* @author Philipp Haller
*/
-@deprecated("Use `ExecutionContext`s instead.", "2.10.0")
+@deprecated("Use `ExecutionContext` instead.", "2.10.0")
trait FutureTaskRunner extends TaskRunner {
/** The type of the futures that the underlying task runner supports.
@@ -33,6 +33,7 @@ trait FutureTaskRunner extends TaskRunner {
/* Possibly blocks the current thread, for example, waiting for
* a lock or condition.
*/
+ @deprecated("Use `blocking` instead.", "2.10.0")
def managedBlock(blocker: ManagedBlocker): Unit
}
diff --git a/src/library/scala/concurrent/ManagedBlocker.scala b/src/library/scala/concurrent/ManagedBlocker.scala
index 9c6f4d51d6..47bbb91f6f 100644
--- a/src/library/scala/concurrent/ManagedBlocker.scala
+++ b/src/library/scala/concurrent/ManagedBlocker.scala
@@ -12,6 +12,7 @@ package scala.concurrent
*
* @author Philipp Haller
*/
+@deprecated("Use `blocking` instead.", "2.10.0")
trait ManagedBlocker {
/**
diff --git a/src/library/scala/concurrent/Scheduler.scala b/src/library/scala/concurrent/Scheduler.scala
deleted file mode 100644
index 6645abcc4e..0000000000
--- a/src/library/scala/concurrent/Scheduler.scala
+++ /dev/null
@@ -1,54 +0,0 @@
-/* __ *\
-** ________ ___ / / ___ Scala API **
-** / __/ __// _ | / / / _ | (c) 2003-2011, LAMP/EPFL **
-** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ **
-** /____/\___/_/ |_/____/_/ | | **
-** |/ **
-\* */
-
-package scala.concurrent
-
-import scala.concurrent.util.Duration
-
-/** A service for scheduling tasks and thunks for one-time, or periodic execution.
- */
-trait Scheduler {
-
- /** Schedules a thunk for repeated execution with an initial delay and a frequency.
- *
- * @param delay the initial delay after which the thunk should be executed
- * the first time
- * @param frequency the frequency with which the thunk should be executed,
- * as a time period between subsequent executions
- */
- def schedule(delay: Duration, frequency: Duration)(thunk: => Unit): Cancellable
-
- /** Schedules a task for execution after a given delay.
- *
- * @param delay the duration after which the task should be executed
- * @param task the task that is scheduled for execution
- * @return a `Cancellable` that may be used to cancel the execution
- * of the task
- */
- def scheduleOnce(delay: Duration, task: Runnable): Cancellable
-
- /** Schedules a thunk for execution after a given delay.
- *
- * @param delay the duration after which the thunk should be executed
- * @param task the thunk that is scheduled for execution
- * @return a `Cancellable` that may be used to cancel the execution
- * of the thunk
- */
- def scheduleOnce(delay: Duration)(task: => Unit): Cancellable
-
-}
-
-
-
-trait Cancellable {
-
- /** Cancels the underlying task.
- */
- def cancel(): Unit
-
-}
diff --git a/src/library/scala/concurrent/Task.scala b/src/library/scala/concurrent/Task.scala
deleted file mode 100644
index eb3efbb422..0000000000
--- a/src/library/scala/concurrent/Task.scala
+++ /dev/null
@@ -1,13 +0,0 @@
-package scala.concurrent
-
-
-
-trait Task[+T] {
-
- def start(): Unit
-
- def future: Future[T]
-
-}
-
-
diff --git a/src/library/scala/concurrent/TaskRunner.scala b/src/library/scala/concurrent/TaskRunner.scala
index 3180e9ce8a..2e11ac42b0 100644
--- a/src/library/scala/concurrent/TaskRunner.scala
+++ b/src/library/scala/concurrent/TaskRunner.scala
@@ -14,7 +14,7 @@ import language.{higherKinds, implicitConversions}
*
* @author Philipp Haller
*/
-@deprecated("Use `ExecutionContext`s instead.", "2.10.0")
+@deprecated("Use `ExecutionContext` instead.", "2.10.0")
trait TaskRunner {
type Task[T]
diff --git a/src/library/scala/concurrent/TaskRunners.scala b/src/library/scala/concurrent/TaskRunners.scala
index 7994255b25..8f7d952ed8 100644
--- a/src/library/scala/concurrent/TaskRunners.scala
+++ b/src/library/scala/concurrent/TaskRunners.scala
@@ -14,7 +14,7 @@ import java.util.concurrent.{ThreadPoolExecutor, LinkedBlockingQueue, TimeUnit}
*
* @author Philipp Haller
*/
-@deprecated("Use `ExecutionContext`s instead.", "2.10.0")
+@deprecated("Use `ExecutionContext` instead.", "2.10.0")
object TaskRunners {
implicit val threadRunner: FutureTaskRunner =
diff --git a/src/library/scala/concurrent/ThreadPoolRunner.scala b/src/library/scala/concurrent/ThreadPoolRunner.scala
index fd6882348a..594555d49b 100644
--- a/src/library/scala/concurrent/ThreadPoolRunner.scala
+++ b/src/library/scala/concurrent/ThreadPoolRunner.scala
@@ -16,7 +16,7 @@ import language.implicitConversions
*
* @author Philipp Haller
*/
-@deprecated("Use `ExecutionContext`s instead.", "2.10.0")
+@deprecated("Use `ExecutionContext` instead.", "2.10.0")
trait ThreadPoolRunner extends FutureTaskRunner {
type Task[T] = Callable[T] with Runnable
@@ -43,6 +43,7 @@ trait ThreadPoolRunner extends FutureTaskRunner {
executor execute task
}
+ @deprecated("Use `blocking` instead.", "2.10.0")
def managedBlock(blocker: ManagedBlocker) {
blocker.block()
}
diff --git a/src/library/scala/concurrent/ThreadRunner.scala b/src/library/scala/concurrent/ThreadRunner.scala
index 76be94aa6b..ab709e0210 100644
--- a/src/library/scala/concurrent/ThreadRunner.scala
+++ b/src/library/scala/concurrent/ThreadRunner.scala
@@ -15,6 +15,7 @@ import language.implicitConversions
*
* @author Philipp Haller
*/
+@deprecated("Use `ExecutionContext` instead.", "2.10.0")
class ThreadRunner extends FutureTaskRunner {
type Task[T] = () => T
@@ -47,6 +48,7 @@ class ThreadRunner extends FutureTaskRunner {
() => result.get.fold[S](throw _, identity _)
}
+ @deprecated("Use `blocking` instead.", "2.10.0")
def managedBlock(blocker: ManagedBlocker) {
blocker.block()
}
diff --git a/src/library/scala/concurrent/impl/Future.scala b/src/library/scala/concurrent/impl/Future.scala
index 0c031743db..132e1d79e7 100644
--- a/src/library/scala/concurrent/impl/Future.scala
+++ b/src/library/scala/concurrent/impl/Future.scala
@@ -21,19 +21,6 @@ private[concurrent] trait Future[+T] extends scala.concurrent.Future[T] with Awa
}
private[concurrent] object Future {
- import java.{ lang => jl }
-
- private val toBoxed = Map[Class[_], Class[_]](
- classOf[Boolean] -> classOf[jl.Boolean],
- classOf[Byte] -> classOf[jl.Byte],
- classOf[Char] -> classOf[jl.Character],
- classOf[Short] -> classOf[jl.Short],
- classOf[Int] -> classOf[jl.Integer],
- classOf[Long] -> classOf[jl.Long],
- classOf[Float] -> classOf[jl.Float],
- classOf[Double] -> classOf[jl.Double],
- classOf[Unit] -> classOf[scala.runtime.BoxedUnit]
- )
/** Wraps a block of code into an awaitable object. */
private[concurrent] def body2awaitable[T](body: =>T) = new Awaitable[T] {
@@ -44,7 +31,7 @@ private[concurrent] object Future {
def result(atMost: Duration)(implicit permit: CanAwait) = body
}
- def boxedType(c: Class[_]): Class[_] = if (c.isPrimitive) toBoxed(c) else c
+ def boxedType(c: Class[_]): Class[_] = if (c.isPrimitive) scala.concurrent.Future.toBoxed(c) else c
private[impl] class PromiseCompletingRunnable[T](body: => T)
extends Runnable {
diff --git a/src/library/scala/concurrent/impl/Promise.scala b/src/library/scala/concurrent/impl/Promise.scala
index ccfcd30c97..84638586cf 100644
--- a/src/library/scala/concurrent/impl/Promise.scala
+++ b/src/library/scala/concurrent/impl/Promise.scala
@@ -10,14 +10,11 @@ package scala.concurrent.impl
-import java.util.concurrent.TimeUnit.{ NANOSECONDS, MILLISECONDS }
-import scala.concurrent.{ Awaitable, ExecutionContext, blocking, CanAwait, OnCompleteRunnable, TimeoutException, ExecutionException }
-//import scala.util.continuations._
+import java.util.concurrent.TimeUnit.NANOSECONDS
+import scala.concurrent.{ ExecutionContext, CanAwait, OnCompleteRunnable, TimeoutException, ExecutionException }
import scala.concurrent.util.Duration
-import scala.util
import scala.annotation.tailrec
import scala.util.control.NonFatal
-//import scala.concurrent.NonDeterministic
@@ -41,7 +38,7 @@ private class CallbackRunnable[T](val executor: ExecutionContext, val onComplete
}
}
-object Promise {
+private[concurrent] object Promise {
private def resolveEither[T](source: Either[Throwable, T]): Either[Throwable, T] = source match {
case Left(t) => resolver(t)
diff --git a/src/library/scala/concurrent/ops.scala b/src/library/scala/concurrent/ops.scala
index 2cea29aefe..4de8f6cba3 100644
--- a/src/library/scala/concurrent/ops.scala
+++ b/src/library/scala/concurrent/ops.scala
@@ -15,7 +15,7 @@ import scala.util.control.Exception.allCatch
*
* @author Martin Odersky, Stepan Koltsov, Philipp Haller
*/
-@deprecated("Use `future` instead.", "2.10.0")
+@deprecated("Use `Future` instead.", "2.10.0")
object ops
{
val defaultRunner: FutureTaskRunner = TaskRunners.threadRunner
diff --git a/src/library/scala/reflect/ClassManifest.scala b/src/library/scala/reflect/ClassManifest.scala
index f143bf8712..d226e43e77 100644
--- a/src/library/scala/reflect/ClassManifest.scala
+++ b/src/library/scala/reflect/ClassManifest.scala
@@ -184,18 +184,18 @@ object ClassManifestFactory {
* pass varargs as arrays into this, we get an infinitely recursive call
* to boxArray. (Besides, having a separate case is more efficient)
*/
- def classType[T <: AnyRef](clazz: jClass[_]): ClassManifest[T] =
+ def classType[T](clazz: jClass[_]): ClassManifest[T] =
new ClassTypeManifest[T](None, clazz, Nil)
/** ClassManifest for the class type `clazz[args]`, where `clazz` is
* a top-level or static class and `args` are its type arguments */
- def classType[T <: AnyRef](clazz: jClass[_], arg1: OptManifest[_], args: OptManifest[_]*): ClassManifest[T] =
+ def classType[T](clazz: jClass[_], arg1: OptManifest[_], args: OptManifest[_]*): ClassManifest[T] =
new ClassTypeManifest[T](None, clazz, arg1 :: args.toList)
/** ClassManifest for the class type `clazz[args]`, where `clazz` is
* a class with non-package prefix type `prefix` and type arguments `args`.
*/
- def classType[T <: AnyRef](prefix: OptManifest[_], clazz: jClass[_], args: OptManifest[_]*): ClassManifest[T] =
+ def classType[T](prefix: OptManifest[_], clazz: jClass[_], args: OptManifest[_]*): ClassManifest[T] =
new ClassTypeManifest[T](Some(prefix), clazz, args.toList)
def arrayType[T](arg: OptManifest[_]): ClassManifest[Array[T]] = arg match {
@@ -228,7 +228,7 @@ object ClassManifestFactory {
/** Manifest for the class type `clazz[args]`, where `clazz` is
* a top-level or static class */
-private class ClassTypeManifest[T <: AnyRef](
+private class ClassTypeManifest[T](
prefix: Option[OptManifest[_]],
val runtimeClass: jClass[_],
override val typeArguments: List[OptManifest[_]]) extends ClassManifest[T]
diff --git a/src/partest/scala/tools/partest/nest/DirectRunner.scala b/src/partest/scala/tools/partest/nest/DirectRunner.scala
index 2bb373d9c5..6c239721c3 100644
--- a/src/partest/scala/tools/partest/nest/DirectRunner.scala
+++ b/src/partest/scala/tools/partest/nest/DirectRunner.scala
@@ -59,7 +59,8 @@ trait DirectRunner {
val futures = kindFiles map (f => (f, pool submit callable(manager runTest f))) toMap
pool.shutdown()
- pool.awaitTermination(1, TimeUnit.HOURS)
+ if (!pool.awaitTermination(4, TimeUnit.HOURS))
+ NestUI.warning("Thread pool timeout elapsed before all tests were complete!")
for ((file, future) <- futures) yield {
val state = if (future.isCancelled) TestState.Timeout else future.get
diff --git a/src/reflect/scala/reflect/api/StandardNames.scala b/src/reflect/scala/reflect/api/StandardNames.scala
index 9ec66b8531..eb1ecda900 100644
--- a/src/reflect/scala/reflect/api/StandardNames.scala
+++ b/src/reflect/scala/reflect/api/StandardNames.scala
@@ -43,7 +43,6 @@ trait StandardNames extends base.StandardNames {
val SUPER_PREFIX_STRING: String
val TRAIT_SETTER_SEPARATOR_STRING: String
- val ANYNAME: TermName
val FAKE_LOCAL_THIS: TermName
val INITIALIZER: TermName
val LAZY_LOCAL: TermName
diff --git a/src/reflect/scala/reflect/internal/AnnotationInfos.scala b/src/reflect/scala/reflect/internal/AnnotationInfos.scala
index c283ae408e..2bcc95b9a8 100644
--- a/src/reflect/scala/reflect/internal/AnnotationInfos.scala
+++ b/src/reflect/scala/reflect/internal/AnnotationInfos.scala
@@ -160,12 +160,7 @@ trait AnnotationInfos extends api.AnnotationInfos { self: SymbolTable =>
*/
final class LazyAnnotationInfo(lazyInfo: => AnnotationInfo) extends AnnotationInfo {
private var forced = false
- private lazy val forcedInfo =
- try {
- val result = lazyInfo
- if (result.pos == NoPosition) result setPos pos
- result
- } finally forced = true
+ private lazy val forcedInfo = try lazyInfo finally forced = true
def atp: Type = forcedInfo.atp
def args: List[Tree] = forcedInfo.args
diff --git a/src/reflect/scala/reflect/internal/Constants.scala b/src/reflect/scala/reflect/internal/Constants.scala
index 820dfe0868..d6a168ee11 100644
--- a/src/reflect/scala/reflect/internal/Constants.scala
+++ b/src/reflect/scala/reflect/internal/Constants.scala
@@ -221,7 +221,12 @@ trait Constants extends api.Constants {
tag match {
case NullTag => "null"
case StringTag => "\"" + escape(stringValue) + "\""
- case ClazzTag => "classOf[" + signature(typeValue) + "]"
+ case ClazzTag =>
+ def show(tpe: Type) = "classOf[" + signature(tpe) + "]"
+ typeValue match {
+ case ErasedValueType(orig) => show(orig)
+ case _ => show(typeValue)
+ }
case CharTag => "'" + escapedChar(charValue) + "'"
case LongTag => longValue.toString() + "L"
case EnumTag => symbolValue.name.toString()
diff --git a/src/reflect/scala/reflect/internal/Mirrors.scala b/src/reflect/scala/reflect/internal/Mirrors.scala
index 210af661ee..761b993539 100644
--- a/src/reflect/scala/reflect/internal/Mirrors.scala
+++ b/src/reflect/scala/reflect/internal/Mirrors.scala
@@ -180,7 +180,7 @@ trait Mirrors extends api.Mirrors {
// Still fiddling with whether it's cleaner to do some of this setup here
// or from constructors. The latter approach tends to invite init order issues.
- EmptyPackageClass setInfo ClassInfoType(Nil, newPackageScope(EmptyPackageClass), EmptyPackageClass)
+ EmptyPackageClass setInfo rootLoader
EmptyPackage setInfo EmptyPackageClass.tpe
connectModuleToClass(EmptyPackage, EmptyPackageClass)
@@ -231,7 +231,6 @@ trait Mirrors extends api.Mirrors {
override def isEffectiveRoot = true
override def isStatic = true
override def isNestedClass = false
- override def ownerOfNewSymbols = EmptyPackageClass
}
// The empty package, which holds all top level types without given packages.
final object EmptyPackage extends ModuleSymbol(RootClass, NoPosition, nme.EMPTY_PACKAGE_NAME) with WellKnownSymbol {
diff --git a/src/reflect/scala/reflect/internal/Names.scala b/src/reflect/scala/reflect/internal/Names.scala
index 20da38fd63..72e6707f57 100644
--- a/src/reflect/scala/reflect/internal/Names.scala
+++ b/src/reflect/scala/reflect/internal/Names.scala
@@ -415,6 +415,9 @@ trait Names extends api.Names with LowPriorityNames {
}
else toString
}
+
+ @inline
+ final def fingerPrint: Long = (1L << start)
/** TODO - find some efficiency. */
def append(ch: Char) = newName("" + this + ch)
diff --git a/src/reflect/scala/reflect/internal/Scopes.scala b/src/reflect/scala/reflect/internal/Scopes.scala
index ceacd2afb0..89e3c52de6 100644
--- a/src/reflect/scala/reflect/internal/Scopes.scala
+++ b/src/reflect/scala/reflect/internal/Scopes.scala
@@ -41,10 +41,15 @@ trait Scopes extends api.Scopes { self: SymbolTable =>
* This is necessary because when run from reflection every scope needs to have a
* SynchronizedScope as mixin.
*/
- class Scope protected[Scopes] (initElems: ScopeEntry = null) extends Iterable[Symbol] {
+ class Scope protected[Scopes] (initElems: ScopeEntry = null, initFingerPrints: Long = 0L) extends Iterable[Symbol] {
+
+ /** A bitset containing the last 6 bits of the start value of every name
+ * stored in this scope.
+ */
+ var fingerPrints: Long = initFingerPrints
protected[Scopes] def this(base: Scope) = {
- this(base.elems)
+ this(base.elems, base.fingerPrints)
nestinglevel = base.nestinglevel + 1
}
@@ -95,7 +100,7 @@ trait Scopes extends api.Scopes { self: SymbolTable =>
*
* @param e ...
*/
- protected def enter(e: ScopeEntry) {
+ protected def enterEntry(e: ScopeEntry) {
elemsCache = null
if (hashtable ne null)
enterInHash(e)
@@ -113,7 +118,11 @@ trait Scopes extends api.Scopes { self: SymbolTable =>
*
* @param sym ...
*/
- def enter[T <: Symbol](sym: T): T = { enter(newScopeEntry(sym, this)); sym }
+ def enter[T <: Symbol](sym: T): T = {
+ fingerPrints |= sym.name.fingerPrint
+ enterEntry(newScopeEntry(sym, this))
+ sym
+ }
/** enter a symbol, asserting that no symbol with same name exists in scope
*
@@ -147,6 +156,7 @@ trait Scopes extends api.Scopes { self: SymbolTable =>
}
def rehash(sym: Symbol, newname: Name) {
+ fingerPrints |= newname.fingerPrint
if (hashtable ne null) {
val index = sym.name.start & HASHMASK
var e1 = hashtable(index)
@@ -344,7 +354,7 @@ trait Scopes extends api.Scopes { self: SymbolTable =>
/** The empty scope (immutable).
*/
object EmptyScope extends Scope {
- override def enter(e: ScopeEntry) {
+ override def enterEntry(e: ScopeEntry) {
abort("EmptyScope.enter")
}
}
diff --git a/src/reflect/scala/reflect/internal/StdNames.scala b/src/reflect/scala/reflect/internal/StdNames.scala
index 165e04863c..c8a2424118 100644
--- a/src/reflect/scala/reflect/internal/StdNames.scala
+++ b/src/reflect/scala/reflect/internal/StdNames.scala
@@ -297,7 +297,7 @@ trait StdNames {
val WHILE_PREFIX = "while$"
// Compiler internal names
- val ANYNAME: NameType = "<anyname>"
+ val ANYname: NameType = "<anyname>"
val CONSTRUCTOR: NameType = "<init>"
val EQEQ_LOCAL_VAR: NameType = "eqEqTemp$"
val FAKE_LOCAL_THIS: NameType = "this$"
diff --git a/src/reflect/scala/reflect/internal/Symbols.scala b/src/reflect/scala/reflect/internal/Symbols.scala
index 04fa01c6f3..d484617767 100644
--- a/src/reflect/scala/reflect/internal/Symbols.scala
+++ b/src/reflect/scala/reflect/internal/Symbols.scala
@@ -100,13 +100,13 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
case _ =>
false
}
- (tp <:< pt) || isCompatibleByName(tp, pt)
+ (tp weak_<:< pt) || isCompatibleByName(tp, pt)
}
def signatureAsSpecific(method1: MethodSymbol, method2: MethodSymbol): Boolean = {
(substituteTypeParams(method1), substituteTypeParams(method2)) match {
case (NullaryMethodType(r1), NullaryMethodType(r2)) =>
- r1 <:< r2
+ r1 weak_<:< r2
case (NullaryMethodType(_), MethodType(_, _)) =>
true
case (MethodType(_, _), NullaryMethodType(_)) =>
@@ -298,7 +298,7 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
else {
val a = argTypes
val p = extend(paramTypes, argTypes.length)
- (a corresponds p)(_ <:< _)
+ (a corresponds p)(_ weak_<:< _)
}
}
}
@@ -813,11 +813,6 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
*/
def isEffectiveRoot = false
- /** For RootClass, this is EmptyPackageClass. For all other symbols,
- * the symbol itself.
- */
- def ownerOfNewSymbols = this
-
final def isLazyAccessor = isLazy && lazyAccessor != NoSymbol
final def isOverridableMember = !(isClass || isEffectivelyFinal) && (this ne NoSymbol) && owner.isClass
diff --git a/src/reflect/scala/reflect/internal/Types.scala b/src/reflect/scala/reflect/internal/Types.scala
index f3dd1f03ad..01679a777d 100644
--- a/src/reflect/scala/reflect/internal/Types.scala
+++ b/src/reflect/scala/reflect/internal/Types.scala
@@ -14,6 +14,7 @@ import Flags._
import scala.util.control.ControlThrowable
import scala.annotation.tailrec
import util.Statistics
+import scala.runtime.ObjectRef
/* A standard type pattern match:
case ErrorType =>
@@ -668,7 +669,8 @@ trait Types extends api.Types { self: SymbolTable =>
* Note: unfortunately it doesn't work to exclude DEFERRED this way.
*/
def membersBasedOnFlags(excludedFlags: Long, requiredFlags: Long): List[Symbol] =
- findMember(nme.ANYNAME, excludedFlags, requiredFlags, false).alternatives
+ findMembers(excludedFlags, requiredFlags)
+// findMember(nme.ANYNAME, excludedFlags, requiredFlags, false).alternatives
def memberBasedOnName(name: Name, excludedFlags: Long): Symbol =
findMember(name, excludedFlags, 0, false)
@@ -1018,6 +1020,72 @@ trait Types extends api.Types { self: SymbolTable =>
else (baseClasses.head.newOverloaded(this, alts))
}
+ def findMembers(excludedFlags: Long, requiredFlags: Long): List[Symbol] = {
+ // if this type contains type variables, put them to sleep for a while -- don't just wipe them out by
+ // replacing them by the corresponding type parameter, as that messes up (e.g.) type variables in type refinements
+ // without this, the matchesType call would lead to type variables on both sides
+ // of a subtyping/equality judgement, which can lead to recursive types being constructed.
+ // See (t0851) for a situation where this happens.
+ val suspension: List[TypeVar] = if (this.isGround) null else suspendTypeVarsInType(this)
+
+ Statistics.incCounter(findMembersCount)
+ val start = Statistics.pushTimer(typeOpsStack, findMembersNanos)
+
+ //Console.println("find member " + name.decode + " in " + this + ":" + this.baseClasses)//DEBUG
+ var members: Scope = null
+ var required = requiredFlags
+ var excluded = excludedFlags | DEFERRED
+ var continue = true
+ var self: Type = null
+ while (continue) {
+ continue = false
+ val bcs0 = baseClasses
+ var bcs = bcs0
+ while (!bcs.isEmpty) {
+ val decls = bcs.head.info.decls
+ var entry = decls.elems
+ while (entry ne null) {
+ val sym = entry.sym
+ val flags = sym.flags
+ if ((flags & required) == required) {
+ val excl = flags & excluded
+ if (excl == 0L &&
+ (// omit PRIVATE LOCALS unless selector class is contained in class owning the def.
+ (bcs eq bcs0) ||
+ (flags & PrivateLocal) != PrivateLocal ||
+ (bcs0.head.hasTransOwner(bcs.head)))) {
+ if (members eq null) members = newScope
+ var others: ScopeEntry = members.lookupEntry(sym.name)
+ var symtpe: Type = null
+ while ((others ne null) && {
+ val other = others.sym
+ (other ne sym) &&
+ ((other.owner eq sym.owner) ||
+ (flags & PRIVATE) != 0 || {
+ if (self eq null) self = this.narrow
+ if (symtpe eq null) symtpe = self.memberType(sym)
+ !(self.memberType(other) matches symtpe)
+ })}) {
+ others = members lookupNextEntry others
+ }
+ if (others eq null) members enter sym
+ } else if (excl == DEFERRED) {
+ continue = true
+ }
+ }
+ entry = entry.next
+ } // while (entry ne null)
+ // excluded = excluded | LOCAL
+ bcs = bcs.tail
+ } // while (!bcs.isEmpty)
+ required |= DEFERRED
+ excluded &= ~(DEFERRED.toLong)
+ } // while (continue)
+ Statistics.popTimer(typeOpsStack, start)
+ if (suspension ne null) suspension foreach (_.suspended = false)
+ if (members eq null) Nil else members.toList
+ }
+
/**
* Find member(s) in this type. If several members matching criteria are found, they are
* returned in an OverloadedSymbol
@@ -1040,75 +1108,83 @@ trait Types extends api.Types { self: SymbolTable =>
val start = Statistics.pushTimer(typeOpsStack, findMemberNanos)
//Console.println("find member " + name.decode + " in " + this + ":" + this.baseClasses)//DEBUG
- var members: Scope = null
var member: Symbol = NoSymbol
+ var members: List[Symbol] = null
+ var lastM: ::[Symbol] = null
+ var membertpe: Type = null
+ var required = requiredFlags
var excluded = excludedFlags | DEFERRED
var continue = true
var self: Type = null
- var membertpe: Type = null
+ val fingerPrint: Long = name.fingerPrint
+
while (continue) {
continue = false
val bcs0 = baseClasses
var bcs = bcs0
while (!bcs.isEmpty) {
val decls = bcs.head.info.decls
- var entry =
- if (name == nme.ANYNAME) decls.elems else decls.lookupEntry(name)
- while (entry ne null) {
- val sym = entry.sym
- if (sym hasAllFlags requiredFlags) {
- val excl = sym.getFlag(excluded)
- if (excl == 0L &&
- (// omit PRIVATE LOCALS unless selector class is contained in class owning the def.
- (bcs eq bcs0) ||
- !sym.isPrivateLocal ||
- (bcs0.head.hasTransOwner(bcs.head)))) {
- if (name.isTypeName || stableOnly && sym.isStable) {
- Statistics.popTimer(typeOpsStack, start)
- if (suspension ne null) suspension foreach (_.suspended = false)
- return sym
- } else if (member == NoSymbol) {
- member = sym
- } else if (members eq null) {
- if (member.name != sym.name ||
- !(member == sym ||
- member.owner != sym.owner &&
- !sym.isPrivate && {
- if (self eq null) self = this.narrow
- if (membertpe eq null) membertpe = self.memberType(member)
- (membertpe matches self.memberType(sym))
- })) {
- members = newScope
- members enter member
- members enter sym
- }
- } else {
- var prevEntry = members.lookupEntry(sym.name)
- var symtpe: Type = null
- while ((prevEntry ne null) &&
- !(prevEntry.sym == sym ||
- prevEntry.sym.owner != sym.owner &&
- !sym.hasFlag(PRIVATE) && {
- if (self eq null) self = this.narrow
- if (symtpe eq null) symtpe = self.memberType(sym)
- self.memberType(prevEntry.sym) matches symtpe
- })) {
- prevEntry = members lookupNextEntry prevEntry
- }
- if (prevEntry eq null) {
- members enter sym
+ if ((fingerPrint & decls.fingerPrints) != 0) {
+ var entry = decls.lookupEntry(name)
+ while (entry ne null) {
+ val sym = entry.sym
+ val flags = sym.flags
+ if ((flags & required) == required) {
+ val excl = flags & excluded
+ if (excl == 0L &&
+ (// omit PRIVATE LOCALS unless selector class is contained in class owning the def.
+ (bcs eq bcs0) ||
+ (flags & PrivateLocal) != PrivateLocal ||
+ (bcs0.head.hasTransOwner(bcs.head)))) {
+ if (name.isTypeName || stableOnly && sym.isStable) {
+ Statistics.popTimer(typeOpsStack, start)
+ if (suspension ne null) suspension foreach (_.suspended = false)
+ return sym
+ } else if (member eq NoSymbol) {
+ member = sym
+ } else if (members eq null) {
+ if ((member ne sym) &&
+ ((member.owner eq sym.owner) ||
+ (flags & PRIVATE) != 0 || {
+ if (self eq null) self = this.narrow
+ if (membertpe eq null) membertpe = self.memberType(member)
+ !(membertpe matches self.memberType(sym))
+ })) {
+ lastM = new ::(sym, null)
+ members = member :: lastM
+ }
+ } else {
+ var others: List[Symbol] = members
+ var symtpe: Type = null
+ while ((others ne null) && {
+ val other = others.head
+ (other ne sym) &&
+ ((other.owner eq sym.owner) ||
+ (flags & PRIVATE) != 0 || {
+ if (self eq null) self = this.narrow
+ if (symtpe eq null) symtpe = self.memberType(sym)
+ !(self.memberType(other) matches symtpe)
+ })}) {
+ others = others.tail
+ }
+ if (others eq null) {
+ val lastM1 = new ::(sym, null)
+ lastM.tl = lastM1
+ lastM = lastM1
+ }
}
+ } else if (excl == DEFERRED) {
+ continue = true
}
- } else if (excl == DEFERRED.toLong) {
- continue = true
}
- }
- entry = if (name == nme.ANYNAME) entry.next else decls lookupNextEntry entry
- } // while (entry ne null)
+ entry = decls lookupNextEntry entry
+ } // while (entry ne null)
+ } // if (fingerPrint matches)
// excluded = excluded | LOCAL
bcs = if (name == nme.CONSTRUCTOR) Nil else bcs.tail
} // while (!bcs.isEmpty)
- excluded = excludedFlags
+ required |= DEFERRED
+ excluded &= ~(DEFERRED.toLong)
} // while (continue)
Statistics.popTimer(typeOpsStack, start)
if (suspension ne null) suspension foreach (_.suspended = false)
@@ -1117,9 +1193,11 @@ trait Types extends api.Types { self: SymbolTable =>
member
} else {
Statistics.incCounter(multMemberCount)
- baseClasses.head.newOverloaded(this, members.toList)
+ lastM.tl = Nil
+ baseClasses.head.newOverloaded(this, members)
}
}
+
/** The (existential or otherwise) skolems and existentially quantified variables which are free in this type */
def skolemsExceptMethodTypeParams: List[Symbol] = {
var boundSyms: List[Symbol] = List()
@@ -1610,8 +1688,13 @@ trait Types extends api.Types { self: SymbolTable =>
if (period != currentPeriod) {
tpe.baseClassesPeriod = currentPeriod
if (!isValidForBaseClasses(period)) {
- tpe.baseClassesCache = null
- tpe.baseClassesCache = tpe.memo(computeBaseClasses)(tpe.typeSymbol :: _.baseClasses.tail)
+ val start = Statistics.pushTimer(typeOpsStack, baseClassesNanos)
+ try {
+ tpe.baseClassesCache = null
+ tpe.baseClassesCache = tpe.memo(computeBaseClasses)(tpe.typeSymbol :: _.baseClasses.tail)
+ } finally {
+ Statistics.popTimer(typeOpsStack, start)
+ }
}
}
if (tpe.baseClassesCache eq null)
@@ -5066,7 +5149,7 @@ trait Types extends api.Types { self: SymbolTable =>
*/
def needsOuterTest(patType: Type, selType: Type, currentOwner: Symbol) = {
def createDummyClone(pre: Type): Type = {
- val dummy = currentOwner.enclClass.newValue(nme.ANYNAME).setInfo(pre.widen)
+ val dummy = currentOwner.enclClass.newValue(nme.ANYname).setInfo(pre.widen)
singleType(ThisType(currentOwner.enclClass), dummy)
}
def maybeCreateDummyClone(pre: Type, sym: Symbol): Type = pre match {
@@ -6909,14 +6992,17 @@ object TypesStats {
val lubCount = Statistics.newCounter ("#toplevel lubs/glbs")
val nestedLubCount = Statistics.newCounter ("#all lubs/glbs")
val findMemberCount = Statistics.newCounter ("#findMember ops")
+ val findMembersCount = Statistics.newCounter ("#findMembers ops")
val noMemberCount = Statistics.newSubCounter(" of which not found", findMemberCount)
val multMemberCount = Statistics.newSubCounter(" of which multiple overloaded", findMemberCount)
val typerNanos = Statistics.newTimer ("time spent typechecking", "typer")
val lubNanos = Statistics.newStackableTimer("time spent in lubs", typerNanos)
val subtypeNanos = Statistics.newStackableTimer("time spent in <:<", typerNanos)
val findMemberNanos = Statistics.newStackableTimer("time spent in findmember", typerNanos)
+ val findMembersNanos = Statistics.newStackableTimer("time spent in findmembers", typerNanos)
val asSeenFromNanos = Statistics.newStackableTimer("time spent in asSeenFrom", typerNanos)
val baseTypeSeqNanos = Statistics.newStackableTimer("time spent in baseTypeSeq", typerNanos)
+ val baseClassesNanos = Statistics.newStackableTimer("time spent in baseClasses", typerNanos)
val compoundBaseTypeSeqCount = Statistics.newSubCounter(" of which for compound types", baseTypeSeqCount)
val typerefBaseTypeSeqCount = Statistics.newSubCounter(" of which for typerefs", baseTypeSeqCount)
val singletonBaseTypeSeqCount = Statistics.newSubCounter(" of which for singletons", baseTypeSeqCount)
diff --git a/src/reflect/scala/reflect/makro/Enclosures.scala b/src/reflect/scala/reflect/makro/Enclosures.scala
index 69bd8d09c7..ff5c13a785 100644
--- a/src/reflect/scala/reflect/makro/Enclosures.scala
+++ b/src/reflect/scala/reflect/makro/Enclosures.scala
@@ -36,10 +36,6 @@ trait Enclosures {
*/
val enclosingPosition: Position
- /** Tree that corresponds to the enclosing application, or EmptyTree if not applicable.
- */
- val enclosingApplication: Tree
-
/** Tree that corresponds to the enclosing method, or EmptyTree if not applicable.
*/
val enclosingMethod: Tree
diff --git a/src/reflect/scala/reflect/runtime/SymbolLoaders.scala b/src/reflect/scala/reflect/runtime/SymbolLoaders.scala
index c1cd5d2911..eb48e9dc79 100644
--- a/src/reflect/scala/reflect/runtime/SymbolLoaders.scala
+++ b/src/reflect/scala/reflect/runtime/SymbolLoaders.scala
@@ -99,8 +99,10 @@ trait SymbolLoaders { self: SymbolTable =>
0 < dp && dp < (name.length - 1)
}
- class PackageScope(pkgClass: Symbol) extends Scope() with SynchronizedScope {
+ class PackageScope(pkgClass: Symbol) extends Scope(initFingerPrints = -1L) // disable fingerprinting as we do not know entries beforehand
+ with SynchronizedScope {
assert(pkgClass.isType)
+ // disable fingerprinting as we do not know entries beforehand
private val negatives = mutable.Set[Name]() // Syncnote: Performance only, so need not be protected.
override def lookupEntry(name: Name): ScopeEntry = {
val e = super.lookupEntry(name)
diff --git a/test/files/neg/t5892.check b/test/files/neg/t5892.check
new file mode 100644
index 0000000000..839bf9de23
--- /dev/null
+++ b/test/files/neg/t5892.check
@@ -0,0 +1,17 @@
+t5892.scala:5: error: type mismatch;
+ found : Boolean(false)
+ required: String
+class C[@annot(false) X] {
+ ^
+t5892.scala:9: error: not found: value b2s
+class D[@annot(b2s(false)) X] {
+ ^
+t5892.scala:13: error: type mismatch;
+ found : Boolean(false)
+ required: String
+@annot(false) class E {
+ ^
+t5892.scala:17: error: not found: value b2s
+@annot(b2s(false)) class F {
+ ^
+four errors found
diff --git a/test/files/neg/t5892.scala b/test/files/neg/t5892.scala
new file mode 100644
index 0000000000..5e3b2f313e
--- /dev/null
+++ b/test/files/neg/t5892.scala
@@ -0,0 +1,25 @@
+import language.implicitConversions
+
+class annot(a: String) extends annotation.StaticAnnotation
+
+class C[@annot(false) X] {
+ implicit def b2s(b: Boolean): String = ""
+}
+
+class D[@annot(b2s(false)) X] {
+ implicit def b2s(b: Boolean): String = ""
+}
+
+@annot(false) class E {
+ implicit def b2s(b: Boolean): String = ""
+}
+
+@annot(b2s(false)) class F {
+ implicit def b2s(b: Boolean): String = ""
+}
+
+object T {
+ implicit def b2s(b: Boolean): String = ""
+ @annot(false) val x = 0
+ @annot(b2s(false)) val y = 0
+}
diff --git a/test/files/pos/t5892.scala b/test/files/pos/t5892.scala
new file mode 100644
index 0000000000..241e59860a
--- /dev/null
+++ b/test/files/pos/t5892.scala
@@ -0,0 +1,5 @@
+class foo(a: String) extends annotation.StaticAnnotation
+object o {
+ implicit def i2s(i: Int) = ""
+ @foo(1: String) def blerg { }
+}
diff --git a/test/files/pos/t6028/t6028_1.scala b/test/files/pos/t6028/t6028_1.scala
new file mode 100644
index 0000000000..6edb76069e
--- /dev/null
+++ b/test/files/pos/t6028/t6028_1.scala
@@ -0,0 +1,3 @@
+class C {
+ def foo(a: Int): Unit = () => a
+}
diff --git a/test/files/pos/t6028/t6028_2.scala b/test/files/pos/t6028/t6028_2.scala
new file mode 100644
index 0000000000..f44048c0ab
--- /dev/null
+++ b/test/files/pos/t6028/t6028_2.scala
@@ -0,0 +1,4 @@
+object Test {
+ // ensure that parameter names are untouched by lambdalift
+ new C().foo(a = 0)
+}
diff --git a/test/files/run/nullable-lazyvals.check b/test/files/run/nullable-lazyvals.check
new file mode 100644
index 0000000000..4db5783257
--- /dev/null
+++ b/test/files/run/nullable-lazyvals.check
@@ -0,0 +1,3 @@
+
+param1: null
+param2: null
diff --git a/test/files/run/nullable-lazyvals.scala b/test/files/run/nullable-lazyvals.scala
new file mode 100644
index 0000000000..c201e74e75
--- /dev/null
+++ b/test/files/run/nullable-lazyvals.scala
@@ -0,0 +1,36 @@
+
+/** Test that call-by-name parameters are set to null if
+ * they are used only to initialize a lazy value, after the
+ * value has been initialized.
+ */
+
+class Foo(param1: => Object, param2: => String) {
+ lazy val field1 = param1
+ lazy val field2 = try param2 finally println("")
+}
+
+object Test extends App {
+ val foo = new Foo(new Object, "abc")
+
+ foo.field1
+ foo.field2
+
+ for (f <- foo.getClass.getDeclaredFields) {
+ f.setAccessible(true)
+ if (f.getName.startsWith("param")) {
+ println("%s: %s".format(f.getName, f.get(foo)))
+ }
+ }
+
+ // test that try-finally does not generated a liftedTry
+ // helper. This would already fail the first part of the test,
+ // but this check will help diganose it (if the single access to a
+ // private field does not happen directly in the lazy val, it won't
+ // be nulled).
+ for (f <- foo.getClass.getDeclaredMethods) {
+ f.setAccessible(true)
+ if (f.getName.startsWith("lifted")) {
+ println("not expected: %s".format(f))
+ }
+ }
+}
diff --git a/test/files/run/reflect-resolveoverload-invalid.scala b/test/files/run/reflect-resolveoverload-invalid.scala
index def28ccbb4..8c5dc9f94b 100644
--- a/test/files/run/reflect-resolveoverload-invalid.scala
+++ b/test/files/run/reflect-resolveoverload-invalid.scala
@@ -27,7 +27,7 @@ object Test extends App {
val d = t member u.newTermName("d") asTermSymbol
val e = t member u.newTermName("e") asTermSymbol
- val n1 = a.resolveOverloaded(posVargs = List(u.typeOf[Char]))
+ val n1 = a.resolveOverloaded(posVargs = List(u.typeOf[Long]))
val n2 = b.resolveOverloaded(posVargs = List(u.typeOf[A]))
val n3 = c.resolveOverloaded(posVargs = List(u.typeOf[B], u.typeOf[B]))
val n4 = d.resolveOverloaded(targs = List(u.typeOf[Int]))
diff --git a/test/files/run/reflect-resolveoverload2.scala b/test/files/run/reflect-resolveoverload2.scala
index b5f719814b..a800a3e92c 100644
--- a/test/files/run/reflect-resolveoverload2.scala
+++ b/test/files/run/reflect-resolveoverload2.scala
@@ -2,16 +2,20 @@ class A
class B extends A
class C {
- def a(x: Int) = 1
- def a(x: String) = 2
- //def b(x: => Int)(s: String) = 1
- //def b(x: => String)(a: Array[_]) = 2
- def c(x: A) = 1
- def c(x: B) = 2
- //def d(x: => A)(s: String) = 1
- //def d(x: => B)(a: Array[_]) = 2
- def e(x: A) = 1
- def e(x: B = new B) = 2
+ def a(x: Int) = 1
+ def a(x: String) = 2
+ //def b(x: => Int)(s: String) = 1
+ //def b(x: => String)(a: Array[_]) = 2
+ def c(x: A) = 1
+ def c(x: B) = 2
+ //def d(x: => A)(s: String) = 1
+ //def d(x: => B)(a: Array[_]) = 2
+ def e(x: A) = 1
+ def e(x: B = new B) = 2
+ def f(x: Int) = 1
+ def f(x: String) = 2
+ def f(x: Long) = 3
+ def f(x: Double) = 4
}
object Test extends App {
@@ -29,6 +33,8 @@ object Test extends App {
}
assert(c.a(1) == invoke("a", 1, u.typeOf[Int]))
assert(c.a("a") == invoke("a", "a", u.typeOf[String]))
+ assert(c.a('a') == invoke("a", 'a', u.typeOf[Char]))
+ assert(c.a(3: Byte) == invoke("a", 3: Byte, u.typeOf[Byte]))
//assert(c.b(1)(null) == invoke("b", 1, u.typeOf[Int]))
//assert(c.b("a")(null) == invoke("b", "a", u.typeOf[String]))
assert(c.c(new A) == invoke("c", new A, u.typeOf[A]))
@@ -37,4 +43,9 @@ object Test extends App {
//assert(c.d(new B)(null) == invoke("d", new B, u.typeOf[B]))
assert(c.e(new A) == invoke("e", new A, u.typeOf[A]))
assert(c.e(new B) == invoke("e", new B, u.typeOf[B]))
+ assert(c.f(1: Short) == invoke("f", 1: Short, u.typeOf[Short]))
+ assert(c.f(2) == invoke("f", 2, u.typeOf[Int]))
+ assert(c.f(3L) == invoke("f", 3L, u.typeOf[Long]))
+ assert(c.f(4f) == invoke("f", 4f, u.typeOf[Float]))
+ assert(c.f(5d) == invoke("f", 5d, u.typeOf[Double]))
}
diff --git a/test/files/run/t5588.check b/test/files/run/t5588.check
new file mode 100644
index 0000000000..bb101b641b
--- /dev/null
+++ b/test/files/run/t5588.check
@@ -0,0 +1,2 @@
+true
+true
diff --git a/test/files/run/t5588.scala b/test/files/run/t5588.scala
new file mode 100644
index 0000000000..f214d16684
--- /dev/null
+++ b/test/files/run/t5588.scala
@@ -0,0 +1,14 @@
+object Test {
+ object MyEnum extends Enumeration {
+ val Foo = Value(2000000000)
+ val Bar = Value(-2000000000)
+ val X = Value(Integer.MAX_VALUE)
+ val Y = Value(Integer.MIN_VALUE)
+ }
+
+ import MyEnum._
+ def main(args: Array[String]) {
+ println(Foo > Bar)
+ println(X > Y)
+ }
+}
diff --git a/test/files/run/t5937.scala b/test/files/run/t5937.scala
new file mode 100644
index 0000000000..e5bf6617af
--- /dev/null
+++ b/test/files/run/t5937.scala
@@ -0,0 +1,12 @@
+
+
+
+import collection._
+
+
+
+object Test extends App {
+
+ val list: List[Int] = (immutable.Vector(1, 2, 3) :+ 4)(breakOut)
+
+}
diff --git a/test/files/run/t6028.check b/test/files/run/t6028.check
new file mode 100644
index 0000000000..dca61115ad
--- /dev/null
+++ b/test/files/run/t6028.check
@@ -0,0 +1,84 @@
+[[syntax trees at end of lambdalift]] // newSource1
+package <empty> {
+ class T extends Object {
+ <paramaccessor> val T$$classParam: Int = _;
+ def <init>(classParam: Int): T = {
+ T.super.<init>();
+ ()
+ };
+ private[this] val field: Int = 0;
+ <stable> <accessor> def field(): Int = T.this.field;
+ def foo(methodParam: Int): Function0 = {
+ val methodLocal: Int = 0;
+ {
+ (new anonymous class $anonfun$foo$1(T.this, methodParam, methodLocal): Function0)
+ }
+ };
+ def bar(barParam: Int): Object = {
+ @volatile var MethodLocalObject$module: scala.runtime.VolatileObjectRef = new scala.runtime.VolatileObjectRef(<empty>);
+ T.this.MethodLocalObject$1(barParam, MethodLocalObject$module)
+ };
+ def tryy(tryyParam: Int): Function0 = {
+ var tryyLocal: scala.runtime.IntRef = new scala.runtime.IntRef(0);
+ {
+ (new anonymous class $anonfun$tryy$1(T.this, tryyParam, tryyLocal): Function0)
+ }
+ };
+ @SerialVersionUID(0) final <synthetic> class $anonfun$foo$1 extends scala.runtime.AbstractFunction0$mcI$sp with Serializable {
+ def <init>($outer: T, methodParam$1: Int, methodLocal$1: Int): anonymous class $anonfun$foo$1 = {
+ $anonfun$foo$1.super.<init>();
+ ()
+ };
+ final def apply(): Int = $anonfun$foo$1.this.apply$mcI$sp();
+ <specialized> def apply$mcI$sp(): Int = $anonfun$foo$1.this.$outer.T$$classParam.+($anonfun$foo$1.this.$outer.field()).+($anonfun$foo$1.this.methodParam$1).+($anonfun$foo$1.this.methodLocal$1);
+ <synthetic> <paramaccessor> private[this] val $outer: T = _;
+ <synthetic> <stable> def T$$anonfun$$$outer(): T = $anonfun$foo$1.this.$outer;
+ final <bridge> def apply(): Object = scala.Int.box($anonfun$foo$1.this.apply());
+ <synthetic> <paramaccessor> private[this] val methodParam$1: Int = _;
+ <synthetic> <paramaccessor> private[this] val methodLocal$1: Int = _
+ };
+ abstract trait MethodLocalTrait$1 extends Object {
+ <synthetic> <stable> def T$MethodLocalTrait$$$outer(): T
+ };
+ object MethodLocalObject$2 extends Object with T#MethodLocalTrait$1 {
+ def <init>($outer: T, barParam$1: Int): ... = {
+ MethodLocalObject$2.super.<init>();
+ MethodLocalObject$2.this.$asInstanceOf[T#MethodLocalTrait$1$class]()./*MethodLocalTrait$1$class*/$init$(barParam$1);
+ ()
+ };
+ <synthetic> <paramaccessor> private[this] val $outer: T = _;
+ <synthetic> <stable> def T$MethodLocalObject$$$outer(): T = MethodLocalObject$2.this.$outer;
+ <synthetic> <stable> def T$MethodLocalTrait$$$outer(): T = MethodLocalObject$2.this.$outer
+ };
+ final <stable> private[this] def MethodLocalObject$1(barParam$1: Int, MethodLocalObject$module$1: scala.runtime.VolatileObjectRef): ... = {
+ MethodLocalObject$module$1.elem = new ...(T.this, barParam$1);
+ MethodLocalObject$module$1.elem.$asInstanceOf[...]()
+ };
+ abstract trait MethodLocalTrait$1$class extends Object with T#MethodLocalTrait$1 {
+ def /*MethodLocalTrait$1$class*/$init$(barParam$1: Int): Unit = {
+ ()
+ };
+ scala.this.Predef.print(scala.Int.box(barParam$1))
+ };
+ @SerialVersionUID(0) final <synthetic> class $anonfun$tryy$1 extends scala.runtime.AbstractFunction0$mcV$sp with Serializable {
+ def <init>($outer: T, tryyParam$1: Int, tryyLocal$1: scala.runtime.IntRef): anonymous class $anonfun$tryy$1 = {
+ $anonfun$tryy$1.super.<init>();
+ ()
+ };
+ final def apply(): Unit = $anonfun$tryy$1.this.apply$mcV$sp();
+ <specialized> def apply$mcV$sp(): Unit = try {
+ $anonfun$tryy$1.this.tryyLocal$1.elem = $anonfun$tryy$1.this.tryyParam$1
+ } finally ();
+ <synthetic> <paramaccessor> private[this] val $outer: T = _;
+ <synthetic> <stable> def T$$anonfun$$$outer(): T = $anonfun$tryy$1.this.$outer;
+ final <bridge> def apply(): Object = {
+ $anonfun$tryy$1.this.apply();
+ scala.runtime.BoxedUnit.UNIT
+ };
+ <synthetic> <paramaccessor> private[this] val tryyParam$1: Int = _;
+ <synthetic> <paramaccessor> private[this] val tryyLocal$1: scala.runtime.IntRef = _
+ }
+ }
+}
+
+warning: there were 1 feature warnings; re-run with -feature for details
diff --git a/test/files/run/t6028.scala b/test/files/run/t6028.scala
new file mode 100644
index 0000000000..cab17535fc
--- /dev/null
+++ b/test/files/run/t6028.scala
@@ -0,0 +1,21 @@
+import scala.tools.partest._
+import java.io.{Console => _, _}
+
+object Test extends DirectTest {
+
+ override def extraSettings: String = "-usejavacp -Xprint:lambdalift -d " + testOutput.path
+
+ override def code = """class T(classParam: Int) {
+ | val field: Int = 0
+ | def foo(methodParam: Int) = {val methodLocal = 0 ; () => classParam + field + methodParam + methodLocal }
+ | def bar(barParam: Int) = { trait MethodLocalTrait { print(barParam) }; object MethodLocalObject extends MethodLocalTrait; MethodLocalObject }
+ | def tryy(tryyParam: Int) = { var tryyLocal = 0; () => try { tryyLocal = tryyParam } finally () }
+ |}
+ |""".stripMargin.trim
+
+ override def show(): Unit = {
+ Console.withErr(System.out) {
+ compile()
+ }
+ }
+}
diff --git a/test/files/run/t6077_patmat_cse_irrefutable.check b/test/files/run/t6077_patmat_cse_irrefutable.check
new file mode 100644
index 0000000000..9766475a41
--- /dev/null
+++ b/test/files/run/t6077_patmat_cse_irrefutable.check
@@ -0,0 +1 @@
+ok
diff --git a/test/files/run/t6077_patmat_cse_irrefutable.scala b/test/files/run/t6077_patmat_cse_irrefutable.scala
new file mode 100644
index 0000000000..b130ae7813
--- /dev/null
+++ b/test/files/run/t6077_patmat_cse_irrefutable.scala
@@ -0,0 +1,13 @@
+class LiteralNode(val value: Any)
+
+object LiteralNode {
+ // irrefutable
+ def unapply(n: LiteralNode) = Some(n.value)
+}
+
+object Test extends App {
+ ((new LiteralNode(false)): Any) match {
+ case LiteralNode(true) => println("uh-oh")
+ case LiteralNode(false) => println("ok")
+ }
+} \ No newline at end of file
diff --git a/test/files/run/t6089.check b/test/files/run/t6089.check
new file mode 100644
index 0000000000..a8d4424106
--- /dev/null
+++ b/test/files/run/t6089.check
@@ -0,0 +1 @@
+scala.MatchError: Foo(0) (of class Foo)
diff --git a/test/files/run/t6089.scala b/test/files/run/t6089.scala
new file mode 100644
index 0000000000..c72d7ba792
--- /dev/null
+++ b/test/files/run/t6089.scala
@@ -0,0 +1,13 @@
+case class Foo(x: Int)
+
+object Test {
+ def bippo(result: Boolean): Boolean = result
+ def bungus(m: Foo): Boolean =
+ bippo(m match { case Foo(2) => bungus(m) })
+
+ def main(args: Array[String]): Unit = try {
+ bungus(Foo(0))
+ } catch {
+ case x: MatchError => println(x)
+ }
+} \ No newline at end of file
diff --git a/test/files/run/valueclasses-classmanifest-basic.check b/test/files/run/valueclasses-classmanifest-basic.check
new file mode 100644
index 0000000000..554c75e074
--- /dev/null
+++ b/test/files/run/valueclasses-classmanifest-basic.check
@@ -0,0 +1 @@
+Foo
diff --git a/test/files/run/valueclasses-classmanifest-basic.scala b/test/files/run/valueclasses-classmanifest-basic.scala
new file mode 100644
index 0000000000..c2aa08ef86
--- /dev/null
+++ b/test/files/run/valueclasses-classmanifest-basic.scala
@@ -0,0 +1,5 @@
+class Foo(val x: Int) extends AnyVal
+
+object Test extends App {
+ println(classManifest[Foo])
+} \ No newline at end of file
diff --git a/test/files/run/valueclasses-classmanifest-existential.check b/test/files/run/valueclasses-classmanifest-existential.check
new file mode 100644
index 0000000000..e9fc6e27ea
--- /dev/null
+++ b/test/files/run/valueclasses-classmanifest-existential.check
@@ -0,0 +1 @@
+Foo[<?>]
diff --git a/test/files/run/valueclasses-classmanifest-existential.scala b/test/files/run/valueclasses-classmanifest-existential.scala
new file mode 100644
index 0000000000..11999df678
--- /dev/null
+++ b/test/files/run/valueclasses-classmanifest-existential.scala
@@ -0,0 +1,5 @@
+class Foo[T](val x: T) extends AnyVal
+
+object Test extends App {
+ println(classManifest[Foo[_]])
+} \ No newline at end of file
diff --git a/test/files/run/valueclasses-classmanifest-generic.check b/test/files/run/valueclasses-classmanifest-generic.check
new file mode 100644
index 0000000000..1418c5cff9
--- /dev/null
+++ b/test/files/run/valueclasses-classmanifest-generic.check
@@ -0,0 +1 @@
+Foo[java.lang.String]
diff --git a/test/files/run/valueclasses-classmanifest-generic.scala b/test/files/run/valueclasses-classmanifest-generic.scala
new file mode 100644
index 0000000000..280152dc1d
--- /dev/null
+++ b/test/files/run/valueclasses-classmanifest-generic.scala
@@ -0,0 +1,5 @@
+class Foo[T](val x: T) extends AnyVal
+
+object Test extends App {
+ println(classManifest[Foo[String]])
+} \ No newline at end of file
diff --git a/test/files/run/valueclasses-classtag-basic.check b/test/files/run/valueclasses-classtag-basic.check
new file mode 100644
index 0000000000..0c13986b32
--- /dev/null
+++ b/test/files/run/valueclasses-classtag-basic.check
@@ -0,0 +1 @@
+ClassTag[class Foo]
diff --git a/test/files/run/valueclasses-classtag-basic.scala b/test/files/run/valueclasses-classtag-basic.scala
new file mode 100644
index 0000000000..912a4bb019
--- /dev/null
+++ b/test/files/run/valueclasses-classtag-basic.scala
@@ -0,0 +1,5 @@
+class Foo(val x: Int) extends AnyVal
+
+object Test extends App {
+ println(scala.reflect.classTag[Foo])
+} \ No newline at end of file
diff --git a/test/files/run/valueclasses-classtag-existential.check b/test/files/run/valueclasses-classtag-existential.check
new file mode 100644
index 0000000000..95e94e7aee
--- /dev/null
+++ b/test/files/run/valueclasses-classtag-existential.check
@@ -0,0 +1 @@
+ClassTag[class java.lang.Object]
diff --git a/test/files/run/valueclasses-classtag-existential.scala b/test/files/run/valueclasses-classtag-existential.scala
new file mode 100644
index 0000000000..e0db9cdd75
--- /dev/null
+++ b/test/files/run/valueclasses-classtag-existential.scala
@@ -0,0 +1,5 @@
+class Foo[T](val x: T) extends AnyVal
+
+object Test extends App {
+ println(scala.reflect.classTag[Foo[_]])
+} \ No newline at end of file
diff --git a/test/files/run/valueclasses-classtag-generic.check b/test/files/run/valueclasses-classtag-generic.check
new file mode 100644
index 0000000000..0c13986b32
--- /dev/null
+++ b/test/files/run/valueclasses-classtag-generic.check
@@ -0,0 +1 @@
+ClassTag[class Foo]
diff --git a/test/files/run/valueclasses-classtag-generic.scala b/test/files/run/valueclasses-classtag-generic.scala
new file mode 100644
index 0000000000..bd1f213835
--- /dev/null
+++ b/test/files/run/valueclasses-classtag-generic.scala
@@ -0,0 +1,5 @@
+class Foo[T](val x: T) extends AnyVal
+
+object Test extends App {
+ println(scala.reflect.classTag[Foo[String]])
+} \ No newline at end of file
diff --git a/test/files/run/valueclasses-manifest-basic.check b/test/files/run/valueclasses-manifest-basic.check
new file mode 100644
index 0000000000..554c75e074
--- /dev/null
+++ b/test/files/run/valueclasses-manifest-basic.check
@@ -0,0 +1 @@
+Foo
diff --git a/test/files/run/valueclasses-manifest-basic.scala b/test/files/run/valueclasses-manifest-basic.scala
new file mode 100644
index 0000000000..eefab20168
--- /dev/null
+++ b/test/files/run/valueclasses-manifest-basic.scala
@@ -0,0 +1,5 @@
+class Foo(val x: Int) extends AnyVal
+
+object Test extends App {
+ println(manifest[Foo])
+} \ No newline at end of file
diff --git a/test/files/run/valueclasses-manifest-existential.check b/test/files/run/valueclasses-manifest-existential.check
new file mode 100644
index 0000000000..fdce051039
--- /dev/null
+++ b/test/files/run/valueclasses-manifest-existential.check
@@ -0,0 +1 @@
+Foo[_ <: Any]
diff --git a/test/files/run/valueclasses-manifest-existential.scala b/test/files/run/valueclasses-manifest-existential.scala
new file mode 100644
index 0000000000..47eb6d64dd
--- /dev/null
+++ b/test/files/run/valueclasses-manifest-existential.scala
@@ -0,0 +1,5 @@
+class Foo[T](val x: T) extends AnyVal
+
+object Test extends App {
+ println(manifest[Foo[_]])
+} \ No newline at end of file
diff --git a/test/files/run/valueclasses-manifest-generic.check b/test/files/run/valueclasses-manifest-generic.check
new file mode 100644
index 0000000000..1418c5cff9
--- /dev/null
+++ b/test/files/run/valueclasses-manifest-generic.check
@@ -0,0 +1 @@
+Foo[java.lang.String]
diff --git a/test/files/run/valueclasses-manifest-generic.scala b/test/files/run/valueclasses-manifest-generic.scala
new file mode 100644
index 0000000000..18313fba6f
--- /dev/null
+++ b/test/files/run/valueclasses-manifest-generic.scala
@@ -0,0 +1,5 @@
+class Foo[T](val x: T) extends AnyVal
+
+object Test extends App {
+ println(manifest[Foo[String]])
+} \ No newline at end of file
diff --git a/test/files/run/valueclasses-typetag-basic.check b/test/files/run/valueclasses-typetag-basic.check
new file mode 100644
index 0000000000..554c75e074
--- /dev/null
+++ b/test/files/run/valueclasses-typetag-basic.check
@@ -0,0 +1 @@
+Foo
diff --git a/test/files/run/valueclasses-typetag-basic.scala b/test/files/run/valueclasses-typetag-basic.scala
new file mode 100644
index 0000000000..d0243f7378
--- /dev/null
+++ b/test/files/run/valueclasses-typetag-basic.scala
@@ -0,0 +1,5 @@
+class Foo(val x: Int) extends AnyVal
+
+object Test extends App {
+ println(scala.reflect.runtime.universe.typeOf[Foo])
+} \ No newline at end of file
diff --git a/test/files/run/valueclasses-typetag-existential.check b/test/files/run/valueclasses-typetag-existential.check
new file mode 100644
index 0000000000..0efa24a45f
--- /dev/null
+++ b/test/files/run/valueclasses-typetag-existential.check
@@ -0,0 +1 @@
+Foo[_]
diff --git a/test/files/run/valueclasses-typetag-existential.scala b/test/files/run/valueclasses-typetag-existential.scala
new file mode 100644
index 0000000000..4cdaa44a83
--- /dev/null
+++ b/test/files/run/valueclasses-typetag-existential.scala
@@ -0,0 +1,5 @@
+class Foo[T](val x: T) extends AnyVal
+
+object Test extends App {
+ println(scala.reflect.runtime.universe.typeOf[Foo[_]])
+} \ No newline at end of file
diff --git a/test/files/run/valueclasses-typetag-generic.check b/test/files/run/valueclasses-typetag-generic.check
new file mode 100644
index 0000000000..fce2e64f79
--- /dev/null
+++ b/test/files/run/valueclasses-typetag-generic.check
@@ -0,0 +1 @@
+Foo[String]
diff --git a/test/files/run/valueclasses-typetag-generic.scala b/test/files/run/valueclasses-typetag-generic.scala
new file mode 100644
index 0000000000..eb32dfcadb
--- /dev/null
+++ b/test/files/run/valueclasses-typetag-generic.scala
@@ -0,0 +1,5 @@
+class Foo[T](val x: T) extends AnyVal
+
+object Test extends App {
+ println(scala.reflect.runtime.universe.typeOf[Foo[String]])
+} \ No newline at end of file
diff --git a/test/files/specialized/t6035.check b/test/files/specialized/t6035.check
new file mode 100644
index 0000000000..573541ac97
--- /dev/null
+++ b/test/files/specialized/t6035.check
@@ -0,0 +1 @@
+0
diff --git a/test/files/specialized/t6035/first_1.scala b/test/files/specialized/t6035/first_1.scala
new file mode 100644
index 0000000000..1289e9f48e
--- /dev/null
+++ b/test/files/specialized/t6035/first_1.scala
@@ -0,0 +1,5 @@
+trait Foo[@specialized(Int) A] {
+ def foo(x: A): A
+}
+
+abstract class Inter extends Foo[Int]
diff --git a/test/files/specialized/t6035/second_2.scala b/test/files/specialized/t6035/second_2.scala
new file mode 100644
index 0000000000..fb317e2a6a
--- /dev/null
+++ b/test/files/specialized/t6035/second_2.scala
@@ -0,0 +1,13 @@
+class Baz extends Inter {
+ def foo(x: Int) = x + 1
+}
+
+object Test {
+ def main(args: Array[String]) {
+ // it's important that the type is Inter so we do not call Baz.foo(I)I directly!
+ val baz: Inter = new Baz
+ // here we should go through specialized version of foo and thus have zero boxing
+ baz.foo(1)
+ println(runtime.BoxesRunTime.integerBoxCount)
+ }
+}
diff --git a/test/files/pos/t1751.cmds b/test/pending/pos/t1751.cmds
index d4a4898ffd..d4a4898ffd 100644
--- a/test/files/pos/t1751.cmds
+++ b/test/pending/pos/t1751.cmds
diff --git a/test/files/pos/t1751/A1_2.scala b/test/pending/pos/t1751/A1_2.scala
index 354d5eecd0..354d5eecd0 100644
--- a/test/files/pos/t1751/A1_2.scala
+++ b/test/pending/pos/t1751/A1_2.scala
diff --git a/test/files/pos/t1751/A2_1.scala b/test/pending/pos/t1751/A2_1.scala
index c768062e43..c768062e43 100644
--- a/test/files/pos/t1751/A2_1.scala
+++ b/test/pending/pos/t1751/A2_1.scala
diff --git a/test/files/pos/t1751/SuiteClasses.java b/test/pending/pos/t1751/SuiteClasses.java
index a415e4f572..a415e4f572 100644
--- a/test/files/pos/t1751/SuiteClasses.java
+++ b/test/pending/pos/t1751/SuiteClasses.java
diff --git a/test/files/pos/t1782.cmds b/test/pending/pos/t1782.cmds
index 61f3d3788e..61f3d3788e 100644
--- a/test/files/pos/t1782.cmds
+++ b/test/pending/pos/t1782.cmds
diff --git a/test/files/pos/t1782/Ann.java b/test/pending/pos/t1782/Ann.java
index 0dcfbd2ed7..0dcfbd2ed7 100644
--- a/test/files/pos/t1782/Ann.java
+++ b/test/pending/pos/t1782/Ann.java
diff --git a/test/files/pos/t1782/Days.java b/test/pending/pos/t1782/Days.java
index 203a87b1c2..203a87b1c2 100644
--- a/test/files/pos/t1782/Days.java
+++ b/test/pending/pos/t1782/Days.java
diff --git a/test/files/pos/t1782/ImplementedBy.java b/test/pending/pos/t1782/ImplementedBy.java
index 6aa8b4fa9e..6aa8b4fa9e 100644
--- a/test/files/pos/t1782/ImplementedBy.java
+++ b/test/pending/pos/t1782/ImplementedBy.java
diff --git a/test/files/pos/t1782/Test_1.scala b/test/pending/pos/t1782/Test_1.scala
index 6467a74c29..6467a74c29 100644
--- a/test/files/pos/t1782/Test_1.scala
+++ b/test/pending/pos/t1782/Test_1.scala
diff --git a/test/files/pos/t294.cmds b/test/pending/pos/t294.cmds
index 62c9a5a068..62c9a5a068 100644
--- a/test/files/pos/t294.cmds
+++ b/test/pending/pos/t294.cmds
diff --git a/test/files/pos/t294/Ann.java b/test/pending/pos/t294/Ann.java
index 934ca46297..934ca46297 100644
--- a/test/files/pos/t294/Ann.java
+++ b/test/pending/pos/t294/Ann.java
diff --git a/test/files/pos/t294/Ann2.java b/test/pending/pos/t294/Ann2.java
index 025b79e794..025b79e794 100644
--- a/test/files/pos/t294/Ann2.java
+++ b/test/pending/pos/t294/Ann2.java
diff --git a/test/files/pos/t294/Test_1.scala b/test/pending/pos/t294/Test_1.scala
index ff1f34b10e..ff1f34b10e 100644
--- a/test/files/pos/t294/Test_1.scala
+++ b/test/pending/pos/t294/Test_1.scala
diff --git a/test/files/pos/t294/Test_2.scala b/test/pending/pos/t294/Test_2.scala
index 9fb1c6e175..9fb1c6e175 100644
--- a/test/files/pos/t294/Test_2.scala
+++ b/test/pending/pos/t294/Test_2.scala
diff --git a/test/files/run/t3897.check b/test/pending/run/t3897.check
index 244b83716f..244b83716f 100644
--- a/test/files/run/t3897.check
+++ b/test/pending/run/t3897.check
diff --git a/test/files/run/t3897/J_2.java b/test/pending/run/t3897/J_2.java
index 178412dc92..178412dc92 100644
--- a/test/files/run/t3897/J_2.java
+++ b/test/pending/run/t3897/J_2.java
diff --git a/test/files/run/t3897/a_1.scala b/test/pending/run/t3897/a_1.scala
index 4da959e2ac..4da959e2ac 100644
--- a/test/files/run/t3897/a_1.scala
+++ b/test/pending/run/t3897/a_1.scala
diff --git a/test/files/run/t3897/a_2.scala b/test/pending/run/t3897/a_2.scala
index 4d9e59ef05..4d9e59ef05 100644
--- a/test/files/run/t3897/a_2.scala
+++ b/test/pending/run/t3897/a_2.scala
diff --git a/test/files/run/t5293-map.scala b/test/pending/run/t5293-map.scala
index 2707aed07e..2707aed07e 100644
--- a/test/files/run/t5293-map.scala
+++ b/test/pending/run/t5293-map.scala
diff --git a/test/files/run/t5293.scala b/test/pending/run/t5293.scala
index 01ead45d2a..01ead45d2a 100644
--- a/test/files/run/t5293.scala
+++ b/test/pending/run/t5293.scala
diff --git a/test/pending/run/t5695.check b/test/pending/run/t5695.check
deleted file mode 100644
index d50069ab4f..0000000000
--- a/test/pending/run/t5695.check
+++ /dev/null
@@ -1,2 +0,0 @@
-..
-..
diff --git a/test/pending/run/t5695/part_1.scala b/test/pending/run/t5695/part_1.scala
deleted file mode 100644
index b8e8f8e52f..0000000000
--- a/test/pending/run/t5695/part_1.scala
+++ /dev/null
@@ -1,12 +0,0 @@
-import language.experimental.macros
-import scala.reflect.makro.Context
-
-object Defs {
-
- def mkInt = macro mkIntImpl
- def mkIntImpl(c: Context): c.Expr[Any] = {
- println(c.enclosingApplication)
- c.reify{ 23 }
- }
-
-}
diff --git a/test/pending/run/t5695/part_2.scala b/test/pending/run/t5695/part_2.scala
deleted file mode 100644
index d34219437d..0000000000
--- a/test/pending/run/t5695/part_2.scala
+++ /dev/null
@@ -1,8 +0,0 @@
-import Defs._
-
-object Test extends App {
-
- val i1 = mkInt
- val i2 = identity(mkInt)
-
-}