summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xbuild.xml82
-rw-r--r--src/compiler/scala/reflect/reify/codegen/GenTrees.scala37
-rw-r--r--src/compiler/scala/tools/nsc/Global.scala2
-rw-r--r--src/compiler/scala/tools/nsc/settings/ScalaSettings.scala6
-rw-r--r--src/compiler/scala/tools/nsc/symtab/classfile/Pickler.scala852
-rw-r--r--src/compiler/scala/tools/nsc/transform/Erasure.scala136
-rw-r--r--src/compiler/scala/tools/nsc/transform/OverridingPairs.scala224
-rw-r--r--src/compiler/scala/tools/nsc/transform/UnCurry.scala5
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Contexts.scala1
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Infer.scala9
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Namers.scala5
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/RefChecks.scala150
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/TreeCheckers.scala8
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Typers.scala296
-rw-r--r--src/reflect/scala/reflect/api/Trees.scala28
-rw-r--r--src/reflect/scala/reflect/internal/AnnotationInfos.scala2
-rw-r--r--src/reflect/scala/reflect/internal/Definitions.scala114
-rw-r--r--src/reflect/scala/reflect/internal/Kinds.scala1
-rw-r--r--src/reflect/scala/reflect/internal/Scopes.scala4
-rw-r--r--src/reflect/scala/reflect/internal/SymbolPairs.scala302
-rw-r--r--src/reflect/scala/reflect/internal/SymbolTable.scala5
-rw-r--r--src/reflect/scala/reflect/internal/Symbols.scala6
-rw-r--r--src/reflect/scala/reflect/internal/Trees.scala277
-rw-r--r--src/reflect/scala/reflect/internal/Types.scala122
-rw-r--r--src/reflect/scala/reflect/internal/Variances.scala3
-rw-r--r--src/reflect/scala/reflect/internal/pickling/Translations.scala128
-rw-r--r--src/reflect/scala/reflect/internal/pickling/UnPickler.scala510
-rw-r--r--src/reflect/scala/reflect/internal/settings/MutableSettings.scala25
-rw-r--r--src/reflect/scala/reflect/internal/tpe/TypeComparers.scala2
-rw-r--r--src/reflect/scala/reflect/internal/tpe/TypeMaps.scala7
-rw-r--r--src/reflect/scala/reflect/runtime/Settings.scala5
-rw-r--r--test/files/jvm/deprecation.check2
-rw-r--r--test/files/neg/accesses.check6
-rw-r--r--test/files/neg/accesses2.check4
-rw-r--r--test/files/neg/accesses2.scala11
-rw-r--r--test/files/neg/any-vs-anyref.check18
-rw-r--r--test/files/neg/applydynamic_sip.check17
-rw-r--r--test/files/neg/macro-basic-mamdmi.check4
-rw-r--r--test/files/neg/names-defaults-neg.check16
-rw-r--r--test/files/neg/reflection-names-neg.check5
-rw-r--r--test/files/neg/sammy_restrictions.check49
-rw-r--r--test/files/neg/sammy_restrictions.flags1
-rw-r--r--test/files/neg/sammy_restrictions.scala45
-rw-r--r--test/files/neg/sammy_wrong_arity.check52
-rw-r--r--test/files/neg/sammy_wrong_arity.flags1
-rw-r--r--test/files/neg/sammy_wrong_arity.scala22
-rw-r--r--test/files/neg/t0259.check4
-rw-r--r--test/files/neg/t0418.check5
-rw-r--r--test/files/neg/t3653.check6
-rw-r--r--test/files/neg/t418.check5
-rw-r--r--test/files/neg/t4515.check12
-rw-r--r--test/files/neg/t512.check5
-rw-r--r--test/files/neg/t545.check5
-rw-r--r--test/files/neg/t556.check5
-rw-r--r--test/files/neg/t5572.check7
-rw-r--r--test/files/neg/t5761.check5
-rw-r--r--test/files/neg/t588.check10
-rw-r--r--test/files/neg/t5903a.check5
-rw-r--r--test/files/neg/t5903b.check5
-rw-r--r--test/files/neg/t5903c.check5
-rw-r--r--test/files/neg/t5903d.check5
-rw-r--r--test/files/neg/t6443c.check4
-rw-r--r--test/files/neg/t663.check6
-rw-r--r--test/files/neg/t6829.check22
-rw-r--r--test/files/neg/t7239.check4
-rw-r--r--test/files/neg/t7239.scala12
-rw-r--r--test/files/neg/t7783.check18
-rw-r--r--test/files/neg/t7783.flags1
-rw-r--r--test/files/neg/t7783.scala15
-rw-r--r--test/files/neg/t7895.check4
-rw-r--r--test/files/neg/t7895.scala6
-rw-r--r--test/files/neg/t7895b.check7
-rw-r--r--test/files/neg/t7895b.scala5
-rw-r--r--test/files/neg/t7895c.check13
-rw-r--r--test/files/neg/t7895c.scala3
-rw-r--r--test/files/neg/t7899.check6
-rw-r--r--test/files/neg/t7899.scala7
-rw-r--r--test/files/neg/t997.check5
-rw-r--r--test/files/neg/typeerror.check7
-rw-r--r--test/files/neg/valueclasses-doubledefs.check4
-rw-r--r--test/files/neg/valueclasses-pavlov.check4
-rw-r--r--test/files/pos/sammy_poly.flags1
-rw-r--r--test/files/pos/sammy_poly.scala7
-rw-r--r--test/files/pos/sammy_scope.flags1
-rw-r--r--test/files/pos/sammy_scope.scala8
-rw-r--r--test/files/pos/sammy_single.flags1
-rw-r--r--test/files/pos/sammy_single.scala9
-rw-r--r--test/files/pos/sammy_twice.flags1
-rw-r--r--test/files/pos/sammy_twice.scala9
-rw-r--r--test/files/pos/t6221.scala8
-rw-r--r--test/files/pos/t7584.scala11
-rw-r--r--test/files/pos/t7688.scala7
-rw-r--r--test/files/pos/t7902.scala17
-rw-r--r--test/files/res/t687.check6
-rw-r--r--test/files/run/constrained-types.check9
-rw-r--r--test/files/run/macro-vampire-false-warning.check2
-rw-r--r--test/files/run/macro-vampire-false-warning.flags1
-rw-r--r--test/files/run/macro-vampire-false-warning/Macros_1.scala52
-rw-r--r--test/files/run/macro-vampire-false-warning/Test_2.scala6
-rw-r--r--test/files/run/private-override.check1
-rw-r--r--test/files/run/private-override.scala17
-rw-r--r--test/files/run/repl-reset.check6
-rw-r--r--test/files/run/sammy_java8.flags1
-rw-r--r--test/files/run/sammy_java8.scala34
-rw-r--r--test/files/run/t4542.check3
-rw-r--r--test/files/run/t7398.scala2
-rw-r--r--test/files/run/t7584b.scala14
-rw-r--r--test/files/run/t7899-regression.check1
-rw-r--r--test/files/run/t7899-regression.flags1
-rw-r--r--test/files/run/t7899-regression.scala24
-rw-r--r--test/files/run/t7899.scala5
111 files changed, 2288 insertions, 1826 deletions
diff --git a/build.xml b/build.xml
index b5e77832df..cb159b6c9e 100755
--- a/build.xml
+++ b/build.xml
@@ -1186,44 +1186,46 @@ TODO:
<staged-uptodate stage="docs" project="@{project}">
<check><srcfiles dir="${src.dir}/@{dir}"/></check>
<do>
- <stopwatch name="docs.@{project}.timer"/>
- <mkdir dir="${build-docs.dir}/@{project}"/>
- <if><equals arg1="@{docroot}" arg2="NOT SET"/><then>
- <!-- TODO: introduce docs.@{project}.build.path for classpathref -->
- <scaladoc
- destdir="${build-docs.dir}/@{project}"
- doctitle="@{title}"
- docversion="${version.number}"
- sourcepath="${src.dir}"
- classpathref="docs.compiler.path"
- srcdir="${src.dir}/@{dir}"
- addparams="${scalac.args.all}"
- implicits="on"
- diagrams="on"
- groups="on"
- rawOutput="${scaladoc.raw.output}"
- noPrefixes="${scaladoc.no.prefixes}">
- <includes/>
- </scaladoc>
- </then><else>
- <scaladoc
- destdir="${build-docs.dir}/@{project}"
- doctitle="@{title}"
- docversion="${version.number}"
- sourcepath="${src.dir}"
- classpathref="docs.compiler.path"
- srcdir="${src.dir}/@{dir}"
- docRootContent="${src.dir}/@{project}/@{docroot}"
- addparams="${scalac.args.all}"
- implicits="on"
- diagrams="on"
- groups="on"
- rawOutput="${scaladoc.raw.output}"
- noPrefixes="${scaladoc.no.prefixes}">
- <includes/>
- </scaladoc>
- </else></if>
- <stopwatch name="docs.@{project}.timer" action="total"/>
+ <if><not><isset property="docs.skip"/></not><then>
+ <stopwatch name="docs.@{project}.timer"/>
+ <mkdir dir="${build-docs.dir}/@{project}"/>
+ <if><equals arg1="@{docroot}" arg2="NOT SET"/><then>
+ <!-- TODO: introduce docs.@{project}.build.path for classpathref -->
+ <scaladoc
+ destdir="${build-docs.dir}/@{project}"
+ doctitle="@{title}"
+ docversion="${version.number}"
+ sourcepath="${src.dir}"
+ classpathref="docs.compiler.path"
+ srcdir="${src.dir}/@{dir}"
+ addparams="${scalac.args.all}"
+ implicits="on"
+ diagrams="on"
+ groups="on"
+ rawOutput="${scaladoc.raw.output}"
+ noPrefixes="${scaladoc.no.prefixes}">
+ <includes/>
+ </scaladoc>
+ </then><else>
+ <scaladoc
+ destdir="${build-docs.dir}/@{project}"
+ doctitle="@{title}"
+ docversion="${version.number}"
+ sourcepath="${src.dir}"
+ classpathref="docs.compiler.path"
+ srcdir="${src.dir}/@{dir}"
+ docRootContent="${src.dir}/@{project}/@{docroot}"
+ addparams="${scalac.args.all}"
+ implicits="on"
+ diagrams="on"
+ groups="on"
+ rawOutput="${scaladoc.raw.output}"
+ noPrefixes="${scaladoc.no.prefixes}">
+ <includes/>
+ </scaladoc>
+ </else></if>
+ <stopwatch name="docs.@{project}.timer" action="total"/>
+ </then></if>
</do>
</staged-uptodate>
</sequential>
@@ -1623,7 +1625,7 @@ TODO:
</target>
<!-- See test/build-partest.xml for the macro(s) being used here. -->
- <target name="partest.task" depends="init,pack.done">
+ <target name="partest.task" depends="pack.done">
<!-- note the classpathref! this is the classpath used to run partest,
so it must have the new compiler.... -->
<taskdef
@@ -1631,7 +1633,7 @@ TODO:
resource="scala/tools/partest/antlib.xml"/>
</target>
- <target name="test.suite.init" depends="pack.done, partest.task">
+ <target name="test.suite.init" depends="partest.task">
<!-- read by test/partest to determine classpath used to run partest -->
<propertyfile file = "build/pack/partest.properties">
<entry key = "partest.classpath" value="${toString:partest.compilation.path}"/>
diff --git a/src/compiler/scala/reflect/reify/codegen/GenTrees.scala b/src/compiler/scala/reflect/reify/codegen/GenTrees.scala
index a09acc04b8..f6b3c42ca9 100644
--- a/src/compiler/scala/reflect/reify/codegen/GenTrees.scala
+++ b/src/compiler/scala/reflect/reify/codegen/GenTrees.scala
@@ -41,17 +41,12 @@ trait GenTrees {
// the first prototype of reification reified all types and symbols for all trees => this quickly became unyieldy
// the second prototype reified external types, but avoided reifying local ones => this created an ugly irregularity
// current approach is uniform and compact
- var rtree = tree match {
- case FreeDef(_, _, _, _, _) =>
- reifyNestedFreeDef(tree)
- case FreeRef(_, _) =>
- reifyNestedFreeRef(tree)
- case BoundTerm(tree) =>
- reifyBoundTerm(tree)
- case BoundType(tree) =>
- reifyBoundType(tree)
- case _ =>
- reifyTreeSyntactically(tree)
+ var rtree: Tree = tree match {
+ case FreeDef(_, _, _, _, _) => reifyNestedFreeDef(tree)
+ case FreeRef(_, _) => reifyNestedFreeRef(tree)
+ case BoundTerm(tree) => reifyBoundTerm(tree)
+ case BoundType(tree) => reifyBoundType(tree)
+ case _ => reifyTreeSyntactically(tree)
}
// usually we don't reify symbols/types, because they can be re-inferred during subsequent reflective compilation
@@ -68,19 +63,13 @@ trait GenTrees {
rtree
}
- def reifyTreeSyntactically(tree: Tree) = tree match {
- case global.EmptyTree =>
- reifyMirrorObject(EmptyTree)
- case global.noSelfType =>
- mirrorSelect(nme.noSelfType)
- case global.pendingSuperCall =>
- mirrorSelect(nme.pendingSuperCall)
- case Literal(const @ Constant(_)) =>
- mirrorCall(nme.Literal, reifyProduct(const))
- case Import(expr, selectors) =>
- mirrorCall(nme.Import, reify(expr), mkList(selectors map reifyProduct))
- case _ =>
- reifyProduct(tree)
+ def reifyTreeSyntactically(tree: Tree): Tree = tree match {
+ case global.EmptyTree => reifyMirrorObject(EmptyTree)
+ case global.noSelfType => mirrorSelect(nme.noSelfType)
+ case global.pendingSuperCall => mirrorSelect(nme.pendingSuperCall)
+ case Literal(const @ Constant(_)) => mirrorCall(nme.Literal, reifyProduct(const))
+ case Import(expr, selectors) => mirrorCall(nme.Import, reify(expr), mkList(selectors map reifyProduct))
+ case _ => reifyProduct(tree)
}
def reifyFlags(flags: FlagSet) =
diff --git a/src/compiler/scala/tools/nsc/Global.scala b/src/compiler/scala/tools/nsc/Global.scala
index 92bfe6e0fe..1cd3e0ec4b 100644
--- a/src/compiler/scala/tools/nsc/Global.scala
+++ b/src/compiler/scala/tools/nsc/Global.scala
@@ -135,6 +135,8 @@ class Global(var currentSettings: Settings, var reporter: Reporter)
val global: Global.this.type = Global.this
} with OverridingPairs
+ type SymbolPair = overridingPairs.SymbolPair
+
// Optimizer components
/** ICode analysis for optimization */
diff --git a/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala b/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala
index 1f80aa4b6f..01d5791f60 100644
--- a/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala
+++ b/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala
@@ -176,8 +176,8 @@ trait ScalaSettings extends AbsScalaSettings
val Yreplsync = BooleanSetting ("-Yrepl-sync", "Do not use asynchronous code for repl startup")
val Yreploutdir = StringSetting ("-Yrepl-outdir", "path", "Write repl-generated classfiles to given output directory (use \"\" to generate a temporary dir)" , "")
val YmethodInfer = BooleanSetting ("-Yinfer-argument-types", "Infer types for arguments of overriden methods.")
- val etaExpandKeepsStar = BooleanSetting ("-Yeta-expand-keeps-star", "Eta-expand varargs methods to T* rather than Seq[T]. This is a temporary option to ease transition.").
- withDeprecationMessage("This flag is scheduled for removal in 2.12. If you have a case where you need this flag then please report a bug.")
+ val etaExpandKeepsStar = BooleanSetting ("-Yeta-expand-keeps-star", "Eta-expand varargs methods to T* rather than Seq[T]. This is a temporary option to ease transition.").withDeprecationMessage(removalIn212)
+ val inferByName = BooleanSetting ("-Yinfer-by-name", "Allow inference of by-name types. This is a temporary option to ease transition. See SI-7899.").withDeprecationMessage(removalIn212)
val Yinvalidate = StringSetting ("-Yinvalidate", "classpath-entry", "Invalidate classpath entry before run", "")
val YvirtClasses = false // too embryonic to even expose as a -Y //BooleanSetting ("-Yvirtual-classes", "Support virtual classes")
val YdisableUnreachablePrevention = BooleanSetting("-Ydisable-unreachable-prevention", "Disable the prevention of unreachable blocks in code generation.")
@@ -185,6 +185,8 @@ trait ScalaSettings extends AbsScalaSettings
val exposeEmptyPackage = BooleanSetting("-Yexpose-empty-package", "Internal only: expose the empty package.").internalOnly()
+ private def removalIn212 = "This flag is scheduled for removal in 2.12. If you have a case where you need this flag then please report a bug."
+
/** Area-specific debug output.
*/
val Ydocdebug = BooleanSetting("-Ydoc-debug", "Trace all scaladoc activity.")
diff --git a/src/compiler/scala/tools/nsc/symtab/classfile/Pickler.scala b/src/compiler/scala/tools/nsc/symtab/classfile/Pickler.scala
index 9ac1ce1b9c..ce3e7b1bb5 100644
--- a/src/compiler/scala/tools/nsc/symtab/classfile/Pickler.scala
+++ b/src/compiler/scala/tools/nsc/symtab/classfile/Pickler.scala
@@ -11,6 +11,7 @@ import java.lang.Float.floatToIntBits
import java.lang.Double.doubleToLongBits
import scala.io.Codec
import scala.reflect.internal.pickling.{ PickleBuffer, PickleFormat }
+import scala.reflect.internal.util.shortClassOfInstance
import scala.collection.mutable.LinkedHashMap
import PickleFormat._
import Flags._
@@ -80,7 +81,7 @@ abstract class Pickler extends SubComponent {
private var entries = new Array[AnyRef](256)
private var ep = 0
private val index = new LinkedHashMap[AnyRef, Int]
- private lazy val nonClassRoot = findOrElse(root.ownersIterator)(!_.isClass)(NoSymbol)
+ private lazy val nonClassRoot = findSymbol(root.ownersIterator)(!_.isClass)
private def isRootSym(sym: Symbol) =
sym.name.toTermName == rootName && sym.owner == rootOwner
@@ -106,13 +107,14 @@ abstract class Pickler extends SubComponent {
* anyway? This is the case if symbol is a refinement class,
* an existentially bound variable, or a higher-order type parameter.
*/
- private def isLocal(sym: Symbol): Boolean =
- !sym.isPackageClass && sym != NoSymbol &&
- (isRootSym(sym) ||
- sym.isRefinementClass ||
- sym.isAbstractType && sym.hasFlag(EXISTENTIAL) || // existential param
- sym.isParameter ||
- isLocal(sym.owner))
+ private def isLocal(sym: Symbol): Boolean = (sym != NoSymbol) && !sym.isPackageClass && (
+ isRootSym(sym)
+ || sym.isRefinementClass
+ || sym.isAbstractType && sym.hasFlag(EXISTENTIAL) // existential param
+ || sym.isParameter
+ || isLocal(sym.owner)
+ )
+ private def isExternalSymbol(sym: Symbol): Boolean = (sym != NoSymbol) && !isLocal(sym)
// Phase 1 methods: Populate entries/index ------------------------------------
@@ -135,13 +137,18 @@ abstract class Pickler extends SubComponent {
true
}
+ private def deskolemizeTypeSymbols(ref: AnyRef): AnyRef = ref match {
+ case sym: Symbol => deskolemize(sym)
+ case _ => ref
+ }
+
/** If the symbol is a type skolem, deskolemize and log it.
* If we fail to deskolemize, in a method like
* trait Trait[+A] { def f[CC[X]] : CC[A] }
* the applied type CC[A] will hold a different CC symbol
* than the type-constructor type-parameter CC.
*/
- private def deskolemize(sym: Symbol) = {
+ private def deskolemize(sym: Symbol): Symbol = {
if (sym.isTypeSkolem) {
val sym1 = sym.deSkolemize
log({
@@ -169,7 +176,7 @@ abstract class Pickler extends SubComponent {
putSymbol(sym.owner)
putSymbol(sym.privateWithin)
putType(sym.info)
- if (sym.thisSym.tpeHK != sym.tpeHK)
+ if (sym.hasSelfType)
putType(sym.typeOfThis)
putSymbol(sym.alias)
if (!sym.children.isEmpty) {
@@ -202,252 +209,65 @@ abstract class Pickler extends SubComponent {
case ThisType(sym) =>
putSymbol(sym)
case SingleType(pre, sym) =>
- putType(pre); putSymbol(sym)
+ putType(pre)
+ putSymbol(sym)
case SuperType(thistpe, supertpe) =>
putType(thistpe)
putType(supertpe)
case ConstantType(value) =>
putConstant(value)
case TypeRef(pre, sym, args) =>
-// if (sym.isAbstractType && (sym hasFlag EXISTENTIAL))
-// if (!(boundSyms contains sym))
-// println("unbound existential: "+sym+sym.locationString)
- putType(pre); putSymbol(sym); putTypes(args)
+ putType(pre)
+ putSymbol(sym)
+ putTypes(args)
case TypeBounds(lo, hi) =>
- putType(lo); putType(hi)
- case RefinedType(parents, decls) =>
- val rclazz = tp.typeSymbol
- for (m <- decls.iterator)
- if (m.owner != rclazz) abort("bad refinement member "+m+" of "+tp+", owner = "+m.owner)
- putSymbol(rclazz); putTypes(parents); putSymbols(decls.toList)
- case ClassInfoType(parents, decls, clazz) =>
- putSymbol(clazz); putTypes(parents); putSymbols(decls.toList)
+ putType(lo)
+ putType(hi)
+ case tp: CompoundType =>
+ putSymbol(tp.typeSymbol)
+ putTypes(tp.parents)
+ putSymbols(tp.decls.toList)
case MethodType(params, restpe) =>
- putType(restpe); putSymbols(params)
+ putType(restpe)
+ putSymbols(params)
case NullaryMethodType(restpe) =>
putType(restpe)
case PolyType(tparams, restpe) =>
- /* no longer needed since all params are now local
- tparams foreach { tparam =>
- if (!isLocal(tparam)) locals += tparam // similar to existential types, these tparams are local
- }
- */
- putType(restpe); putSymbols(tparams)
+ putType(restpe)
+ putSymbols(tparams)
case ExistentialType(tparams, restpe) =>
-// val savedBoundSyms = boundSyms // boundSyms are known to be local based on the EXISTENTIAL flag (see isLocal)
-// boundSyms = tparams ::: boundSyms
-// try {
- putType(restpe)
- // } finally {
-// boundSyms = savedBoundSyms
-// }
+ putType(restpe)
putSymbols(tparams)
- case AnnotatedType(annotations, underlying, selfsym) =>
+ case AnnotatedType(_, underlying, selfsym) =>
putType(underlying)
if (settings.selfInAnnots) putSymbol(selfsym)
- putAnnotations(annotations filter (_.isStatic))
+ tp.staticAnnotations foreach putAnnotation
case _ =>
throw new FatalError("bad type: " + tp + "(" + tp.getClass + ")")
}
}
private def putTypes(tps: List[Type]) { tps foreach putType }
- private def putTree(tree: Tree): Unit = if (putEntry(tree)) {
- if (tree != EmptyTree)
- putType(tree.tpe)
- if (tree.hasSymbolField)
- putSymbol(tree.symbol)
-
- tree match {
- case EmptyTree =>
-
- case tree@PackageDef(pid, stats) =>
- putTree(pid)
- putTrees(stats)
-
- case ClassDef(mods, name, tparams, impl) =>
- putMods(mods)
- putEntry(name)
- putTree(impl)
- putTrees(tparams)
-
- case ModuleDef(mods, name, impl) =>
- putMods(mods)
- putEntry(name)
- putTree(impl)
-
- case ValDef(mods, name, tpt, rhs) =>
- putMods(mods)
- putEntry(name)
- putTree(tpt)
- putTree(rhs)
-
- case DefDef(mods, name, tparams, vparamss, tpt, rhs) =>
- putMods(mods)
- putEntry(name)
- putTrees(tparams)
- putTreess(vparamss)
- putTree(tpt)
- putTree(rhs)
-
- case TypeDef(mods, name, tparams, rhs) =>
- putMods(mods)
- putEntry(name)
- putTree(rhs)
- putTrees(tparams)
-
- case LabelDef(name, params, rhs) =>
- putEntry(name)
- putTree(rhs)
- putTrees(params)
-
- case Import(expr, selectors) =>
- putTree(expr)
- for (ImportSelector(from, _, to, _) <- selectors) {
- putEntry(from)
- putEntry(to)
- }
-/*
- case DocDef(comment, definition) => should not be needed
- putConstant(Constant(comment))
- putTree(definition)
-*/
- case Template(parents, self, body) =>
- putTrees(parents)
- putTree(self)
- putTrees(body)
-
- case Block(stats, expr) =>
- putTree(expr)
- putTrees(stats)
-
- case CaseDef(pat, guard, body) =>
- putTree(pat)
- putTree(guard)
- putTree(body)
-
- case Alternative(trees) =>
- putTrees(trees)
-
- case Star(elem) =>
- putTree(elem)
-
- case Bind(name, body) =>
- putEntry(name)
- putTree(body)
-
- case UnApply(fun: Tree, args) =>
- putTree(fun)
- putTrees(args)
-
- case ArrayValue(elemtpt, trees) =>
- putTree(elemtpt)
- putTrees(trees)
-
-
- case Function(vparams, body) =>
- putTree(body)
- putTrees(vparams)
-
- case Assign(lhs, rhs) =>
- putTree(lhs)
- putTree(rhs)
-
- case If(cond, thenp, elsep) =>
- putTree(cond)
- putTree(thenp)
- putTree(elsep)
-
- case Match(selector, cases) =>
- putTree(selector)
- putTrees(cases)
-
- case Return(expr) =>
- putTree(expr)
-
- case Try(block, catches, finalizer) =>
- putTree(block)
- putTree(finalizer)
- putTrees(catches)
-
- case Throw(expr) =>
- putTree(expr)
-
- case New(tpt) =>
- putTree(tpt)
-
- case Typed(expr, tpt) =>
- putTree(expr)
- putTree(tpt)
-
- case TypeApply(fun, args) =>
- putTree(fun)
- putTrees(args)
-
- case Apply(fun, args) =>
- putTree(fun)
- putTrees(args)
-
- case ApplyDynamic(qual, args) =>
- putTree(qual)
- putTrees(args)
-
- case Super(qual, mix) =>
- putTree(qual)
- putEntry(mix:Name)
-
- case This(qual) =>
- putEntry(qual)
-
- case Select(qualifier, selector) =>
- putTree(qualifier)
- putEntry(selector)
-
- case Ident(name) =>
- putEntry(name)
-
- case Literal(value) =>
- putEntry(value)
-
- case TypeTree() =>
-
- case Annotated(annot, arg) =>
- putTree(annot)
- putTree(arg)
-
- case SingletonTypeTree(ref) =>
- putTree(ref)
-
- case SelectFromTypeTree(qualifier, selector) =>
- putTree(qualifier)
- putEntry(selector)
-
- case CompoundTypeTree(templ: Template) =>
- putTree(templ)
-
- case AppliedTypeTree(tpt, args) =>
- putTree(tpt)
- putTrees(args)
-
- case TypeBoundsTree(lo, hi) =>
- putTree(lo)
- putTree(hi)
-
- case ExistentialTypeTree(tpt, whereClauses) =>
- putTree(tpt)
- putTrees(whereClauses)
+ private object putTreeTraverser extends Traverser {
+ // Only used when pickling trees, i.e. in an argument of some Annotation
+ // annotations in Modifiers are removed by the typechecker
+ override def traverseModifiers(mods: Modifiers): Unit = if (putEntry(mods)) putEntry(mods.privateWithin)
+ override def traverseName(name: Name): Unit = putEntry(name)
+ override def traverseConstant(const: Constant): Unit = putEntry(const)
+ override def traverse(tree: Tree): Unit = putTree(tree)
+
+ def put(tree: Tree): Unit = {
+ if (tree.canHaveAttrs)
+ putType(tree.tpe)
+ if (tree.hasSymbolField)
+ putSymbol(tree.symbol)
+
+ super.traverse(tree)
}
}
-
- private def putTrees(trees: List[Tree]) = trees foreach putTree
- private def putTreess(treess: List[List[Tree]]) = treess foreach putTrees
-
- /** only used when pickling trees, i.e. in an
- * argument of some Annotation */
- private def putMods(mods: Modifiers) = if (putEntry(mods)) {
- // annotations in Modifiers are removed by the typechecker
- val Modifiers(_, privateWithin, Nil) = mods
- putEntry(privateWithin)
+ private def putTree(tree: Tree) {
+ if (putEntry(tree))
+ putTreeTraverser put tree
}
/** Store a constant in map index, along with anything it references.
@@ -461,7 +281,7 @@ abstract class Pickler extends SubComponent {
}
private def putChildren(sym: Symbol, children: List[Symbol]) {
- assert(putEntry((sym, children)))
+ putEntry(sym -> children)
children foreach putSymbol
}
@@ -469,14 +289,10 @@ abstract class Pickler extends SubComponent {
private def putAnnotation(sym: Symbol, annot: AnnotationInfo) {
// if an annotation with the same arguments is applied to the
// same symbol multiple times, it's only pickled once.
- if (putEntry((sym, annot)))
+ if (putEntry(sym -> annot))
putAnnotationBody(annot)
}
- /** used in AnnotatedType only, i.e. annotations on types */
- private def putAnnotations(annots: List[AnnotationInfo]) {
- annots foreach putAnnotation
- }
private def putAnnotation(annot: AnnotationInfo) {
if (putEntry(annot))
putAnnotationBody(annot)
@@ -510,14 +326,11 @@ abstract class Pickler extends SubComponent {
/** Write a reference to object, i.e., the object's number in the map index.
*/
- private def writeRef(ref0: AnyRef) {
- val ref = ref0 match {
- case sym: Symbol => deskolemize(sym)
- case _ => ref0
- }
- writeNat(index(ref))
+ private def writeRef(ref: AnyRef) {
+ writeNat(index(deskolemizeTypeSymbols(ref)))
}
- private def writeRefs(refs: List[AnyRef]) { refs foreach writeRef }
+ private def writeRefs(refs: List[AnyRef]): Unit = refs foreach writeRef
+
private def writeRefsWithLength(refs: List[AnyRef]) {
writeNat(refs.length)
writeRefs(refs)
@@ -567,446 +380,137 @@ abstract class Pickler extends SubComponent {
}
}
- /** Write an entry */
- private def writeEntry(entry: AnyRef) {
- def writeBody(entry: AnyRef): Int = entry match {
- case name: Name =>
- writeName(name)
- if (name.isTermName) TERMname else TYPEname
- case NoSymbol =>
- NONEsym
- case sym: Symbol if !isLocal(sym) =>
- val tag =
- if (sym.isModuleClass) {
- writeRef(sym.name.toTermName); EXTMODCLASSref
- } else {
- writeRef(sym.name); EXTref
- }
- if (!sym.owner.isRoot) writeRef(sym.owner)
- tag
- case sym: ClassSymbol =>
- writeSymInfo(sym)
- if (sym.thisSym.tpe_* != sym.tpe_*) writeRef(sym.typeOfThis)
- CLASSsym
- case sym: TypeSymbol =>
- writeSymInfo(sym)
- if (sym.isAbstractType) TYPEsym else ALIASsym
- case sym: TermSymbol =>
- writeSymInfo(sym)
- if (sym.alias != NoSymbol) writeRef(sym.alias)
- if (sym.isModule) MODULEsym else VALsym
- case NoType =>
- NOtpe
- case NoPrefix =>
- NOPREFIXtpe
- case ThisType(sym) =>
- writeRef(sym); THIStpe
- case SingleType(pre, sym) =>
- writeRef(pre); writeRef(sym); SINGLEtpe
- case SuperType(thistpe, supertpe) =>
- writeRef(thistpe); writeRef(supertpe); SUPERtpe
- case ConstantType(value) =>
- writeRef(value); CONSTANTtpe
- case TypeRef(pre, sym, args) =>
- writeRef(pre); writeRef(sym); writeRefs(args); TYPEREFtpe
- case TypeBounds(lo, hi) =>
- writeRef(lo); writeRef(hi); TYPEBOUNDStpe
- case tp @ RefinedType(parents, decls) =>
- writeRef(tp.typeSymbol); writeRefs(parents); REFINEDtpe
- case ClassInfoType(parents, decls, clazz) =>
- writeRef(clazz); writeRefs(parents); CLASSINFOtpe
- case mt @ MethodType(formals, restpe) =>
- writeRef(restpe); writeRefs(formals) ; METHODtpe
- case mt @ NullaryMethodType(restpe) =>
- // reuse POLYtpe since those can never have an empty list of tparams.
- // TODO: is there any way this can come back and bite us in the bottom?
- // ugliness and thrift aside, this should make this somewhat more backward compatible
- // (I'm not sure how old scalac's would deal with nested PolyTypes, as these used to be folded into one)
- writeRef(restpe); writeRefs(Nil); POLYtpe
- case PolyType(tparams, restpe) => // invar: tparams nonEmpty
- writeRef(restpe); writeRefs(tparams); POLYtpe
- case ExistentialType(tparams, restpe) =>
- writeRef(restpe); writeRefs(tparams); EXISTENTIALtpe
- case c @ Constant(_) =>
- if (c.tag == BooleanTag) writeLong(if (c.booleanValue) 1 else 0)
- else if (ByteTag <= c.tag && c.tag <= LongTag) writeLong(c.longValue)
- else if (c.tag == FloatTag) writeLong(floatToIntBits(c.floatValue).toLong)
- else if (c.tag == DoubleTag) writeLong(doubleToLongBits(c.doubleValue))
- else if (c.tag == StringTag) writeRef(newTermName(c.stringValue))
- else if (c.tag == ClazzTag) writeRef(c.typeValue)
- else if (c.tag == EnumTag) writeRef(c.symbolValue)
- LITERAL + c.tag // also treats UnitTag, NullTag; no value required
- case AnnotatedType(annotations, tp, selfsym) =>
- annotations filter (_.isStatic) match {
- case Nil => writeBody(tp) // write the underlying type if there are no annotations
- case staticAnnots =>
- if (settings.selfInAnnots && selfsym != NoSymbol)
- writeRef(selfsym)
- writeRef(tp)
- writeRefs(staticAnnots)
- ANNOTATEDtpe
- }
- // annotations attached to a symbol (i.e. annots on terms)
- case (target: Symbol, annot@AnnotationInfo(_, _, _)) =>
- writeRef(target)
- writeAnnotation(annot)
- SYMANNOT
-
- case ArrayAnnotArg(args) =>
- args foreach writeClassfileAnnotArg
- ANNOTARGARRAY
-
- case (target: Symbol, children: List[_]) =>
- writeRef(target)
- writeRefs(children.asInstanceOf[List[Symbol]])
- CHILDREN
-
- case EmptyTree =>
- writeNat(EMPTYtree)
- TREE
-
- case tree@PackageDef(pid, stats) =>
- writeNat(PACKAGEtree)
- writeRef(tree.tpe)
- writeRef(tree.symbol)
- writeRef(tree.mods)
- writeRef(pid)
- writeRefs(stats)
- TREE
-
- case tree@ClassDef(mods, name, tparams, impl) =>
- writeNat(CLASStree)
- writeRef(tree.tpe)
- writeRef(tree.symbol)
- writeRef(mods)
- writeRef(name)
- writeRef(impl)
- writeRefs(tparams)
- TREE
-
- case tree@ModuleDef(mods, name, impl) =>
- writeNat(MODULEtree)
- writeRef(tree.tpe)
- writeRef(tree.symbol)
- writeRef(mods)
- writeRef(name)
- writeRef(impl)
- TREE
-
- case tree@ValDef(mods, name, tpt, rhs) =>
- writeNat(VALDEFtree)
- writeRef(tree.tpe)
- writeRef(tree.symbol)
- writeRef(mods)
- writeRef(name)
- writeRef(tpt)
- writeRef(rhs)
- TREE
-
- case tree@DefDef(mods, name, tparams, vparamss, tpt, rhs) =>
- writeNat(DEFDEFtree)
- writeRef(tree.tpe)
- writeRef(tree.symbol)
- writeRef(mods)
- writeRef(name)
- writeRefsWithLength(tparams)
- writeNat(vparamss.length)
- vparamss foreach writeRefsWithLength
- writeRef(tpt)
- writeRef(rhs)
- TREE
-
- case tree@TypeDef(mods, name, tparams, rhs) =>
- writeNat(TYPEDEFtree)
- writeRef(tree.tpe)
- writeRef(tree.symbol)
- writeRef(mods)
- writeRef(name)
- writeRef(rhs)
- writeRefs(tparams)
- TREE
-
- case tree@LabelDef(name, params, rhs) =>
- writeNat(LABELtree)
- writeRef(tree.tpe)
- writeRef(tree.symbol)
- writeRef(name)
- writeRef(rhs)
- writeRefs(params)
- TREE
-
- case tree@Import(expr, selectors) =>
- writeNat(IMPORTtree)
- writeRef(tree.tpe)
- writeRef(tree.symbol)
- writeRef(expr)
- for (ImportSelector(from, _, to, _) <- selectors) {
- writeRef(from)
- writeRef(to)
- }
- TREE
-
- case tree@DocDef(comment, definition) =>
- writeNat(DOCDEFtree)
- writeRef(tree.tpe)
- writeRef(Constant(comment))
- writeRef(definition)
- TREE
-
- case tree@Template(parents, self, body) =>
- writeNat(TEMPLATEtree)
- writeRef(tree.tpe)
- writeRef(tree.symbol)
- writeRefsWithLength(parents)
- writeRef(self)
- writeRefs(body)
- TREE
-
- case tree@Block(stats, expr) =>
- writeNat(BLOCKtree)
- writeRef(tree.tpe)
- writeRef(expr)
- writeRefs(stats)
- TREE
-
- case tree@CaseDef(pat, guard, body) =>
- writeNat(CASEtree)
- writeRef(tree.tpe)
- writeRef(pat)
- writeRef(guard)
- writeRef(body)
- TREE
-
- case tree@Alternative(trees) =>
- writeNat(ALTERNATIVEtree)
- writeRef(tree.tpe)
- writeRefs(trees)
- TREE
-
- case tree@Star(elem) =>
- writeNat(STARtree)
- writeRef(tree.tpe)
- writeRef(elem)
- TREE
-
- case tree@Bind(name, body) =>
- writeNat(BINDtree)
- writeRef(tree.tpe)
- writeRef(tree.symbol)
- writeRef(name)
- writeRef(body)
- TREE
-
- case tree@UnApply(fun: Tree, args) =>
- writeNat(UNAPPLYtree)
- writeRef(tree.tpe)
- writeRef(fun)
- writeRefs(args)
- TREE
-
- case tree@ArrayValue(elemtpt, trees) =>
- writeNat(ARRAYVALUEtree)
- writeRef(tree.tpe)
- writeRef(elemtpt)
- writeRefs(trees)
- TREE
-
- case tree@Function(vparams, body) =>
- writeNat(FUNCTIONtree)
- writeRef(tree.tpe)
- writeRef(tree.symbol)
- writeRef(body)
- writeRefs(vparams)
- TREE
-
- case tree@Assign(lhs, rhs) =>
- writeNat(ASSIGNtree)
- writeRef(tree.tpe)
- writeRef(lhs)
- writeRef(rhs)
- TREE
-
- case tree@If(cond, thenp, elsep) =>
- writeNat(IFtree)
- writeRef(tree.tpe)
- writeRef(cond)
- writeRef(thenp)
- writeRef(elsep)
- TREE
-
- case tree@Match(selector, cases) =>
- writeNat(MATCHtree)
- writeRef(tree.tpe)
- writeRef(selector)
- writeRefs(cases)
- TREE
-
- case tree@Return(expr) =>
- writeNat(RETURNtree)
- writeRef(tree.tpe)
- writeRef(tree.symbol)
- writeRef(expr)
- TREE
-
- case tree@Try(block, catches, finalizer) =>
- writeNat(TREtree)
- writeRef(tree.tpe)
- writeRef(block)
- writeRef(finalizer)
- writeRefs(catches)
- TREE
-
- case tree@Throw(expr) =>
- writeNat(THROWtree)
- writeRef(tree.tpe)
- writeRef(expr)
- TREE
-
- case tree@New(tpt) =>
- writeNat(NEWtree)
- writeRef(tree.tpe)
- writeRef(tpt)
- TREE
-
- case tree@Typed(expr, tpt) =>
- writeNat(TYPEDtree)
- writeRef(tree.tpe)
- writeRef(expr)
- writeRef(tpt)
- TREE
-
- case tree@TypeApply(fun, args) =>
- writeNat(TYPEAPPLYtree)
- writeRef(tree.tpe)
- writeRef(fun)
- writeRefs(args)
- TREE
-
- case tree@Apply(fun, args) =>
- writeNat(APPLYtree)
- writeRef(tree.tpe)
- writeRef(fun)
- writeRefs(args)
- TREE
-
- case tree@ApplyDynamic(qual, args) =>
- writeNat(APPLYDYNAMICtree)
- writeRef(tree.tpe)
- writeRef(tree.symbol)
- writeRef(qual)
- writeRefs(args)
- TREE
-
- case tree@Super(qual, mix) =>
- writeNat(SUPERtree)
- writeRef(tree.tpe)
- writeRef(tree.symbol)
- writeRef(qual)
- writeRef(mix)
- TREE
-
- case tree@This(qual) =>
- writeNat(THIStree)
- writeRef(tree.tpe)
- writeRef(tree.symbol)
- writeRef(qual)
- TREE
-
- case tree@Select(qualifier, selector) =>
- writeNat(SELECTtree)
- writeRef(tree.tpe)
- writeRef(tree.symbol)
- writeRef(qualifier)
- writeRef(selector)
- TREE
-
- case tree@Ident(name) =>
- writeNat(IDENTtree)
- writeRef(tree.tpe)
- writeRef(tree.symbol)
- writeRef(name)
- TREE
-
- case tree@Literal(value) =>
- writeNat(LITERALtree)
- writeRef(tree.tpe)
- writeRef(value)
- TREE
-
- case tree@TypeTree() =>
- writeNat(TYPEtree)
- writeRef(tree.tpe)
- TREE
-
- case tree@Annotated(annot, arg) =>
- writeNat(ANNOTATEDtree)
- writeRef(tree.tpe)
- writeRef(annot)
- writeRef(arg)
- TREE
-
- case tree@SingletonTypeTree(ref) =>
- writeNat(SINGLETONTYPEtree)
+ private object writeTreeBodyTraverser extends Traverser {
+ private var refs = false
+ @inline private def asRefs[T](body: => T): T = {
+ val saved = refs
+ refs = true
+ try body finally refs = saved
+ }
+ override def traverseModifiers(mods: Modifiers): Unit = if (refs) writeRef(mods) else super.traverseModifiers(mods)
+ override def traverseName(name: Name): Unit = writeRef(name)
+ override def traverseConstant(const: Constant): Unit = writeRef(const)
+ override def traverseParams(params: List[Tree]): Unit = writeRefsWithLength(params)
+ override def traverseParamss(vparamss: List[List[Tree]]): Unit = {
+ writeNat(vparamss.length)
+ super.traverseParamss(vparamss)
+ }
+ override def traverse(tree: Tree): Unit = {
+ if (refs)
+ writeRef(tree)
+ else {
writeRef(tree.tpe)
- writeRef(ref)
- TREE
+ if (tree.hasSymbolField)
+ writeRef(tree.symbol)
- case tree@SelectFromTypeTree(qualifier, selector) =>
- writeNat(SELECTFROMTYPEtree)
- writeRef(tree.tpe)
- writeRef(qualifier)
- writeRef(selector)
- TREE
+ asRefs(super.traverse(tree))
+ }
+ }
+ }
- case tree@CompoundTypeTree(templ: Template) =>
- writeNat(COMPOUNDTYPEtree)
- writeRef(tree.tpe)
- writeRef(templ)
- TREE
+ /** Write an entry */
+ private def writeEntry(entry: AnyRef) {
+ def writeLocalSymbolBody(sym: Symbol) {
+ writeSymInfo(sym)
+ sym match {
+ case _: ClassSymbol if sym.hasSelfType => writeRef(sym.typeOfThis)
+ case _: TermSymbol if sym.alias.exists => writeRef(sym.alias)
+ case _ =>
+ }
+ }
+ def writeExtSymbolBody(sym: Symbol) {
+ val name = if (sym.isModuleClass) sym.name.toTermName else sym.name
+ writeRef(name)
+ if (!sym.owner.isRoot)
+ writeRef(sym.owner)
+ }
+ def writeSymbolBody(sym: Symbol) {
+ if (sym ne NoSymbol) {
+ if (isLocal(sym))
+ writeLocalSymbolBody(sym)
+ else
+ writeExtSymbolBody(sym)
+ }
+ }
- case tree@AppliedTypeTree(tpt, args) =>
- writeNat(APPLIEDTYPEtree)
- writeRef(tree.tpe)
- writeRef(tpt)
- writeRefs(args)
- TREE
+ // NullaryMethodType reuses POLYtpe since those can never have an empty list of tparams.
+ // TODO: is there any way this can come back and bite us in the bottom?
+ // ugliness and thrift aside, this should make this somewhat more backward compatible
+ // (I'm not sure how old scalac's would deal with nested PolyTypes, as these used to be folded into one)
+ def writeTypeBody(tpe: Type): Unit = tpe match {
+ case NoType | NoPrefix =>
+ case ThisType(sym) => writeRef(sym)
+ case SingleType(pre, sym) => writeRef(pre) ; writeRef(sym)
+ case SuperType(thistpe, supertpe) => writeRef(thistpe) ; writeRef(supertpe)
+ case ConstantType(value) => writeRef(value)
+ case TypeBounds(lo, hi) => writeRef(lo) ; writeRef(hi)
+ case TypeRef(pre, sym, args) => writeRef(pre) ; writeRef(sym); writeRefs(args)
+ case MethodType(formals, restpe) => writeRef(restpe) ; writeRefs(formals)
+ case NullaryMethodType(restpe) => writeRef(restpe); writeRefs(Nil)
+ case PolyType(tparams, restpe) => writeRef(restpe); writeRefs(tparams)
+ case ExistentialType(tparams, restpe) => writeRef(restpe); writeRefs(tparams)
+ case StaticallyAnnotatedType(annots, tp) => writeRef(tp) ; writeRefs(annots)
+ case AnnotatedType(_, tp, _) => writeTypeBody(tp) // write the underlying type if there are no static annotations
+ case CompoundType(parents, _, clazz) => writeRef(clazz); writeRefs(parents)
+ }
- case tree@TypeBoundsTree(lo, hi) =>
- writeNat(TYPEBOUNDStree)
- writeRef(tree.tpe)
- writeRef(lo)
- writeRef(hi)
- TREE
+ def writeTreeBody(tree: Tree) {
+ writeNat(picklerSubTag(tree))
+ if (!tree.isEmpty)
+ writeTreeBodyTraverser traverse tree
+ }
- case tree@ExistentialTypeTree(tpt, whereClauses) =>
- writeNat(EXISTENTIALTYPEtree)
- writeRef(tree.tpe)
- writeRef(tpt)
- writeRefs(whereClauses)
- TREE
+ def writeConstant(c: Constant): Unit = c.tag match {
+ case BooleanTag => writeLong(if (c.booleanValue) 1 else 0)
+ case FloatTag => writeLong(floatToIntBits(c.floatValue).toLong)
+ case DoubleTag => writeLong(doubleToLongBits(c.doubleValue))
+ case StringTag => writeRef(newTermName(c.stringValue))
+ case ClazzTag => writeRef(c.typeValue)
+ case EnumTag => writeRef(c.symbolValue)
+ case tag => if (ByteTag <= tag && tag <= LongTag) writeLong(c.longValue)
+ }
- case Modifiers(flags, privateWithin, _) =>
- val pflags = rawToPickledFlags(flags)
- writeNat((pflags >> 32).toInt)
- writeNat((pflags & 0xFFFFFFFF).toInt)
- writeRef(privateWithin)
- MODIFIERS
+ def writeModifiers(mods: Modifiers) {
+ val pflags = rawToPickledFlags(mods.flags)
+ writeNat((pflags >> 32).toInt)
+ writeNat((pflags & 0xFFFFFFFF).toInt)
+ writeRef(mods.privateWithin)
+ }
- // annotations on types (not linked to a symbol)
- case annot@AnnotationInfo(_, _, _) =>
- writeAnnotation(annot)
- ANNOTINFO
+ def writeSymbolTuple(target: Symbol, other: Any) {
+ writeRef(target)
+ other match {
+ case annot: AnnotationInfo => writeAnnotation(annot)
+ case children: List[Symbol @unchecked] => writeRefs(children)
+ case _ =>
+ }
+ }
- case _ =>
- throw new FatalError("bad entry: " + entry + " " + entry.getClass)
+ def writeBody(entry: AnyRef): Unit = entry match {
+ case tree: Tree => writeTreeBody(tree)
+ case sym: Symbol => writeSymbolBody(sym)
+ case tpe: Type => writeTypeBody(tpe)
+ case name: Name => writeName(name)
+ case const: Constant => writeConstant(const)
+ case mods: Modifiers => writeModifiers(mods)
+ case annot: AnnotationInfo => writeAnnotation(annot)
+ case (target: Symbol, other) => writeSymbolTuple(target, other)
+ case ArrayAnnotArg(args) => args foreach writeClassfileAnnotArg
+ case _ => devWarning(s"Unexpected entry to pickler ${shortClassOfInstance(entry)} $entry")
}
// begin writeEntry
- val startpos = writeIndex
- // reserve some space so that the patchNat's most likely won't need to shift
- writeByte(0); writeByte(0)
- patchNat(startpos, writeBody(entry))
- patchNat(startpos + 1, writeIndex - (startpos + 2))
+ // The picklerTag method can't determine if it's an external symbol reference
+ val tag = entry match {
+ case sym: Symbol if isExternalSymbol(sym) => if (sym.isModuleClass) EXTMODCLASSref else EXTref
+ case _ => picklerTag(entry)
+ }
+ writeNat(tag)
+ writeByte(0) // reserve a place to record the number of bytes written
+ val start = writeIndex
+ writeBody(entry)
+ val length = writeIndex - start
+ patchNat(start - 1, length) // patch bytes written over the placeholder
}
/** Write byte array */
diff --git a/src/compiler/scala/tools/nsc/transform/Erasure.scala b/src/compiler/scala/tools/nsc/transform/Erasure.scala
index 2d005b26e3..e2902a74b8 100644
--- a/src/compiler/scala/tools/nsc/transform/Erasure.scala
+++ b/src/compiler/scala/tools/nsc/transform/Erasure.scala
@@ -371,17 +371,14 @@ abstract class Erasure extends AddInterfaces
val opc = enteringExplicitOuter {
new overridingPairs.Cursor(root) {
override def parents = List(root.info.firstParent)
- override def exclude(sym: Symbol) = !sym.isMethod || sym.isPrivate || super.exclude(sym)
+ override def exclude(sym: Symbol) = !sym.isMethod || super.exclude(sym)
}
}
def compute(): (List[Tree], immutable.Set[Symbol]) = {
while (opc.hasNext) {
- val member = opc.overriding
- val other = opc.overridden
- //println("bridge? " + member + ":" + member.tpe + member.locationString + " to " + other + ":" + other.tpe + other.locationString)//DEBUG
- if (enteringExplicitOuter(!member.isDeferred))
- checkPair(member, other)
+ if (enteringExplicitOuter(!opc.low.isDeferred))
+ checkPair(opc.currentPair)
opc.next()
}
@@ -438,8 +435,15 @@ abstract class Erasure extends AddInterfaces
noclash
}
- def checkPair(member: Symbol, other: Symbol) {
- val otpe = specialErasure(root)(other.tpe)
+ /** TODO - work through this logic with a fine-toothed comb, incorporating
+ * into SymbolPairs where appropriate.
+ */
+ def checkPair(pair: SymbolPair) {
+ import pair._
+ val member = low
+ val other = high
+ val otpe = highErased
+
val bridgeNeeded = exitingErasure (
!member.isMacro &&
!(other.tpe =:= member.tpe) &&
@@ -844,88 +848,75 @@ abstract class Erasure extends AddInterfaces
/** The erasure transformer */
class ErasureTransformer(unit: CompilationUnit) extends Transformer {
- /** Emit an error if there is a double definition. This can happen if:
- *
- * - A template defines two members with the same name and erased type.
- * - A template defines and inherits two members `m` with different types,
- * but their erased types are the same.
- * - A template inherits two members `m` with different types,
- * but their erased types are the same.
- */
- private def checkNoDoubleDefs(root: Symbol) {
- def doubleDefError(sym1: Symbol, sym2: Symbol) {
- // the .toString must also be computed at the earlier phase
- val tpe1 = exitingRefchecks(root.thisType.memberType(sym1))
- val tpe2 = exitingRefchecks(root.thisType.memberType(sym2))
- if (!tpe1.isErroneous && !tpe2.isErroneous)
- unit.error(
- if (sym1.owner == root) sym1.pos else root.pos,
- (if (sym1.owner == sym2.owner) "double definition:\n"
- else if (sym1.owner == root) "name clash between defined and inherited member:\n"
- else "name clash between inherited members:\n") +
- sym1 + ":" + exitingRefchecks(tpe1.toString) +
- (if (sym1.owner == root) "" else sym1.locationString) + " and\n" +
- sym2 + ":" + exitingRefchecks(tpe2.toString) +
- (if (sym2.owner == root) " at line " + (sym2.pos).line else sym2.locationString) +
- "\nhave same type" +
- (if (exitingRefchecks(tpe1 =:= tpe2)) "" else " after erasure: " + exitingPostErasure(sym1.tpe)))
- sym1.setInfo(ErrorType)
+ import overridingPairs.Cursor
+
+ private def doubleDefError(pair: SymbolPair) {
+ import pair._
+
+ if (!pair.isErroneous) {
+ val what = (
+ if (low.owner == high.owner) "double definition"
+ else if (low.owner == base) "name clash between defined and inherited member"
+ else "name clash between inherited members"
+ )
+ val when = if (exitingRefchecks(lowType matches highType)) "" else " after erasure: " + exitingPostErasure(highType)
+
+ unit.error(pos,
+ s"""|$what:
+ |${exitingRefchecks(highString)} and
+ |${exitingRefchecks(lowString)}
+ |have same type$when""".trim.stripMargin
+ )
}
+ low setInfo ErrorType
+ }
- val decls = root.info.decls
+ /** TODO - adapt SymbolPairs so it can be used here. */
+ private def checkNoDeclaredDoubleDefs(base: Symbol) {
+ val decls = base.info.decls
var e = decls.elems
while (e ne null) {
if (e.sym.isTerm) {
- var e1 = decls.lookupNextEntry(e)
+ var e1 = decls lookupNextEntry e
while (e1 ne null) {
- if (exitingPostErasure(e1.sym.info =:= e.sym.info)) doubleDefError(e.sym, e1.sym)
- e1 = decls.lookupNextEntry(e1)
+ if (exitingPostErasure(e1.sym.info =:= e.sym.info))
+ doubleDefError(new SymbolPair(base, e.sym, e1.sym))
+
+ e1 = decls lookupNextEntry e1
}
}
e = e.next
}
+ }
- val opc = new overridingPairs.Cursor(root) {
+ /** Emit an error if there is a double definition. This can happen if:
+ *
+ * - A template defines two members with the same name and erased type.
+ * - A template defines and inherits two members `m` with different types,
+ * but their erased types are the same.
+ * - A template inherits two members `m` with different types,
+ * but their erased types are the same.
+ */
+ private def checkNoDoubleDefs(root: Symbol) {
+ checkNoDeclaredDoubleDefs(root)
+ object opc extends Cursor(root) {
+ // specialized members have no type history before 'specialize', causing double def errors for curried defs
override def exclude(sym: Symbol): Boolean = (
- !sym.isTerm || sym.isPrivate || super.exclude(sym)
- // specialized members have no type history before 'specialize', causing double def errors for curried defs
+ sym.isType
+ || sym.isPrivate
+ || super.exclude(sym)
|| !sym.hasTypeAt(currentRun.refchecksPhase.id)
)
-
- override def matches(sym1: Symbol, sym2: Symbol): Boolean =
- exitingPostErasure(sym1.tpe =:= sym2.tpe)
+ override def matches(sym1: Symbol, sym2: Symbol) = true
}
- while (opc.hasNext) {
- if (!exitingRefchecks(
- root.thisType.memberType(opc.overriding) matches
- root.thisType.memberType(opc.overridden))) {
- debuglog("" + opc.overriding.locationString + " " +
- opc.overriding.infosString +
- opc.overridden.locationString + " " +
- opc.overridden.infosString)
- doubleDefError(opc.overriding, opc.overridden)
- }
- opc.next()
+ def sameTypeAfterErasure(pair: SymbolPair) = {
+ import pair._
+ log(s"Considering for erasure clash:\n$pair")
+ !exitingRefchecks(lowType matches highType) && exitingPostErasure(low.tpe =:= high.tpe)
}
+ opc.iterator filter sameTypeAfterErasure foreach doubleDefError
}
-/*
- for (bc <- root.info.baseClasses.tail; other <- bc.info.decls.toList) {
- if (other.isTerm && !other.isConstructor && !(other hasFlag (PRIVATE | BRIDGE))) {
- for (member <- root.info.nonPrivateMember(other.name).alternatives) {
- if (member != other &&
- !(member hasFlag BRIDGE) &&
- exitingErasure(member.tpe =:= other.tpe) &&
- !exitingRefchecks(
- root.thisType.memberType(member) matches root.thisType.memberType(other))) {
- debuglog("" + member.locationString + " " + member.infosString + other.locationString + " " + other.infosString);
- doubleDefError(member, other)
- }
- }
- }
- }
-*/
-
/** Add bridge definitions to a template. This means:
*
* If there is a concrete member `m` which overrides a member in a base
@@ -940,7 +931,6 @@ abstract class Erasure extends AddInterfaces
*/
private def bridgeDefs(owner: Symbol): (List[Tree], immutable.Set[Symbol]) = {
assert(phase == currentRun.erasurePhase, phase)
- debuglog("computing bridges for " + owner)
new ComputeBridges(unit, owner) compute()
}
diff --git a/src/compiler/scala/tools/nsc/transform/OverridingPairs.scala b/src/compiler/scala/tools/nsc/transform/OverridingPairs.scala
index 2610679542..4222c4d8c8 100644
--- a/src/compiler/scala/tools/nsc/transform/OverridingPairs.scala
+++ b/src/compiler/scala/tools/nsc/transform/OverridingPairs.scala
@@ -6,221 +6,33 @@
package scala.tools.nsc
package transform
-import scala.collection.mutable
import symtab.Flags._
-import util.HashSet
-import scala.annotation.tailrec
+import scala.reflect.internal.SymbolPairs
/** A class that yields a kind of iterator (`Cursor`),
- * which yields all pairs of overriding/overridden symbols
- * that are visible in some baseclass, unless there's a parent class
- * that already contains the same pairs.
- * @author Martin Odersky
- * @version 1.0
+ * which yields pairs of corresponding symbols visible in some base class,
+ * unless there's a parent class that already contains the same pairs.
+ * Most of the logic is in SymbolPairs, which contains generic
+ * pair-oriented traversal logic.
*/
-abstract class OverridingPairs {
-
- val global: Global
+abstract class OverridingPairs extends SymbolPairs {
import global._
- /** The cursor class
- * @param base the base class that contains the overriding pairs
- */
- class Cursor(base: Symbol) {
-
- private val self = base.thisType
-
- /** Symbols to exclude: Here these are constructors, private locals,
- * and hidden symbols, including bridges. But it may be refined in subclasses.
- *
- */
- protected def exclude(sym: Symbol): Boolean =
- sym.isConstructor || sym.isPrivateLocal || sym.isArtifact
-
- /** The parents of base (may also be refined).
- */
- protected def parents: List[Type] = base.info.parents
-
- /** Does `sym1` match `sym2` so that it qualifies as overriding.
- * Types always match. Term symbols match if their membertypes
- * relative to <base>.this do
- */
- protected def matches(sym1: Symbol, sym2: Symbol): Boolean = {
- def tp_s(s: Symbol) = self.memberType(s) + "/" + self.memberType(s).getClass
- val result = sym1.isType || (self.memberType(sym1) matches self.memberType(sym2))
- debuglog("overriding-pairs? %s matches %s (%s vs. %s) == %s".format(
- sym1.fullLocationString, sym2.fullLocationString, tp_s(sym1), tp_s(sym2), result))
-
- result
- }
+ class Cursor(base: Symbol) extends super.Cursor(base) {
+ lazy val relatively = new RelativeTo(base.thisType)
- /** An implementation of BitSets as arrays (maybe consider collection.BitSet
- * for that?) The main purpose of this is to implement
- * intersectionContainsElement efficiently.
+ /** Symbols to exclude: Here these are constructors and private/artifact symbols,
+ * including bridges. But it may be refined in subclasses.
*/
- private type BitSet = Array[Int]
-
- private def include(bs: BitSet, n: Int) {
- val nshifted = n >> 5
- val nmask = 1 << (n & 31)
- bs(nshifted) = bs(nshifted) | nmask
- }
-
- /** Implements `bs1 * bs2 * {0..n} != 0.
- * Used in hasCommonParentAsSubclass */
- private def intersectionContainsElementLeq(bs1: BitSet, bs2: BitSet, n: Int): Boolean = {
- val nshifted = n >> 5
- val nmask = 1 << (n & 31)
- var i = 0
- while (i < nshifted) {
- if ((bs1(i) & bs2(i)) != 0) return true
- i += 1
- }
- (bs1(nshifted) & bs2(nshifted) & (nmask | nmask - 1)) != 0
- }
-
- /** The symbols that can take part in an overriding pair */
- private val decls = newScope
+ override protected def exclude(sym: Symbol) = (sym hasFlag PRIVATE | ARTIFACT) || sym.isConstructor
- // fill `decls` with overriding shadowing overridden */
- { def fillDecls(bcs: List[Symbol], deferredflag: Int) {
- if (!bcs.isEmpty) {
- fillDecls(bcs.tail, deferredflag)
- var e = bcs.head.info.decls.elems
- while (e ne null) {
- if (e.sym.getFlag(DEFERRED) == deferredflag.toLong && !exclude(e.sym))
- decls enter e.sym
- e = e.next
- }
- }
- }
- // first, deferred (this wil need to change if we change lookup rules!
- fillDecls(base.info.baseClasses, DEFERRED)
- // then, concrete.
- fillDecls(base.info.baseClasses, 0)
- }
-
- private val size = base.info.baseClasses.length
-
- /** A map from baseclasses of <base> to ints, with smaller ints meaning lower in
- * linearization order.
- * symbols that are not baseclasses map to -1.
+ /** Types always match. Term symbols match if their member types
+ * relative to `self` match.
*/
- private val index = new mutable.HashMap[Symbol, Int] {
- override def default(key: Symbol) = -1
- }
-
- // Note: overridingPairs can be called at odd instances by the Eclipse plugin
- // Soemtimes symbols are not yet defined and we get missing keys.
- // The implementation here is hardened so that it does not crash on a missing key.
-
- { var i = 0
- for (bc <- base.info.baseClasses) {
- index(bc) = i
- i += 1
- }
- }
-
- /** A mapping from all base class indices to a bitset
- * which indicates whether parents are subclasses.
- *
- * i \in subParents(j) iff
- * exists p \in parents, b \in baseClasses:
- * i = index(p)
- * j = index(b)
- * p isSubClass b
- * p.baseType(b) == self.baseType(b)
- */
- private val subParents = new Array[BitSet](size)
-
- { for (i <- List.range(0, size))
- subParents(i) = new BitSet(size)
- for (p <- parents) {
- val pIndex = index(p.typeSymbol)
- if (pIndex >= 0)
- for (bc <- p.baseClasses)
- if (p.baseType(bc) =:= self.baseType(bc)) {
- val bcIndex = index(bc)
- if (bcIndex >= 0)
- include(subParents(bcIndex), pIndex)
- }
- }
- }
-
- /** Do `sym1` and `sym2` have a common subclass in `parents`?
- * In that case we do not follow their overriding pairs
- */
- private def hasCommonParentAsSubclass(sym1: Symbol, sym2: Symbol) = {
- val index1 = index(sym1.owner)
- (index1 >= 0) && {
- val index2 = index(sym2.owner)
- (index2 >= 0) && {
- intersectionContainsElementLeq(
- subParents(index1), subParents(index2), index1 min index2)
- }
- }
- }
-
- /** The scope entries that have already been visited as overridden
- * (maybe excluded because of hasCommonParentAsSubclass).
- * These will not appear as overriding
- */
- private val visited = HashSet[ScopeEntry]("visited", 64)
-
- /** The current entry candidate for overriding
- */
- private var curEntry = decls.elems
-
- /** The current entry candidate for overridden */
- private var nextEntry = curEntry
-
- /** The current candidate symbol for overriding */
- var overriding: Symbol = _
-
- /** If not null: The symbol overridden by overriding */
- var overridden: Symbol = _
-
- //@M: note that next is called once during object initialization
- def hasNext: Boolean = curEntry ne null
-
- @tailrec
- final def next() {
- if (curEntry ne null) {
- overriding = curEntry.sym
- if (nextEntry ne null) {
- do {
- do {
- nextEntry = decls.lookupNextEntry(nextEntry)
- /* DEBUG
- if ((nextEntry ne null) &&
- !(nextEntry.sym hasFlag PRIVATE) &&
- !(overriding.owner == nextEntry.sym.owner) &&
- !matches(overriding, nextEntry.sym))
- println("skipping "+overriding+":"+self.memberType(overriding)+overriding.locationString+" to "+nextEntry.sym+":"+self.memberType(nextEntry.sym)+nextEntry.sym.locationString)
- */
- } while ((nextEntry ne null) &&
- ((nextEntry.sym hasFlag PRIVATE) ||
- (overriding.owner == nextEntry.sym.owner) ||
- (!matches(overriding, nextEntry.sym)) ||
- (exclude(overriding))))
- if (nextEntry ne null) visited addEntry nextEntry
- // skip nextEntry if a class in `parents` is a subclass of the owners of both
- // overriding and nextEntry.sym
- } while ((nextEntry ne null) && (hasCommonParentAsSubclass(overriding, nextEntry.sym)))
- if (nextEntry ne null) {
- overridden = nextEntry.sym
- //Console.println("yield: " + overriding + overriding.locationString + " / " + overridden + overridden.locationString);//DEBUG
- } else {
- do {
- curEntry = curEntry.next
- } while ((curEntry ne null) && (visited contains curEntry))
- nextEntry = curEntry
- next()
- }
- }
- }
- }
-
- next()
+ override protected def matches(sym1: Symbol, sym2: Symbol) = sym1.isType || (
+ (sym1.owner != sym2.owner)
+ && !exclude(sym2)
+ && relatively.matches(sym1, sym2)
+ )
}
}
diff --git a/src/compiler/scala/tools/nsc/transform/UnCurry.scala b/src/compiler/scala/tools/nsc/transform/UnCurry.scala
index d97f62d5d6..ccf2266540 100644
--- a/src/compiler/scala/tools/nsc/transform/UnCurry.scala
+++ b/src/compiler/scala/tools/nsc/transform/UnCurry.scala
@@ -85,9 +85,6 @@ abstract class UnCurry extends InfoTransform
transformFunction(result)
}
- private lazy val serialVersionUIDAnnotation =
- AnnotationInfo(SerialVersionUIDAttr.tpe, List(Literal(Constant(0))), List())
-
// I don't have a clue why I'm catching TypeErrors here, but it's better
// than spewing stack traces at end users for internal errors. Examples
// which hit at this point should not be hard to come by, but the immediate
@@ -220,7 +217,7 @@ abstract class UnCurry extends InfoTransform
case fun1 if fun1 ne fun => fun1
case _ =>
val parents = addSerializable(abstractFunctionForFunctionType(fun.tpe))
- val anonClass = fun.symbol.owner newAnonymousFunctionClass(fun.pos, inConstructorFlag) addAnnotation serialVersionUIDAnnotation
+ val anonClass = fun.symbol.owner newAnonymousFunctionClass(fun.pos, inConstructorFlag) addAnnotation SerialVersionUIDAnnotation
anonClass setInfo ClassInfoType(parents, newScope, anonClass)
val targs = fun.tpe.typeArgs
diff --git a/src/compiler/scala/tools/nsc/typechecker/Contexts.scala b/src/compiler/scala/tools/nsc/typechecker/Contexts.scala
index abc5363423..5e5619d034 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Contexts.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Contexts.scala
@@ -329,6 +329,7 @@ trait Contexts { self: Analyzer =>
/** The first error, if any, in the report buffer */
def firstError: Option[AbsTypeError] = reportBuffer.firstError
+ def errors: Seq[AbsTypeError] = reportBuffer.errors
/** Does the report buffer contain any errors? */
def hasErrors = reportBuffer.hasErrors
diff --git a/src/compiler/scala/tools/nsc/typechecker/Infer.scala b/src/compiler/scala/tools/nsc/typechecker/Infer.scala
index 03f680525c..dd0923a696 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Infer.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Infer.scala
@@ -914,11 +914,16 @@ trait Infer extends Checkable {
def infer_s = map3(tparams, tvars, targs)((tparam, tvar, targ) => s"$tparam=$tvar/$targ") mkString ","
printTyping(tree, s"infer expr instance from pt=$pt, $infer_s")
+ // SI-7899 infering by-name types is unsound. The correct behaviour is conditional because the hole is
+ // exploited in Scalaz (Free.scala), as seen in: run/t7899-regression.
+ def dropByNameIfStrict(tp: Type): Type = if (settings.inferByName) tp else dropByName(tp)
+ def targsStrict = if (targs eq null) null else targs mapConserve dropByNameIfStrict
+
if (keepNothings || (targs eq null)) { //@M: adjustTypeArgs fails if targs==null, neg/t0226
- substExpr(tree, tparams, targs, pt)
+ substExpr(tree, tparams, targsStrict, pt)
List()
} else {
- val AdjustedTypeArgs.Undets(okParams, okArgs, leftUndet) = adjustTypeArgs(tparams, tvars, targs)
+ val AdjustedTypeArgs.Undets(okParams, okArgs, leftUndet) = adjustTypeArgs(tparams, tvars, targsStrict)
def solved_s = map2(okParams, okArgs)((p, a) => s"$p=$a") mkString ","
def undet_s = leftUndet match {
case Nil => ""
diff --git a/src/compiler/scala/tools/nsc/typechecker/Namers.scala b/src/compiler/scala/tools/nsc/typechecker/Namers.scala
index 599969598e..e3d7bfd4f8 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Namers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Namers.scala
@@ -425,11 +425,10 @@ trait Namers extends MethodSynthesis {
sym
}
- /** Enter a module symbol. The tree parameter can be either
- * a module definition or a class definition.
+ /** Enter a module symbol.
*/
def enterModuleSymbol(tree : ModuleDef): Symbol = {
- var m: Symbol = context.scope lookupAll tree.name find (_.isModule) getOrElse NoSymbol
+ var m: Symbol = context.scope lookupModule tree.name
val moduleFlags = tree.mods.flags | MODULE
if (m.isModule && !m.isPackage && inCurrentScope(m) && (currentRun.canRedefine(m) || m.isSynthetic)) {
updatePosFlags(m, tree.pos, moduleFlags)
diff --git a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala
index d60e61df1b..36f889f8a4 100644
--- a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala
@@ -305,18 +305,23 @@ abstract class RefChecks extends InfoTransform with scala.reflect.internal.trans
/* Check that all conditions for overriding `other` by `member`
* of class `clazz` are met.
*/
- def checkOverride(member: Symbol, other: Symbol) {
+ def checkOverride(pair: SymbolPair) {
+ import pair._
+ val member = low
+ val other = high
+ def memberTp = lowType
+ def otherTp = highType
+
debuglog("Checking validity of %s overriding %s".format(member.fullLocationString, other.fullLocationString))
- def memberTp = self.memberType(member)
- def otherTp = self.memberType(other)
- def noErrorType = other.tpe != ErrorType && member.tpe != ErrorType
+ def noErrorType = !pair.isErroneous
def isRootOrNone(sym: Symbol) = sym != null && sym.isRoot || sym == NoSymbol
- def isNeitherInClass = (member.owner != clazz) && (other.owner != clazz)
+ def isNeitherInClass = member.owner != pair.base && other.owner != pair.base
+
def objectOverrideErrorMsg = (
- "overriding " + other.fullLocationString + " with " + member.fullLocationString + ":\n" +
+ "overriding " + high.fullLocationString + " with " + low.fullLocationString + ":\n" +
"an overriding object must conform to the overridden object's class bound" +
- analyzer.foundReqMsg(classBoundAsSeen(member.tpe), classBoundAsSeen(other.tpe))
+ analyzer.foundReqMsg(pair.lowClassBound, pair.highClassBound)
)
def overrideErrorMsg(msg: String): String = {
@@ -460,79 +465,72 @@ abstract class RefChecks extends InfoTransform with scala.reflect.internal.trans
}
}
- def checkOverrideTypes() {
- if (other.isAliasType) {
- //if (!member.typeParams.isEmpty) (1.5) @MAT
- // overrideError("may not be parameterized");
- //if (!other.typeParams.isEmpty) (1.5) @MAT
- // overrideError("may not override parameterized type");
- // @M: substSym
-
- if( !(sameLength(member.typeParams, other.typeParams) && (memberTp.substSym(member.typeParams, other.typeParams) =:= otherTp)) ) // (1.6)
- overrideTypeError()
+ //if (!member.typeParams.isEmpty) (1.5) @MAT
+ // overrideError("may not be parameterized");
+ //if (!other.typeParams.isEmpty) (1.5) @MAT
+ // overrideError("may not override parameterized type");
+ // @M: substSym
+ def checkOverrideAlias() {
+ if (pair.sameKind && lowType.substSym(low.typeParams, high.typeParams) =:= highType) ()
+ else overrideTypeError() // (1.6)
+ }
+ //if (!member.typeParams.isEmpty) // (1.7) @MAT
+ // overrideError("may not be parameterized");
+ def checkOverrideAbstract() {
+ if (!(highInfo.bounds containsType lowType)) { // (1.7.1)
+ overrideTypeError(); // todo: do an explaintypes with bounds here
+ explainTypes(_.bounds containsType _, highInfo, lowType)
}
- else if (other.isAbstractType) {
- //if (!member.typeParams.isEmpty) // (1.7) @MAT
- // overrideError("may not be parameterized");
- val otherTp = self.memberInfo(other)
-
- if (!(otherTp.bounds containsType memberTp)) { // (1.7.1)
- overrideTypeError(); // todo: do an explaintypes with bounds here
- explainTypes(_.bounds containsType _, otherTp, memberTp)
- }
-
- // check overriding (abstract type --> abstract type or abstract type --> concrete type member (a type alias))
- // making an abstract type member concrete is like passing a type argument
- val kindErrors = typer.infer.checkKindBounds(List(other), List(memberTp), self, member.owner) // (1.7.2)
-
- if(!kindErrors.isEmpty)
+ // check overriding (abstract type --> abstract type or abstract type --> concrete type member (a type alias))
+ // making an abstract type member concrete is like passing a type argument
+ typer.infer.checkKindBounds(high :: Nil, lowType :: Nil, rootType, low.owner) match { // (1.7.2)
+ case Nil =>
+ case kindErrors =>
unit.error(member.pos,
"The kind of "+member.keyString+" "+member.varianceString + member.nameString+
" does not conform to the expected kind of " + other.defString + other.locationString + "." +
kindErrors.toList.mkString("\n", ", ", ""))
-
- // check a type alias's RHS corresponds to its declaration
- // this overlaps somewhat with validateVariance
- if(member.isAliasType) {
- // println("checkKindBounds" + ((List(member), List(memberTp.dealiasWiden), self, member.owner)))
- val kindErrors = typer.infer.checkKindBounds(List(member), List(memberTp.dealiasWiden), self, member.owner)
-
- if(!kindErrors.isEmpty)
+ }
+ // check a type alias's RHS corresponds to its declaration
+ // this overlaps somewhat with validateVariance
+ if (low.isAliasType) {
+ typer.infer.checkKindBounds(low :: Nil, lowType.normalize :: Nil, rootType, low.owner) match {
+ case Nil =>
+ case kindErrors =>
unit.error(member.pos,
- "The kind of the right-hand side "+memberTp.dealiasWiden+" of "+member.keyString+" "+
- member.varianceString + member.nameString+ " does not conform to its expected kind."+
+ "The kind of the right-hand side "+lowType.normalize+" of "+low.keyString+" "+
+ low.varianceString + low.nameString+ " does not conform to its expected kind."+
kindErrors.toList.mkString("\n", ", ", ""))
- } else if (member.isAbstractType) {
- if (memberTp.isVolatile && !otherTp.bounds.hi.isVolatile)
- overrideError("is a volatile type; cannot override a type with non-volatile upper bound")
- }
- } else if (other.isTerm) {
- other.cookJavaRawInfo() // #2454
- val memberTp = self.memberType(member)
- val otherTp = self.memberType(other)
- if (!overridesTypeInPrefix(memberTp, otherTp, self)) { // 8
- overrideTypeError()
- explainTypes(memberTp, otherTp)
}
-
- if (member.isStable && !otherTp.isVolatile) {
- // (1.4), pt 2 -- member.isStable && memberTp.isVolatile started being possible after SI-6815
- // (before SI-6815, !symbol.tpe.isVolatile was implied by symbol.isStable)
- // TODO: allow overriding when @uncheckedStable?
- if (memberTp.isVolatile)
- overrideError("has a volatile type; cannot override a member with non-volatile type")
- else memberTp.dealiasWiden.resultType match {
- case rt: RefinedType if !(rt =:= otherTp) && !(checkedCombinations contains rt.parents) =>
- // might mask some inconsistencies -- check overrides
- checkedCombinations += rt.parents
- val tsym = rt.typeSymbol
- if (tsym.pos == NoPosition) tsym setPos member.pos
- checkAllOverrides(tsym, typesOnly = true)
- case _ =>
- }
+ }
+ else if (low.isAbstractType && lowType.isVolatile && !highInfo.bounds.hi.isVolatile)
+ overrideError("is a volatile type; cannot override a type with non-volatile upper bound")
+ }
+ def checkOverrideTerm() {
+ other.cookJavaRawInfo() // #2454
+ if (!overridesTypeInPrefix(lowType, highType, rootType)) { // 8
+ overrideTypeError()
+ explainTypes(lowType, highType)
+ }
+ if (low.isStable && !highType.isVolatile) {
+ if (lowType.isVolatile)
+ overrideError("has a volatile type; cannot override a member with non-volatile type")
+ else lowType.normalize.resultType match {
+ case rt: RefinedType if !(rt =:= highType) && !(checkedCombinations contains rt.parents) =>
+ // might mask some inconsistencies -- check overrides
+ checkedCombinations += rt.parents
+ val tsym = rt.typeSymbol
+ if (tsym.pos == NoPosition) tsym setPos member.pos
+ checkAllOverrides(tsym, typesOnly = true)
+ case _ =>
}
}
}
+ def checkOverrideTypes() {
+ if (high.isAliasType) checkOverrideAlias()
+ else if (high.isAbstractType) checkOverrideAbstract()
+ else if (high.isTerm) checkOverrideTerm()
+ }
def checkOverrideDeprecated() {
if (other.hasDeprecatedOverridingAnnotation) {
@@ -545,8 +543,8 @@ abstract class RefChecks extends InfoTransform with scala.reflect.internal.trans
val opc = new overridingPairs.Cursor(clazz)
while (opc.hasNext) {
- //Console.println(opc.overriding/* + ":" + opc.overriding.tpe*/ + " in "+opc.overriding.fullName + " overrides " + opc.overridden/* + ":" + opc.overridden.tpe*/ + " in "+opc.overridden.fullName + "/"+ opc.overridden.hasFlag(DEFERRED));//debug
- if (!opc.overridden.isClass) checkOverride(opc.overriding, opc.overridden)
+ if (!opc.high.isClass)
+ checkOverride(opc.currentPair)
opc.next()
}
@@ -585,10 +583,10 @@ abstract class RefChecks extends InfoTransform with scala.reflect.internal.trans
def ignoreDeferred(member: Symbol) = (
(member.isAbstractType && !member.isFBounded) || (
- member.isJavaDefined &&
// the test requires exitingErasure so shouldn't be
// done if the compiler has no erasure phase available
- (currentRun.erasurePhase == NoPhase || javaErasedOverridingSym(member) != NoSymbol)
+ member.isJavaDefined
+ && (currentRun.erasurePhase == NoPhase || javaErasedOverridingSym(member) != NoSymbol)
)
)
@@ -1416,7 +1414,11 @@ abstract class RefChecks extends InfoTransform with scala.reflect.internal.trans
private def checkTypeRef(tp: Type, tree: Tree, skipBounds: Boolean) = tp match {
case TypeRef(pre, sym, args) =>
- checkDeprecated(sym, tree.pos)
+ tree match {
+ case tt: TypeTree if tt.original == null => // SI-7783 don't warn about inferred types
+ case _ =>
+ checkDeprecated(sym, tree.pos)
+ }
if(sym.isJavaDefined)
sym.typeParams foreach (_.cookJavaRawInfo())
if (!tp.isHigherKinded && !skipBounds)
diff --git a/src/compiler/scala/tools/nsc/typechecker/TreeCheckers.scala b/src/compiler/scala/tools/nsc/typechecker/TreeCheckers.scala
index 1b726c37b9..fd8f9bebba 100644
--- a/src/compiler/scala/tools/nsc/typechecker/TreeCheckers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/TreeCheckers.scala
@@ -283,6 +283,9 @@ abstract class TreeCheckers extends Analyzer {
}
private def traverseInternal(tree: Tree) {
+ if (!tree.canHaveAttrs)
+ return
+
checkSymbolRefsRespectScope(enclosingMemberDefs takeWhile (md => !md.symbol.hasPackageFlag), tree)
checkReturnReferencesDirectlyEnclosingDef(tree)
@@ -329,10 +332,9 @@ abstract class TreeCheckers extends Analyzer {
return
case _ =>
}
-
- if (tree.canHaveAttrs && tree.pos == NoPosition)
+ if (tree.pos == NoPosition)
noPos(tree)
- else if (tree.tpe == null && phase.id > currentRun.typerPhase.id)
+ else if (tree.tpe == null && isPastTyper)
noType(tree)
else if (tree.isDef) {
checkSym(tree)
diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
index ecd987b031..97e9d6ef52 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
@@ -13,7 +13,7 @@ package scala
package tools.nsc
package typechecker
-import scala.collection.mutable
+import scala.collection.{ mutable, immutable }
import scala.reflect.internal.util.{ BatchSourceFile, Statistics, shortClassOfInstance }
import mutable.ListBuffer
import symtab.Flags._
@@ -79,12 +79,25 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper
case SilentResultValue(value) if !p(value) => SilentTypeError(TypeErrorWrapper(new TypeError(NoPosition, "!p")))
case _ => this
}
- @inline final def orElse[T1 >: T](f: AbsTypeError => T1): T1 = this match {
+ @inline final def orElse[T1 >: T](f: Seq[AbsTypeError] => T1): T1 = this match {
case SilentResultValue(value) => value
- case SilentTypeError(err) => f(err)
+ case s : SilentTypeError => f(s.reportableErrors)
}
}
- case class SilentTypeError(err: AbsTypeError) extends SilentResult[Nothing] { }
+ class SilentTypeError private(val errors: List[AbsTypeError]) extends SilentResult[Nothing] {
+ def err: AbsTypeError = errors.head
+ def reportableErrors = errors match {
+ case (e1: AmbiguousImplicitTypeError) +: _ =>
+ List(e1) // DRYer error reporting for neg/t6436b.scala
+ case all =>
+ all
+ }
+ }
+ object SilentTypeError {
+ def apply(errors: AbsTypeError*): SilentTypeError = new SilentTypeError(errors.toList)
+ def unapply(error: SilentTypeError): Option[AbsTypeError] = error.errors.headOption
+ }
+
case class SilentResultValue[+T](value: T) extends SilentResult[T] { }
def newTyper(context: Context): Typer = new NormalTyper(context)
@@ -682,14 +695,13 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper
context.undetparams = context1.undetparams
context.savedTypeBounds = context1.savedTypeBounds
context.namedApplyBlockInfo = context1.namedApplyBlockInfo
- context1.firstError match {
- case Some(err) =>
- stopStats()
- SilentTypeError(err)
- case None =>
- // If we have a successful result, emit any warnings it created.
- context1.flushAndIssueWarnings()
- SilentResultValue(result)
+ if (context1.hasErrors) {
+ stopStats()
+ SilentTypeError(context1.errors: _*)
+ } else {
+ // If we have a successful result, emit any warnings it created.
+ context1.flushAndIssueWarnings()
+ SilentResultValue(result)
}
} else {
assert(context.bufferErrors || isPastTyper, "silent mode is not available past typer")
@@ -1258,9 +1270,9 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper
reportError
}
- silent(_.adaptToMember(qual, HasMember(name), reportAmbiguous = false)) orElse (err =>
+ silent(_.adaptToMember(qual, HasMember(name), reportAmbiguous = false)) orElse (errs =>
onError {
- if (reportAmbiguous) context issue err
+ if (reportAmbiguous) errs foreach (context issue _)
setError(tree)
}
)
@@ -2392,9 +2404,16 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper
if (pat1.tpe.paramSectionCount > 0)
pat1 modifyType (_.finalResultType)
- for (bind @ Bind(name, _) <- cdef.pat)
- if (name.toTermName != nme.WILDCARD && bind.symbol != null && bind.symbol != NoSymbol)
- namer.enterIfNotThere(bind.symbol)
+ for (bind @ Bind(name, _) <- cdef.pat) {
+ val sym = bind.symbol
+ if (name.toTermName != nme.WILDCARD && sym != null) {
+ if (sym == NoSymbol) {
+ if (context.scope.lookup(name) == NoSymbol)
+ namer.enterInScope(context.owner.newErrorSymbol(name))
+ } else
+ namer.enterIfNotThere(sym)
+ }
+ }
val guard1: Tree = if (cdef.guard == EmptyTree) EmptyTree
else typed(cdef.guard, BooleanTpe)
@@ -2484,7 +2503,7 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper
assert(pt.typeSymbol == PartialFunctionClass, s"PartialFunction synthesis for match in $tree requires PartialFunction expected type, but got $pt.")
val targs = pt.dealiasWiden.typeArgs
- // if targs.head isn't fully defined, we can translate --> error
+ // if targs.head isn't fully defined, we can't translate --> error
targs match {
case argTp :: _ if isFullyDefined(argTp) => // ok
case _ => // uh-oh
@@ -2498,9 +2517,7 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper
// targs must conform to Any for us to synthesize an applyOrElse (fallback to apply otherwise -- typically for @cps annotated targs)
val targsValidParams = targs forall (_ <:< AnyTpe)
- val anonClass = (context.owner
- newAnonymousFunctionClass tree.pos
- addAnnotation AnnotationInfo(SerialVersionUIDAttr.tpe, List(Literal(Constant(0))), List()))
+ val anonClass = context.owner newAnonymousFunctionClass tree.pos addAnnotation SerialVersionUIDAnnotation
import CODE._
@@ -2693,17 +2710,197 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper
}
}
+ /** Synthesize and type check the implementation of a type with a Single Abstract Method
+ *
+ * `{ (p1: T1, ..., pN: TN) => body } : S`
+ *
+ * expands to (where `S` is the expected type that defines a single abstract method named `apply`)
+ *
+ * `{
+ * def apply$body(p1: T1, ..., pN: TN): T = body
+ * new S {
+ * def apply(p1: T1, ..., pN: TN): T = apply$body(p1,..., pN)
+ * }
+ * }`
+ *
+ * If 'T' is not fully defined, it is inferred by type checking
+ * `apply$body` without a result type before type checking the block.
+ * The method's inferred result type is used instead of T`. [See test/files/pos/sammy_poly.scala]
+ *
+ * The `apply` method is identified by the argument `sam`; `S` corresponds to the argument `samClassTp`,
+ * and `resPt` is derived from `samClassTp` -- it may be fully defined, or not...
+ *
+ * The function's body is put in a method outside of the class definition to enforce scoping.
+ * S's members should not be in scope in `body`.
+ *
+ * The restriction on implicit arguments (neither S's constructor, nor sam may take an implicit argument list),
+ * is largely to keep the implementation of type inference (the computation of `samClassTpFullyDefined`) simple.
+ *
+ * NOTE: it would be nicer to not have to type check `apply$body` separately when `T` is not fully defined.
+ * However T must be fully defined before we type the instantiation, as it'll end up as a parent type,
+ * which must be fully defined. Would be nice to have some kind of mechanism to insert type vars in a block of code,
+ * and have the instantiation of the first occurrence propagate to the rest of the block.
+ */
+ def synthesizeSAMFunction(sam: Symbol, fun: Function, resPt: Type, samClassTp: Type, mode: Mode): Tree = {
+ // assert(fun.vparams forall (vp => isFullyDefined(vp.tpt.tpe))) -- by construction, as we take them from sam's info
+ val sampos = fun.pos
+
+ // if the expected sam type is fully defined, use it for the method's result type
+ // otherwise, NoType, so that type inference will determine the method's result type
+ // resPt is syntactically contained in samClassTp, so if the latter is fully defined, so is the former
+ // ultimately, we want to fully define samClassTp as it is used as the superclass of our anonymous class
+ val samDefTp = if (isFullyDefined(resPt)) resPt else NoType
+ val bodyName = newTermName(sam.name + "$body")
+
+ // `def '${sam.name}\$body'($p1: $T1, ..., $pN: $TN): $resPt = $body`
+ val samBodyDef =
+ DefDef(NoMods,
+ bodyName,
+ Nil,
+ List(fun.vparams.map(_.duplicate)), // must duplicate as we're also using them for `samDef`
+ TypeTree(samDefTp) setPos sampos.focus,
+ fun.body)
+
+ // If we need to enter the sym for the body def before type checking the block,
+ // we'll create a nested context, as explained below.
+ var nestedTyper = this
+
+ // Type check body def before classdef to fully determine samClassTp (if necessary).
+ // As `samClassTp` determines a parent type for the class,
+ // we can't type check `block` in one go unless `samClassTp` is fully defined.
+ val samClassTpFullyDefined =
+ if (isFullyDefined(samClassTp)) samClassTp
+ else try {
+ // This creates a symbol for samBodyDef with a type completer that'll be triggered immediately below.
+ // The symbol is entered in the same scope used for the block below, and won't thus be reentered later.
+ // It has to be a new scope, though, or we'll "get ambiguous reference to overloaded definition" [pos/sammy_twice.scala]
+ // makeSilent: [pos/nonlocal-unchecked.scala -- when translation all functions to sams]
+ val nestedCtx = enterSym(context.makeNewScope(context.tree, context.owner).makeSilent(), samBodyDef)
+ nestedTyper = newTyper(nestedCtx)
+
+ // NOTE: this `samBodyDef.symbol.info` runs the type completer set up by the enterSym above
+ val actualSamType = samBodyDef.symbol.info
+
+ // we're trying to fully define the type arguments for this type constructor
+ val samTyCon = samClassTp.typeSymbol.typeConstructor
+
+ // the unknowns
+ val tparams = samClassTp.typeSymbol.typeParams
+ // ... as typevars
+ val tvars = tparams map freshVar
+
+ // 1. Recover partial information:
+ // - derive a type from samClassTp that has the corresponding tparams for type arguments that aren't fully defined
+ // - constrain typevars to be equal to type args that are fully defined
+ val samClassTpMoreDefined = appliedType(samTyCon,
+ (samClassTp.typeArgs, tparams, tvars).zipped map {
+ case (a, _, tv) if isFullyDefined(a) => tv =:= a; a
+ case (_, p, _) => p.typeConstructor
+ })
+
+ // the method type we're expecting the synthesized sam to have, based on the expected sam type,
+ // where fully defined type args to samClassTp have been preserved,
+ // with the unknown args replaced by their corresponding type param
+ val expectedSamType = samClassTpMoreDefined.memberInfo(sam)
+
+ // 2. make sure the body def's actual type (formals and result) conforms to
+ // sam's expected type (in terms of the typevars that represent the sam's class's type params)
+ actualSamType <:< expectedSamType.substituteTypes(tparams, tvars)
+
+ // solve constraints tracked by tvars
+ val targs = solvedTypes(tvars, tparams, tparams map varianceInType(sam.info), upper = false, lubDepth(sam.info :: Nil))
+
+ debuglog(s"sam infer: $samClassTp --> ${appliedType(samTyCon, targs)} by $actualSamType <:< $expectedSamType --> $targs for $tparams")
+
+ // a fully defined samClassTp
+ appliedType(samTyCon, targs)
+ } catch {
+ case _: NoInstance | _: TypeError =>
+ devWarning(sampos, s"Could not define type $samClassTp using ${samBodyDef.symbol.rawInfo} <:< ${samClassTp memberInfo sam} (for $sam)")
+ samClassTp
+ }
+
+ // `final override def ${sam.name}($p1: $T1, ..., $pN: $TN): $resPt = ${sam.name}\$body'($p1, ..., $pN)`
+ val samDef =
+ DefDef(Modifiers(FINAL | OVERRIDE | SYNTHETIC),
+ sam.name.toTermName,
+ Nil,
+ List(fun.vparams),
+ TypeTree(samBodyDef.tpt.tpe) setPos sampos.focus,
+ Apply(Ident(bodyName), fun.vparams map (p => Ident(p.name)))
+ )
+
+ val serializableParentAddendum =
+ if (typeIsSubTypeOfSerializable(samClassTp)) Nil
+ else List(TypeTree(SerializableTpe))
+
+ val classDef =
+ ClassDef(Modifiers(FINAL), tpnme.ANON_FUN_NAME, tparams = Nil,
+ gen.mkTemplate(
+ parents = TypeTree(samClassTpFullyDefined) :: serializableParentAddendum,
+ self = emptyValDef,
+ constrMods = NoMods,
+ vparamss = ListOfNil,
+ body = List(samDef),
+ superPos = sampos.focus
+ )
+ )
+
+ // type checking the whole block, so that everything is packaged together nicely
+ // and we don't have to create any symbols by hand
+ val block =
+ nestedTyper.typedPos(sampos, mode, samClassTpFullyDefined) {
+ Block(
+ samBodyDef,
+ classDef,
+ Apply(Select(New(Ident(tpnme.ANON_FUN_NAME)), nme.CONSTRUCTOR), Nil)
+ )
+ }
+
+ classDef.symbol addAnnotation SerialVersionUIDAnnotation
+ block
+ }
+
+ /** Type check a function literal.
+ *
+ * Based on the expected type pt, potentially synthesize an instance of
+ * - PartialFunction,
+ * - a type with a Single Abstract Method (under -Xexperimental for now).
+ */
private def typedFunction(fun: Function, mode: Mode, pt: Type): Tree = {
val numVparams = fun.vparams.length
- if (numVparams > definitions.MaxFunctionArity)
- return MaxFunctionArityError(fun)
+ val FunctionSymbol =
+ if (numVparams > definitions.MaxFunctionArity) NoSymbol
+ else FunctionClass(numVparams)
- val FunctionSymbol = FunctionClass(numVparams)
- val (argpts, respt) = pt baseType FunctionSymbol match {
- case TypeRef(_, FunctionSymbol, args :+ res) => (args, res)
- case _ => (fun.vparams map (_ => NoType), WildcardType)
- }
- if (argpts.lengthCompare(numVparams) != 0)
+ /* The Single Abstract Member of pt, unless pt is the built-in function type of the expected arity,
+ * as `(a => a): Int => Int` should not (yet) get the sam treatment.
+ */
+ val sam =
+ if (!settings.Xexperimental || pt.typeSymbol == FunctionSymbol) NoSymbol
+ else samOf(pt)
+
+ /* The SAM case comes first so that this works:
+ * abstract class MyFun extends (Int => Int)
+ * (a => a): MyFun
+ *
+ * Note that the arity of the sam must correspond to the arity of the function.
+ */
+ val samViable = sam.exists && sameLength(sam.info.params, fun.vparams)
+ val (argpts, respt) =
+ if (samViable) {
+ val samInfo = pt memberInfo sam
+ (samInfo.paramTypes, samInfo.resultType)
+ } else {
+ pt baseType FunctionSymbol match {
+ case TypeRef(_, FunctionSymbol, args :+ res) => (args, res)
+ case _ => (fun.vparams map (_ => if (pt == ErrorType) ErrorType else NoType), WildcardType)
+ }
+ }
+
+ if (!FunctionSymbol.exists)
+ MaxFunctionArityError(fun)
+ else if (argpts.lengthCompare(numVparams) != 0)
WrongNumberOfParametersError(fun, argpts)
else {
foreach2(fun.vparams, argpts) { (vparam, argpt) =>
@@ -2714,7 +2911,7 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper
fun match {
case etaExpansion(vparams, fn, args) =>
silent(_.typed(fn, mode.forFunMode, pt)) filter (_ => context.undetparams.isEmpty) map { fn1 =>
- // if context,undetparams is not empty, the function was polymorphic,
+ // if context.undetparams is not empty, the function was polymorphic,
// so we need the missing arguments to infer its type. See #871
//println("typing eta "+fun+":"+fn1.tpe+"/"+context.undetparams)
val ftpe = normalize(fn1.tpe) baseType FunctionClass(numVparams)
@@ -2742,6 +2939,13 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper
if (p.tpt.tpe == null) p.tpt setType outerTyper.typedType(p.tpt).tpe
outerTyper.synthesizePartialFunction(p.name, p.pos, fun.body, mode, pt)
+
+ // Use synthesizeSAMFunction to expand `(p1: T1, ..., pN: TN) => body`
+ // to an instance of the corresponding anonymous subclass of `pt`.
+ case _ if samViable =>
+ newTyper(context.outer).synthesizeSAMFunction(sam, fun, respt, pt, mode)
+
+ // regular Function
case _ =>
val vparamSyms = fun.vparams map { vparam =>
enterSym(context, vparam)
@@ -3386,7 +3590,7 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper
else {
val annScope = annType.decls
.filter(sym => sym.isMethod && !sym.isConstructor && sym.isJavaDefined)
- val names = new scala.collection.mutable.HashSet[Symbol]
+ val names = mutable.Set[Symbol]()
names ++= (if (isJava) annScope.iterator
else typedFun.tpe.params.iterator)
@@ -3399,7 +3603,7 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper
val nvPairs = args map {
case arg @ AssignOrNamedArg(Ident(name), rhs) =>
val sym = if (isJava) annScope.lookup(name)
- else typedFun.tpe.params.find(p => p.name == name).getOrElse(NoSymbol)
+ else findSymbol(typedFun.tpe.params)(_.name == name)
if (sym == NoSymbol) {
reportAnnotationError(UnknownAnnotationNameError(arg, name))
(nme.ERROR, None)
@@ -3526,8 +3730,8 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper
while (o != owner && o != NoSymbol && !o.hasPackageFlag) o = o.owner
o == owner && !isVisibleParameter(sym)
}
- var localSyms = scala.collection.immutable.Set[Symbol]()
- var boundSyms = scala.collection.immutable.Set[Symbol]()
+ var localSyms = immutable.Set[Symbol]()
+ var boundSyms = immutable.Set[Symbol]()
def isLocal(sym: Symbol): Boolean =
if (sym == NoSymbol || sym.isRefinementClass || sym.isLocalDummy) false
else if (owner == NoSymbol) tree exists (defines(_, sym))
@@ -3779,7 +3983,7 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper
}
}
}
- def wrapErrors(tree: Tree, typeTree: Typer => Tree): Tree = silent(typeTree) orElse (err => DynamicRewriteError(tree, err))
+ def wrapErrors(tree: Tree, typeTree: Typer => Tree): Tree = silent(typeTree) orElse (err => DynamicRewriteError(tree, err.head))
}
def typed1(tree: Tree, mode: Mode, pt: Type): Tree = {
@@ -4107,7 +4311,7 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper
NotAMemberError(tpt, TypeTree(tp), nme.CONSTRUCTOR)
setError(tpt)
}
- else if (!( tp == sym.thisSym.tpe_* // when there's no explicit self type -- with (#3612) or without self variable
+ else if (!( tp == sym.typeOfThis // when there's no explicit self type -- with (#3612) or without self variable
// sym.thisSym.tpe == tp.typeOfThis (except for objects)
|| narrowRhs(tp) <:< tp.typeOfThis
|| phase.erasedTypes
@@ -4166,7 +4370,7 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper
def tryTypedApply(fun: Tree, args: List[Tree]): Tree = {
val start = if (Statistics.canEnable) Statistics.startTimer(failedApplyNanos) else null
- def onError(typeError: AbsTypeError): Tree = {
+ def onError(typeErrors: Seq[AbsTypeError]): Tree = {
if (Statistics.canEnable) Statistics.stopTimer(failedApplyNanos, start)
// If the problem is with raw types, copnvert to existentials and try again.
@@ -4191,13 +4395,13 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper
case TypeApply(fun, args) => treesInResult(fun) ++ args.flatMap(treesInResult)
case _ => Nil
})
- def errorInResult(tree: Tree) = treesInResult(tree) exists (_.pos == typeError.errPos)
+ def errorInResult(tree: Tree) = treesInResult(tree) exists (err => typeErrors.exists(_.errPos == err.pos))
- val retry = (typeError.errPos != null) && (fun :: tree :: args exists errorInResult)
+ val retry = (typeErrors.forall(_.errPos != null)) && (fun :: tree :: args exists errorInResult)
typingStack.printTyping({
val funStr = ptTree(fun) + " and " + (args map ptTree mkString ", ")
if (retry) "second try: " + funStr
- else "no second try: " + funStr + " because error not in result: " + typeError.errPos+"!="+tree.pos
+ else "no second try: " + funStr + " because error not in result: " + typeErrors.head.errPos+"!="+tree.pos
})
if (retry) {
val Select(qual, name) = fun
@@ -4213,7 +4417,7 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper
case _ => ()
}
}
- issue(typeError)
+ typeErrors foreach issue
setError(treeCopy.Apply(tree, fun, args))
}
@@ -4265,8 +4469,12 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper
tryTypedApply(fun2, args)
else
doTypedApply(tree, fun2, args, mode, pt)
- case SilentTypeError(err) =>
- onError({ issue(err); setError(tree) })
+ case err: SilentTypeError =>
+ onError({
+ err.reportableErrors foreach issue
+ args foreach (arg => typed(arg, mode, ErrorType))
+ setError(tree)
+ })
}
}
@@ -4539,7 +4747,7 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper
def sym = tree1.symbol
if (tree.isInstanceOf[PostfixSelect])
checkFeature(tree.pos, PostfixOpsFeature, name.decode)
- if (sym != null && sym.isOnlyRefinementMember)
+ if (sym != null && sym.isOnlyRefinementMember && !sym.isMacro)
checkFeature(tree1.pos, ReflectiveCallsFeature, sym.toString)
qualStableOrError.symbol match {
diff --git a/src/reflect/scala/reflect/api/Trees.scala b/src/reflect/scala/reflect/api/Trees.scala
index fa7d41f0fc..241747e6d8 100644
--- a/src/reflect/scala/reflect/api/Trees.scala
+++ b/src/reflect/scala/reflect/api/Trees.scala
@@ -2544,18 +2544,32 @@ trait Trees { self: Universe =>
class Traverser {
protected[scala] var currentOwner: Symbol = rootMirror.RootClass
+ /** Traverse something which Trees contain, but which isn't a Tree itself. */
+ def traverseName(name: Name): Unit = ()
+ def traverseConstant(c: Constant): Unit = ()
+ def traverseImportSelector(sel: ImportSelector): Unit = ()
+ def traverseModifiers(mods: Modifiers): Unit = traverseAnnotations(mods.annotations)
+
/** Traverses a single tree. */
- def traverse(tree: Tree): Unit = itraverse(this, tree)
+ def traverse(tree: Tree): Unit = itraverse(this, tree)
+ def traversePattern(pat: Tree): Unit = traverse(pat)
+ def traverseGuard(guard: Tree): Unit = traverse(guard)
+ def traverseTypeAscription(tpt: Tree): Unit = traverse(tpt)
+ // Special handling of noSelfType necessary for backward compat: existing
+ // traversers break down when they see the unexpected tree.
+ def traverseSelfType(self: ValDef): Unit = if (self ne noSelfType) traverse(self)
/** Traverses a list of trees. */
- def traverseTrees(trees: List[Tree]) {
- trees foreach traverse
- }
+ def traverseTrees(trees: List[Tree]): Unit = trees foreach traverse
+ def traverseTypeArgs(args: List[Tree]): Unit = traverseTrees(args)
+ def traverseParents(parents: List[Tree]): Unit = traverseTrees(parents)
+ def traverseCases(cases: List[CaseDef]): Unit = traverseTrees(cases)
+ def traverseAnnotations(annots: List[Tree]): Unit = traverseTrees(annots)
/** Traverses a list of lists of trees. */
- def traverseTreess(treess: List[List[Tree]]) {
- treess foreach traverseTrees
- }
+ def traverseTreess(treess: List[List[Tree]]): Unit = treess foreach traverseTrees
+ def traverseParams(params: List[Tree]): Unit = traverseTrees(params)
+ def traverseParamss(vparamss: List[List[Tree]]): Unit = vparamss foreach traverseParams
/** Traverses a list of trees with a given owner symbol. */
def traverseStats(stats: List[Tree], exprOwner: Symbol) {
diff --git a/src/reflect/scala/reflect/internal/AnnotationInfos.scala b/src/reflect/scala/reflect/internal/AnnotationInfos.scala
index 215ab6abd6..f45fa40f89 100644
--- a/src/reflect/scala/reflect/internal/AnnotationInfos.scala
+++ b/src/reflect/scala/reflect/internal/AnnotationInfos.scala
@@ -27,6 +27,8 @@ trait AnnotationInfos extends api.Annotations { self: SymbolTable =>
def filterAnnotations(p: AnnotationInfo => Boolean): Self // Retain only annotations meeting the condition.
def withoutAnnotations: Self // Remove all annotations from this type.
+ def staticAnnotations = annotations filter (_.isStatic)
+
/** Symbols of any @throws annotations on this symbol.
*/
def throwsAnnotations(): List[Symbol] = annotations collect {
diff --git a/src/reflect/scala/reflect/internal/Definitions.scala b/src/reflect/scala/reflect/internal/Definitions.scala
index 7b2e40b59c..99aad4f057 100644
--- a/src/reflect/scala/reflect/internal/Definitions.scala
+++ b/src/reflect/scala/reflect/internal/Definitions.scala
@@ -709,7 +709,82 @@ trait Definitions extends api.StandardDefinitions {
case NullaryMethodType(restpe) => finalResultType(restpe)
case _ => tp
}
+ /** Similarly, putting all the isStable logic in one place.
+ * This makes it like 1000x easier to see the overall logic
+ * of the method.
+ */
+ def isStable(tp: Type): Boolean = tp match {
+ case _: SingletonType => true
+ case NoPrefix => true
+ case TypeRef(_, NothingClass | SingletonClass, _) => true
+ case TypeRef(_, sym, _) if sym.isAbstractType => tp.bounds.hi.typeSymbol isSubClass SingletonClass
+ case TypeRef(pre, sym, _) if sym.isModuleClass => isStable(pre)
+ case TypeRef(_, _, _) if tp ne tp.dealias => isStable(tp.dealias)
+ case TypeVar(origin, _) => isStable(origin)
+ case AnnotatedType(_, atp, _) => isStable(atp) // Really?
+ case _: SimpleTypeProxy => isStable(tp.underlying)
+ case _ => false
+ }
+ def isVolatile(tp: Type): Boolean = {
+ // need to be careful not to fall into an infinite recursion here
+ // because volatile checking is done before all cycles are detected.
+ // the case to avoid is an abstract type directly or
+ // indirectly upper-bounded by itself. See #2918
+ def isVolatileAbstractType: Boolean = {
+ def sym = tp.typeSymbol
+ def volatileUpperBound = isVolatile(tp.bounds.hi)
+ def safeIsVolatile = (
+ if (volatileRecursions < TypeConstants.LogVolatileThreshold)
+ volatileUpperBound
+ // we can return true when pendingVolatiles contains sym, because
+ // a cycle will be detected afterwards and an error will result anyway.
+ else pendingVolatiles(sym) || {
+ pendingVolatiles += sym
+ try volatileUpperBound finally pendingVolatiles -= sym
+ }
+ )
+ volatileRecursions += 1
+ try safeIsVolatile finally volatileRecursions -= 1
+ }
+ /** A refined type P1 with ... with Pn { decls } is volatile if
+ * one of the parent types Pi is an abstract type, and
+ * either i > 1, or decls or a following parent Pj, j > 1, contributes
+ * an abstract member.
+ * A type contributes an abstract member if it has an abstract member which
+ * is also a member of the whole refined type. A scope `decls` contributes
+ * an abstract member if it has an abstract definition which is also
+ * a member of the whole type.
+ */
+ def isVolatileRefinedType: Boolean = {
+ val RefinedType(parents, decls) = tp
+ def isVisibleDeferred(m: Symbol) = m.isDeferred && ((tp nonPrivateMember m.name).alternatives contains m)
+ def contributesAbstractMembers(p: Type) = p.deferredMembers exists isVisibleDeferred
+ def dropConcreteParents = parents dropWhile (p => !p.typeSymbol.isAbstractType)
+
+ (parents exists isVolatile) || {
+ dropConcreteParents match {
+ case Nil => false
+ case ps => (ps ne parents) || (ps.tail exists contributesAbstractMembers) || (decls exists isVisibleDeferred)
+ }
+ }
+ }
+ tp match {
+ case ThisType(_) => false
+ case SingleType(_, sym) => isVolatile(tp.underlying) && (sym.hasVolatileType || !sym.isStable)
+ case NullaryMethodType(restpe) => isVolatile(restpe)
+ case PolyType(_, restpe) => isVolatile(restpe)
+ case TypeRef(_, _, _) if tp ne tp.dealias => isVolatile(tp.dealias)
+ case TypeRef(_, sym, _) if sym.isAbstractType => isVolatileAbstractType
+ case RefinedType(_, _) => isVolatileRefinedType
+ case TypeVar(origin, _) => isVolatile(origin)
+ case _: SimpleTypeProxy => isVolatile(tp.underlying)
+ case _ => false
+ }
+ }
+
+ private[this] var volatileRecursions: Int = 0
+ private[this] val pendingVolatiles = mutable.HashSet[Symbol]()
def abstractFunctionForFunctionType(tp: Type) = {
assert(isFunctionType(tp), tp)
abstractFunctionType(tp.typeArgs.init, tp.typeArgs.last)
@@ -724,6 +799,44 @@ trait Definitions extends api.StandardDefinitions {
(sym eq PartialFunctionClass) || (sym eq AbstractPartialFunctionClass)
}
+ /** The single abstract method declared by type `tp` (or `NoSymbol` if it cannot be found).
+ *
+ * The method must be monomorphic and have exactly one parameter list.
+ * The class defining the method is a supertype of `tp` that
+ * has a public no-arg primary constructor.
+ */
+ def samOf(tp: Type): Symbol = {
+ // if tp has a constructor, it must be public and must not take any arguments
+ // (not even an implicit argument list -- to keep it simple for now)
+ val tpSym = tp.typeSymbol
+ val ctor = tpSym.primaryConstructor
+ val ctorOk = !ctor.exists || (!ctor.isOverloaded && ctor.isPublic && ctor.info.params.isEmpty && ctor.info.paramSectionCount <= 1)
+
+ if (tpSym.exists && ctorOk) {
+ // find the single abstract member, if there is one
+ // don't go out requiring DEFERRED members, as you will get them even if there's a concrete override:
+ // scala> abstract class X { def m: Int }
+ // scala> class Y extends X { def m: Int = 1}
+ // scala> typeOf[Y].deferredMembers
+ // Scopes(method m, method getClass)
+ //
+ // scala> typeOf[Y].members.filter(_.isDeferred)
+ // Scopes()
+ // must filter out "universal" members (getClass is deferred for some reason)
+ val deferredMembers = (
+ tp membersBasedOnFlags (excludedFlags = BridgeAndPrivateFlags, requiredFlags = METHOD)
+ filter (mem => mem.isDeferredNotDefault && !isUniversalMember(mem)) // TODO: test
+ )
+
+ // if there is only one, it's monomorphic and has a single argument list
+ if (deferredMembers.size == 1 &&
+ deferredMembers.head.typeParams.isEmpty &&
+ deferredMembers.head.info.paramSectionCount == 1)
+ deferredMembers.head
+ else NoSymbol
+ } else NoSymbol
+ }
+
def arrayType(arg: Type) = appliedType(ArrayClass, arg)
def byNameType(arg: Type) = appliedType(ByNameParamClass, arg)
def iteratorOfType(tp: Type) = appliedType(IteratorClass, tp)
@@ -1014,6 +1127,7 @@ trait Definitions extends api.StandardDefinitions {
lazy val ScalaInlineClass = requiredClass[scala.inline]
lazy val ScalaNoInlineClass = requiredClass[scala.noinline]
lazy val SerialVersionUIDAttr = requiredClass[scala.SerialVersionUID]
+ lazy val SerialVersionUIDAnnotation = AnnotationInfo(SerialVersionUIDAttr.tpe, List(Literal(Constant(0))), List())
lazy val SpecializedClass = requiredClass[scala.specialized]
lazy val ThrowsClass = requiredClass[scala.throws[_]]
lazy val TransientAttr = requiredClass[scala.transient]
diff --git a/src/reflect/scala/reflect/internal/Kinds.scala b/src/reflect/scala/reflect/internal/Kinds.scala
index d1c215713e..d48a6c6322 100644
--- a/src/reflect/scala/reflect/internal/Kinds.scala
+++ b/src/reflect/scala/reflect/internal/Kinds.scala
@@ -185,6 +185,7 @@ trait Kinds {
)
}
else {
+ hkarg.initialize // SI-7902 otherwise hkarg.typeParams yields List(NoSymbol)!
debuglog("checkKindBoundsHK recursing to compare params of "+ hkparam +" with "+ hkarg)
kindErrors ++= checkKindBoundsHK(
hkarg.typeParams,
diff --git a/src/reflect/scala/reflect/internal/Scopes.scala b/src/reflect/scala/reflect/internal/Scopes.scala
index 485d4d5ddd..1060b3a99c 100644
--- a/src/reflect/scala/reflect/internal/Scopes.scala
+++ b/src/reflect/scala/reflect/internal/Scopes.scala
@@ -221,8 +221,8 @@ trait Scopes extends api.Scopes { self: SymbolTable =>
/** Lookup a module or a class, filtering out matching names in scope
* which do not match that requirement.
*/
- def lookupModule(name: Name): Symbol = lookupAll(name.toTermName) find (_.isModule) getOrElse NoSymbol
- def lookupClass(name: Name): Symbol = lookupAll(name.toTypeName) find (_.isClass) getOrElse NoSymbol
+ def lookupModule(name: Name): Symbol = findSymbol(lookupAll(name.toTermName))(_.isModule)
+ def lookupClass(name: Name): Symbol = findSymbol(lookupAll(name.toTypeName))(_.isClass)
/** True if the name exists in this scope, false otherwise. */
def containsName(name: Name) = lookupEntry(name) != null
diff --git a/src/reflect/scala/reflect/internal/SymbolPairs.scala b/src/reflect/scala/reflect/internal/SymbolPairs.scala
new file mode 100644
index 0000000000..b538648b36
--- /dev/null
+++ b/src/reflect/scala/reflect/internal/SymbolPairs.scala
@@ -0,0 +1,302 @@
+/* NSC -- new Scala compiler
+ * Copyright 2005-2013 LAMP/EPFL
+ * @author Paul Phillips
+ */
+
+package scala
+package reflect
+package internal
+
+import scala.collection.mutable
+import Flags._
+import util.HashSet
+import scala.annotation.tailrec
+
+/** An abstraction for considering symbol pairs.
+ * One of the greatest sources of compiler bugs is that symbols can
+ * trivially lose their prefixes and turn into some completely different
+ * type with the smallest of errors. It is the exception not the rule
+ * that type comparisons are done correctly.
+ *
+ * This offers a small step toward coherence with two abstractions
+ * which come up over and over again:
+ *
+ * RelativeTo: operations relative to a prefix
+ * SymbolPair: two symbols being related somehow, plus the class
+ * in which the relation is being performed
+ *
+ * This is only a start, but it is a start.
+ */
+abstract class SymbolPairs {
+ val global: SymbolTable
+ import global._
+
+ /** Type operations relative to a prefix. All operations work on Symbols,
+ * and the types are the member types of those symbols in the prefix.
+ */
+ class RelativeTo(val prefix: Type) {
+ def this(clazz: Symbol) = this(clazz.thisType)
+ import scala.language.implicitConversions // geez, it even has to hassle me when it's private
+ private implicit def symbolToType(sym: Symbol): Type = prefix memberType sym
+
+ def erasureOf(sym: Symbol): Type = erasure.erasure(sym)(sym: Type)
+ def signature(sym: Symbol): String = sym defStringSeenAs (sym: Type)
+ def erasedSignature(sym: Symbol): String = sym defStringSeenAs erasureOf(sym)
+
+ def isSameType(sym1: Symbol, sym2: Symbol): Boolean = sym1 =:= sym2
+ def isSubType(sym1: Symbol, sym2: Symbol): Boolean = sym1 <:< sym2
+ def isSuperType(sym1: Symbol, sym2: Symbol): Boolean = sym2 <:< sym1
+ def isSameErasure(sym1: Symbol, sym2: Symbol): Boolean = erasureOf(sym1) =:= erasureOf(sym2)
+ def matches(sym1: Symbol, sym2: Symbol): Boolean = (sym1: Type) matches (sym2: Type)
+
+ override def toString = s"RelativeTo($prefix)"
+ }
+
+ /** Are types tp1 and tp2 equivalent seen from the perspective
+ * of `baseClass`? For instance List[Int] and Seq[Int] are =:=
+ * when viewed from IterableClass.
+ */
+ def sameInBaseClass(baseClass: Symbol)(tp1: Type, tp2: Type) =
+ (tp1 baseType baseClass) =:= (tp2 baseType baseClass)
+
+ case class SymbolPair(base: Symbol, low: Symbol, high: Symbol) {
+ def pos = if (low.owner == base) low.pos else if (high.owner == base) high.pos else base.pos
+ def self: Type = base.thisType
+ def rootType: Type = base.thisType
+
+ def lowType: Type = self memberType low
+ def lowErased: Type = erasure.specialErasure(base)(low.tpe)
+ def lowClassBound: Type = classBoundAsSeen(low.tpe.typeSymbol)
+
+ def highType: Type = self memberType high
+ def highInfo: Type = self memberInfo high
+ def highErased: Type = erasure.specialErasure(base)(high.tpe)
+ def highClassBound: Type = classBoundAsSeen(high.tpe.typeSymbol)
+
+ def isErroneous = low.tpe.isErroneous || high.tpe.isErroneous
+ def sameKind = sameLength(low.typeParams, high.typeParams)
+
+ private def classBoundAsSeen(tsym: Symbol) =
+ tsym.classBound.asSeenFrom(rootType, tsym.owner)
+
+ private def memberDefString(sym: Symbol, where: Boolean) = {
+ val def_s = (
+ if (sym.isConstructor) s"$sym: ${self memberType sym}"
+ else sym defStringSeenAs (self memberType sym)
+ )
+ def_s + whereString(sym)
+ }
+ /** A string like ' at line 55' if the symbol is defined in the class
+ * under consideration, or ' in trait Foo' if defined elsewhere.
+ */
+ private def whereString(sym: Symbol) =
+ if (sym.owner == base) " at line " + sym.pos.line else sym.locationString
+
+ def lowString = memberDefString(low, where = true)
+ def highString = memberDefString(high, where = true)
+
+ override def toString = sm"""
+ |Cursor(in $base) {
+ | high $highString
+ | erased $highErased
+ | infos ${high.infosString}
+ | low $lowString
+ | erased $lowErased
+ | infos ${low.infosString}
+ |}""".trim
+ }
+
+ /** The cursor class
+ * @param base the base class containing the participating symbols
+ */
+ abstract class Cursor(val base: Symbol) {
+ cursor =>
+
+ final val self = base.thisType // The type relative to which symbols are seen.
+ private val decls = newScope // all the symbols which can take part in a pair.
+ private val size = bases.length
+
+ /** A symbol for which exclude returns true will not appear as
+ * either end of a pair.
+ */
+ protected def exclude(sym: Symbol): Boolean
+
+ /** Does `sym1` match `sym2` such that (sym1, sym2) should be
+ * considered as a (lo, high) pair? Types always match. Term symbols
+ * match if their member types relative to `self` match.
+ */
+ protected def matches(sym1: Symbol, sym2: Symbol): Boolean
+
+ /** The parents and base classes of `base`. Can be refined in subclasses.
+ */
+ protected def parents: List[Type] = base.info.parents
+ protected def bases: List[Symbol] = base.info.baseClasses
+
+ /** An implementation of BitSets as arrays (maybe consider collection.BitSet
+ * for that?) The main purpose of this is to implement
+ * intersectionContainsElement efficiently.
+ */
+ private type BitSet = Array[Int]
+
+ /** A mapping from all base class indices to a bitset
+ * which indicates whether parents are subclasses.
+ *
+ * i \in subParents(j) iff
+ * exists p \in parents, b \in baseClasses:
+ * i = index(p)
+ * j = index(b)
+ * p isSubClass b
+ * p.baseType(b) == self.baseType(b)
+ */
+ private val subParents = new Array[BitSet](size)
+
+ /** A map from baseclasses of <base> to ints, with smaller ints meaning lower in
+ * linearization order. Symbols that are not baseclasses map to -1.
+ */
+ private val index = new mutable.HashMap[Symbol, Int] { override def default(key: Symbol) = -1 }
+
+ /** The scope entries that have already been visited as highSymbol
+ * (but may have been excluded via hasCommonParentAsSubclass.)
+ * These will not appear as lowSymbol.
+ */
+ private val visited = HashSet[ScopeEntry]("visited", 64)
+
+ /** Initialization has to run now so decls is populated before
+ * the declaration of curEntry.
+ */
+ init()
+
+ // The current low and high symbols; the high may be null.
+ private[this] var lowSymbol: Symbol = _
+ private[this] var highSymbol: Symbol = _
+
+ // The current entry candidates for low and high symbol.
+ private[this] var curEntry = decls.elems
+ private[this] var nextEntry = curEntry
+
+ // These fields are initially populated with a call to next().
+ next()
+
+ // populate the above data structures
+ private def init() {
+ // Fill `decls` with lower symbols shadowing higher ones
+ def fillDecls(bcs: List[Symbol], deferred: Boolean) {
+ if (!bcs.isEmpty) {
+ fillDecls(bcs.tail, deferred)
+ var e = bcs.head.info.decls.elems
+ while (e ne null) {
+ if (e.sym.initialize.isDeferred == deferred && !exclude(e.sym))
+ decls enter e.sym
+ e = e.next
+ }
+ }
+ }
+ var i = 0
+ for (bc <- bases) {
+ index(bc) = i
+ subParents(i) = new BitSet(size)
+ i += 1
+ }
+ for (p <- parents) {
+ val pIndex = index(p.typeSymbol)
+ if (pIndex >= 0)
+ for (bc <- p.baseClasses ; if sameInBaseClass(bc)(p, self)) {
+ val bcIndex = index(bc)
+ if (bcIndex >= 0)
+ include(subParents(bcIndex), pIndex)
+ }
+ }
+ // first, deferred (this will need to change if we change lookup rules!)
+ fillDecls(bases, deferred = true)
+ // then, concrete.
+ fillDecls(bases, deferred = false)
+ }
+
+ private def include(bs: BitSet, n: Int) {
+ val nshifted = n >> 5
+ val nmask = 1 << (n & 31)
+ bs(nshifted) |= nmask
+ }
+
+ /** Implements `bs1 * bs2 * {0..n} != 0.
+ * Used in hasCommonParentAsSubclass */
+ private def intersectionContainsElementLeq(bs1: BitSet, bs2: BitSet, n: Int): Boolean = {
+ val nshifted = n >> 5
+ val nmask = 1 << (n & 31)
+ var i = 0
+ while (i < nshifted) {
+ if ((bs1(i) & bs2(i)) != 0) return true
+ i += 1
+ }
+ (bs1(nshifted) & bs2(nshifted) & (nmask | nmask - 1)) != 0
+ }
+
+ /** Do `sym1` and `sym2` have a common subclass in `parents`?
+ * In that case we do not follow their pairs.
+ */
+ private def hasCommonParentAsSubclass(sym1: Symbol, sym2: Symbol) = {
+ val index1 = index(sym1.owner)
+ (index1 >= 0) && {
+ val index2 = index(sym2.owner)
+ (index2 >= 0) && {
+ intersectionContainsElementLeq(
+ subParents(index1), subParents(index2), index1 min index2)
+ }
+ }
+ }
+
+ @tailrec private def advanceNextEntry() {
+ if (nextEntry ne null) {
+ nextEntry = decls lookupNextEntry nextEntry
+ if (nextEntry ne null) {
+ val high = nextEntry.sym
+ val isMatch = matches(lowSymbol, high) && { visited addEntry nextEntry ; true } // side-effect visited on all matches
+
+ // skip nextEntry if a class in `parents` is a subclass of the
+ // owners of both low and high.
+ if (isMatch && !hasCommonParentAsSubclass(lowSymbol, high))
+ highSymbol = high
+ else
+ advanceNextEntry()
+ }
+ }
+ }
+ @tailrec private def advanceCurEntry() {
+ if (curEntry ne null) {
+ curEntry = curEntry.next
+ if (curEntry ne null) {
+ if (visited(curEntry) || exclude(curEntry.sym))
+ advanceCurEntry()
+ else
+ nextEntry = curEntry
+ }
+ }
+ }
+
+ /** The `low` and `high` symbol. In the context of overriding pairs,
+ * low == overriding and high == overridden.
+ */
+ def low = lowSymbol
+ def high = highSymbol
+
+ def hasNext = curEntry ne null
+ def currentPair = new SymbolPair(base, low, high)
+ def iterator = new Iterator[SymbolPair] {
+ def hasNext = cursor.hasNext
+ def next() = try cursor.currentPair finally cursor.next()
+ }
+
+ // Note that next is called once during object initialization to
+ // populate the fields tracking the current symbol pair.
+ def next() {
+ if (curEntry ne null) {
+ lowSymbol = curEntry.sym
+ advanceNextEntry() // sets highSymbol
+ if (nextEntry eq null) {
+ advanceCurEntry()
+ next()
+ }
+ }
+ }
+ }
+}
diff --git a/src/reflect/scala/reflect/internal/SymbolTable.scala b/src/reflect/scala/reflect/internal/SymbolTable.scala
index a6f9dfc164..98466ebb2b 100644
--- a/src/reflect/scala/reflect/internal/SymbolTable.scala
+++ b/src/reflect/scala/reflect/internal/SymbolTable.scala
@@ -41,6 +41,7 @@ abstract class SymbolTable extends macros.Universe
with StdCreators
with BuildUtils
with PrivateWithin
+ with pickling.Translations
{
val gen = new TreeGen { val global: SymbolTable.this.type = SymbolTable.this }
@@ -124,6 +125,10 @@ abstract class SymbolTable extends macros.Universe
result
}
+ @inline final def findSymbol(xs: TraversableOnce[Symbol])(p: Symbol => Boolean): Symbol = {
+ xs find p getOrElse NoSymbol
+ }
+
// For too long have we suffered in order to sort NAMES.
// I'm pretty sure there's a reasonable default for that.
// Notice challenge created by Ordering's invariance.
diff --git a/src/reflect/scala/reflect/internal/Symbols.scala b/src/reflect/scala/reflect/internal/Symbols.scala
index 14d742fc2c..71de02ef9e 100644
--- a/src/reflect/scala/reflect/internal/Symbols.scala
+++ b/src/reflect/scala/reflect/internal/Symbols.scala
@@ -1859,6 +1859,8 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
*/
def thisSym: Symbol = this
+ def hasSelfType = thisSym.tpeHK != this.tpeHK
+
/** The type of `this` in a class, or else the type of the symbol itself. */
def typeOfThis = thisSym.tpe_*
@@ -3471,8 +3473,8 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
assert((prev eq null) || phaseId(validFrom) > phaseId(prev.validFrom), this)
assert(validFrom != NoPeriod, this)
- override def toString() =
- "TypeHistory(" + phaseOf(validFrom)+":"+runId(validFrom) + "," + info + "," + prev + ")"
+ private def phaseString = "%s: %s".format(phaseOf(validFrom), info)
+ override def toString = toList reverseMap (_.phaseString) mkString ", "
def toList: List[TypeHistory] = this :: ( if (prev eq null) Nil else prev.toList )
diff --git a/src/reflect/scala/reflect/internal/Trees.scala b/src/reflect/scala/reflect/internal/Trees.scala
index ccf5cf5249..9adddeed50 100644
--- a/src/reflect/scala/reflect/internal/Trees.scala
+++ b/src/reflect/scala/reflect/internal/Trees.scala
@@ -8,10 +8,12 @@ package reflect
package internal
import Flags._
-import scala.collection.mutable.{ListBuffer, LinkedHashSet}
+import pickling.PickleFormat._
+import scala.collection.{ mutable, immutable }
import util.Statistics
-trait Trees extends api.Trees { self: SymbolTable =>
+trait Trees extends api.Trees {
+ self: SymbolTable =>
private[scala] var nodeCount = 0
@@ -160,7 +162,7 @@ trait Trees extends api.Trees { self: SymbolTable =>
override def freeTypes: List[FreeTypeSymbol] = freeSyms[FreeTypeSymbol](_.isFreeType, _.typeSymbol)
private def freeSyms[S <: Symbol](isFree: Symbol => Boolean, symOfType: Type => Symbol): List[S] = {
- val s = scala.collection.mutable.LinkedHashSet[S]()
+ val s = mutable.LinkedHashSet[S]()
def addIfFree(sym: Symbol): Unit = if (sym != null && isFree(sym)) s += sym.asInstanceOf[S]
for (t <- this) {
addIfFree(t.symbol)
@@ -1019,18 +1021,22 @@ trait Trees extends api.Trees { self: SymbolTable =>
}
trait CannotHaveAttrs extends Tree {
- override def canHaveAttrs = false
-
- private def requireLegal(value: Any, allowed: Any, what: String) =
- require(value == allowed, s"can't set $what for $self to value other than $allowed")
-
super.setPos(NoPosition)
+ super.setType(NoType)
+
+ override def canHaveAttrs = false
override def setPos(pos: Position) = { requireLegal(pos, NoPosition, "pos"); this }
override def pos_=(pos: Position) = setPos(pos)
-
- super.setType(NoType)
override def setType(t: Type) = { requireLegal(t, NoType, "tpe"); this }
override def tpe_=(t: Type) = setType(t)
+
+ private def requireLegal(value: Any, allowed: Any, what: String) = (
+ if (value != allowed) {
+ log(s"can't set $what for $self to value other than $allowed")
+ if (settings.debug && settings.developer)
+ (new Throwable).printStackTrace
+ }
+ )
}
case object EmptyTree extends TermTree with CannotHaveAttrs { override def isEmpty = true; val asList = List(this) }
@@ -1159,113 +1165,136 @@ trait Trees extends api.Trees { self: SymbolTable =>
override protected def itraverse(traverser: Traverser, tree: Tree): Unit = {
import traverser._
- tree match {
- case EmptyTree =>
- ;
- case PackageDef(pid, stats) =>
- traverse(pid)
- atOwner(mclass(tree.symbol)) {
- traverseTrees(stats)
- }
- case ClassDef(mods, name, tparams, impl) =>
- atOwner(tree.symbol) {
- traverseTrees(mods.annotations); traverseTrees(tparams); traverse(impl)
- }
- case ModuleDef(mods, name, impl) =>
- atOwner(mclass(tree.symbol)) {
- traverseTrees(mods.annotations); traverse(impl)
- }
- case ValDef(mods, name, tpt, rhs) =>
- atOwner(tree.symbol) {
- traverseTrees(mods.annotations); traverse(tpt); traverse(rhs)
- }
- case DefDef(mods, name, tparams, vparamss, tpt, rhs) =>
- atOwner(tree.symbol) {
- traverseTrees(mods.annotations); traverseTrees(tparams); traverseTreess(vparamss); traverse(tpt); traverse(rhs)
- }
- case TypeDef(mods, name, tparams, rhs) =>
- atOwner(tree.symbol) {
- traverseTrees(mods.annotations); traverseTrees(tparams); traverse(rhs)
- }
+
+ def traverseMemberDef(md: MemberDef, owner: Symbol): Unit = atOwner(owner) {
+ traverseModifiers(md.mods)
+ traverseName(md.name)
+ md match {
+ case ClassDef(_, _, tparams, impl) => traverseParams(tparams) ; traverse(impl)
+ case ModuleDef(_, _, impl) => traverse(impl)
+ case ValDef(_, _, tpt, rhs) => traverseTypeAscription(tpt) ; traverse(rhs)
+ case TypeDef(_, _, tparams, rhs) => traverseParams(tparams) ; traverse(rhs)
+ case DefDef(_, _, tparams, vparamss, tpt, rhs) =>
+ traverseParams(tparams)
+ traverseParamss(vparamss)
+ traverseTypeAscription(tpt)
+ traverse(rhs)
+ }
+ }
+ def traverseComponents(): Unit = tree match {
case LabelDef(name, params, rhs) =>
- traverseTrees(params); traverse(rhs)
+ traverseName(name)
+ traverseParams(params)
+ traverse(rhs)
case Import(expr, selectors) =>
traverse(expr)
+ selectors foreach traverseImportSelector
case Annotated(annot, arg) =>
- traverse(annot); traverse(arg)
+ traverse(annot)
+ traverse(arg)
case Template(parents, self, body) =>
- traverseTrees(parents)
- if (self ne noSelfType) traverse(self)
+ traverseParents(parents)
+ traverseSelfType(self)
traverseStats(body, tree.symbol)
case Block(stats, expr) =>
- traverseTrees(stats); traverse(expr)
+ traverseTrees(stats)
+ traverse(expr)
case CaseDef(pat, guard, body) =>
- traverse(pat); traverse(guard); traverse(body)
+ traversePattern(pat)
+ traverseGuard(guard)
+ traverse(body)
case Alternative(trees) =>
traverseTrees(trees)
case Star(elem) =>
traverse(elem)
case Bind(name, body) =>
+ traverseName(name)
traverse(body)
case UnApply(fun, args) =>
- traverse(fun); traverseTrees(args)
+ traverse(fun)
+ traverseTrees(args)
case ArrayValue(elemtpt, trees) =>
- traverse(elemtpt); traverseTrees(trees)
- case Function(vparams, body) =>
- atOwner(tree.symbol) {
- traverseTrees(vparams); traverse(body)
- }
+ traverse(elemtpt)
+ traverseTrees(trees)
case Assign(lhs, rhs) =>
- traverse(lhs); traverse(rhs)
+ traverse(lhs)
+ traverse(rhs)
case AssignOrNamedArg(lhs, rhs) =>
- traverse(lhs); traverse(rhs)
+ traverse(lhs)
+ traverse(rhs)
case If(cond, thenp, elsep) =>
- traverse(cond); traverse(thenp); traverse(elsep)
+ traverse(cond)
+ traverse(thenp)
+ traverse(elsep)
case Match(selector, cases) =>
- traverse(selector); traverseTrees(cases)
+ traverse(selector)
+ traverseCases(cases)
case Return(expr) =>
traverse(expr)
case Try(block, catches, finalizer) =>
- traverse(block); traverseTrees(catches); traverse(finalizer)
+ traverse(block)
+ traverseCases(catches)
+ traverse(finalizer)
case Throw(expr) =>
traverse(expr)
case New(tpt) =>
traverse(tpt)
case Typed(expr, tpt) =>
- traverse(expr); traverse(tpt)
+ traverse(expr)
+ traverseTypeAscription(tpt)
case TypeApply(fun, args) =>
- traverse(fun); traverseTrees(args)
+ traverse(fun)
+ traverseTypeArgs(args)
case Apply(fun, args) =>
- traverse(fun); traverseTrees(args)
+ traverse(fun)
+ traverseTrees(args)
case ApplyDynamic(qual, args) =>
- traverse(qual); traverseTrees(args)
- case Super(qual, _) =>
traverse(qual)
- case This(_) =>
- ;
+ traverseTrees(args)
+ case Super(qual, mix) =>
+ traverse(qual)
+ traverseName(mix)
+ case This(qual) =>
+ traverseName(qual)
case Select(qualifier, selector) =>
traverse(qualifier)
- case Ident(_) =>
- ;
+ traverseName(selector)
+ case Ident(name) =>
+ traverseName(name)
case ReferenceToBoxed(idt) =>
traverse(idt)
- case Literal(_) =>
- ;
+ case Literal(const) =>
+ traverseConstant(const)
case TypeTree() =>
;
case SingletonTypeTree(ref) =>
traverse(ref)
case SelectFromTypeTree(qualifier, selector) =>
traverse(qualifier)
+ traverseName(selector)
case CompoundTypeTree(templ) =>
traverse(templ)
case AppliedTypeTree(tpt, args) =>
- traverse(tpt); traverseTrees(args)
+ traverse(tpt)
+ traverseTypeArgs(args)
case TypeBoundsTree(lo, hi) =>
- traverse(lo); traverse(hi)
+ traverse(lo)
+ traverse(hi)
case ExistentialTypeTree(tpt, whereClauses) =>
- traverse(tpt); traverseTrees(whereClauses)
- case _ => xtraverse(traverser, tree)
+ traverse(tpt)
+ traverseTrees(whereClauses)
+ case _ =>
+ xtraverse(traverser, tree)
+ }
+
+ if (tree.canHaveAttrs) {
+ tree match {
+ case PackageDef(pid, stats) => traverse(pid) ; traverseStats(stats, mclass(tree.symbol))
+ case md: ModuleDef => traverseMemberDef(md, mclass(tree.symbol))
+ case md: MemberDef => traverseMemberDef(md, tree.symbol)
+ case Function(vparams, body) => atOwner(tree.symbol) { traverseParams(vparams) ; traverse(body) }
+ case _ => traverseComponents()
+ }
}
}
@@ -1563,7 +1592,7 @@ trait Trees extends api.Trees { self: SymbolTable =>
}
class FilterTreeTraverser(p: Tree => Boolean) extends Traverser {
- val hits = new ListBuffer[Tree]
+ val hits = mutable.ListBuffer[Tree]()
override def traverse(t: Tree) {
if (p(t)) hits += t
super.traverse(t)
@@ -1571,7 +1600,7 @@ trait Trees extends api.Trees { self: SymbolTable =>
}
class CollectTreeTraverser[T](pf: PartialFunction[Tree, T]) extends Traverser {
- val results = new ListBuffer[T]
+ val results = mutable.ListBuffer[T]()
override def traverse(t: Tree) {
if (pf.isDefinedAt(t)) results += pf(t)
super.traverse(t)
@@ -1758,59 +1787,59 @@ trait Trees extends api.Trees { self: SymbolTable =>
// -------------- Classtags --------------------------------------------------------
- implicit val TreeTag = ClassTag[Tree](classOf[Tree])
- implicit val TermTreeTag = ClassTag[TermTree](classOf[TermTree])
- implicit val TypTreeTag = ClassTag[TypTree](classOf[TypTree])
- implicit val SymTreeTag = ClassTag[SymTree](classOf[SymTree])
- implicit val NameTreeTag = ClassTag[NameTree](classOf[NameTree])
- implicit val RefTreeTag = ClassTag[RefTree](classOf[RefTree])
- implicit val DefTreeTag = ClassTag[DefTree](classOf[DefTree])
- implicit val MemberDefTag = ClassTag[MemberDef](classOf[MemberDef])
- implicit val PackageDefTag = ClassTag[PackageDef](classOf[PackageDef])
- implicit val ImplDefTag = ClassTag[ImplDef](classOf[ImplDef])
- implicit val ClassDefTag = ClassTag[ClassDef](classOf[ClassDef])
- implicit val ModuleDefTag = ClassTag[ModuleDef](classOf[ModuleDef])
- implicit val ValOrDefDefTag = ClassTag[ValOrDefDef](classOf[ValOrDefDef])
- implicit val ValDefTag = ClassTag[ValDef](classOf[ValDef])
- implicit val DefDefTag = ClassTag[DefDef](classOf[DefDef])
- implicit val TypeDefTag = ClassTag[TypeDef](classOf[TypeDef])
- implicit val LabelDefTag = ClassTag[LabelDef](classOf[LabelDef])
- implicit val ImportSelectorTag = ClassTag[ImportSelector](classOf[ImportSelector])
- implicit val ImportTag = ClassTag[Import](classOf[Import])
- implicit val TemplateTag = ClassTag[Template](classOf[Template])
- implicit val BlockTag = ClassTag[Block](classOf[Block])
- implicit val CaseDefTag = ClassTag[CaseDef](classOf[CaseDef])
- implicit val AlternativeTag = ClassTag[Alternative](classOf[Alternative])
- implicit val StarTag = ClassTag[Star](classOf[Star])
- implicit val BindTag = ClassTag[Bind](classOf[Bind])
- implicit val UnApplyTag = ClassTag[UnApply](classOf[UnApply])
- implicit val FunctionTag = ClassTag[Function](classOf[Function])
- implicit val AssignTag = ClassTag[Assign](classOf[Assign])
- implicit val AssignOrNamedArgTag = ClassTag[AssignOrNamedArg](classOf[AssignOrNamedArg])
- implicit val IfTag = ClassTag[If](classOf[If])
- implicit val MatchTag = ClassTag[Match](classOf[Match])
- implicit val ReturnTag = ClassTag[Return](classOf[Return])
- implicit val TryTag = ClassTag[Try](classOf[Try])
- implicit val ThrowTag = ClassTag[Throw](classOf[Throw])
- implicit val NewTag = ClassTag[New](classOf[New])
- implicit val TypedTag = ClassTag[Typed](classOf[Typed])
- implicit val GenericApplyTag = ClassTag[GenericApply](classOf[GenericApply])
- implicit val TypeApplyTag = ClassTag[TypeApply](classOf[TypeApply])
- implicit val ApplyTag = ClassTag[Apply](classOf[Apply])
- implicit val SuperTag = ClassTag[Super](classOf[Super])
- implicit val ThisTag = ClassTag[This](classOf[This])
- implicit val SelectTag = ClassTag[Select](classOf[Select])
- implicit val IdentTag = ClassTag[Ident](classOf[Ident])
- implicit val ReferenceToBoxedTag = ClassTag[ReferenceToBoxed](classOf[ReferenceToBoxed])
- implicit val LiteralTag = ClassTag[Literal](classOf[Literal])
- implicit val AnnotatedTag = ClassTag[Annotated](classOf[Annotated])
- implicit val SingletonTypeTreeTag = ClassTag[SingletonTypeTree](classOf[SingletonTypeTree])
- implicit val SelectFromTypeTreeTag = ClassTag[SelectFromTypeTree](classOf[SelectFromTypeTree])
- implicit val CompoundTypeTreeTag = ClassTag[CompoundTypeTree](classOf[CompoundTypeTree])
- implicit val AppliedTypeTreeTag = ClassTag[AppliedTypeTree](classOf[AppliedTypeTree])
- implicit val TypeBoundsTreeTag = ClassTag[TypeBoundsTree](classOf[TypeBoundsTree])
+ implicit val AlternativeTag = ClassTag[Alternative](classOf[Alternative])
+ implicit val AnnotatedTag = ClassTag[Annotated](classOf[Annotated])
+ implicit val AppliedTypeTreeTag = ClassTag[AppliedTypeTree](classOf[AppliedTypeTree])
+ implicit val ApplyTag = ClassTag[Apply](classOf[Apply])
+ implicit val AssignOrNamedArgTag = ClassTag[AssignOrNamedArg](classOf[AssignOrNamedArg])
+ implicit val AssignTag = ClassTag[Assign](classOf[Assign])
+ implicit val BindTag = ClassTag[Bind](classOf[Bind])
+ implicit val BlockTag = ClassTag[Block](classOf[Block])
+ implicit val CaseDefTag = ClassTag[CaseDef](classOf[CaseDef])
+ implicit val ClassDefTag = ClassTag[ClassDef](classOf[ClassDef])
+ implicit val CompoundTypeTreeTag = ClassTag[CompoundTypeTree](classOf[CompoundTypeTree])
+ implicit val DefDefTag = ClassTag[DefDef](classOf[DefDef])
+ implicit val DefTreeTag = ClassTag[DefTree](classOf[DefTree])
implicit val ExistentialTypeTreeTag = ClassTag[ExistentialTypeTree](classOf[ExistentialTypeTree])
- implicit val TypeTreeTag = ClassTag[TypeTree](classOf[TypeTree])
+ implicit val FunctionTag = ClassTag[Function](classOf[Function])
+ implicit val GenericApplyTag = ClassTag[GenericApply](classOf[GenericApply])
+ implicit val IdentTag = ClassTag[Ident](classOf[Ident])
+ implicit val IfTag = ClassTag[If](classOf[If])
+ implicit val ImplDefTag = ClassTag[ImplDef](classOf[ImplDef])
+ implicit val ImportSelectorTag = ClassTag[ImportSelector](classOf[ImportSelector])
+ implicit val ImportTag = ClassTag[Import](classOf[Import])
+ implicit val LabelDefTag = ClassTag[LabelDef](classOf[LabelDef])
+ implicit val LiteralTag = ClassTag[Literal](classOf[Literal])
+ implicit val MatchTag = ClassTag[Match](classOf[Match])
+ implicit val MemberDefTag = ClassTag[MemberDef](classOf[MemberDef])
+ implicit val ModuleDefTag = ClassTag[ModuleDef](classOf[ModuleDef])
+ implicit val NameTreeTag = ClassTag[NameTree](classOf[NameTree])
+ implicit val NewTag = ClassTag[New](classOf[New])
+ implicit val PackageDefTag = ClassTag[PackageDef](classOf[PackageDef])
+ implicit val RefTreeTag = ClassTag[RefTree](classOf[RefTree])
+ implicit val ReferenceToBoxedTag = ClassTag[ReferenceToBoxed](classOf[ReferenceToBoxed])
+ implicit val ReturnTag = ClassTag[Return](classOf[Return])
+ implicit val SelectFromTypeTreeTag = ClassTag[SelectFromTypeTree](classOf[SelectFromTypeTree])
+ implicit val SelectTag = ClassTag[Select](classOf[Select])
+ implicit val SingletonTypeTreeTag = ClassTag[SingletonTypeTree](classOf[SingletonTypeTree])
+ implicit val StarTag = ClassTag[Star](classOf[Star])
+ implicit val SuperTag = ClassTag[Super](classOf[Super])
+ implicit val SymTreeTag = ClassTag[SymTree](classOf[SymTree])
+ implicit val TemplateTag = ClassTag[Template](classOf[Template])
+ implicit val TermTreeTag = ClassTag[TermTree](classOf[TermTree])
+ implicit val ThisTag = ClassTag[This](classOf[This])
+ implicit val ThrowTag = ClassTag[Throw](classOf[Throw])
+ implicit val TreeTag = ClassTag[Tree](classOf[Tree])
+ implicit val TryTag = ClassTag[Try](classOf[Try])
+ implicit val TypTreeTag = ClassTag[TypTree](classOf[TypTree])
+ implicit val TypeApplyTag = ClassTag[TypeApply](classOf[TypeApply])
+ implicit val TypeBoundsTreeTag = ClassTag[TypeBoundsTree](classOf[TypeBoundsTree])
+ implicit val TypeDefTag = ClassTag[TypeDef](classOf[TypeDef])
+ implicit val TypeTreeTag = ClassTag[TypeTree](classOf[TypeTree])
+ implicit val TypedTag = ClassTag[Typed](classOf[Typed])
+ implicit val UnApplyTag = ClassTag[UnApply](classOf[UnApply])
+ implicit val ValDefTag = ClassTag[ValDef](classOf[ValDef])
+ implicit val ValOrDefDefTag = ClassTag[ValOrDefDef](classOf[ValOrDefDef])
val treeNodeCount = Statistics.newView("#created tree nodes")(nodeCount)
}
diff --git a/src/reflect/scala/reflect/internal/Types.scala b/src/reflect/scala/reflect/internal/Types.scala
index 4367e51041..9344212294 100644
--- a/src/reflect/scala/reflect/internal/Types.scala
+++ b/src/reflect/scala/reflect/internal/Types.scala
@@ -18,6 +18,7 @@ import util.Statistics
import util.ThreeValues._
import Variance._
import Depth._
+import TypeConstants._
/* A standard type pattern match:
case ErrorType =>
@@ -90,10 +91,6 @@ trait Types
private var explainSwitch = false
private final val emptySymbolSet = immutable.Set.empty[Symbol]
- protected[internal] final val DefaultLogThreshhold = 50
- private final val LogPendingBaseTypesThreshold = DefaultLogThreshhold
- private final val LogVolatileThreshold = DefaultLogThreshhold
-
private final val traceTypeVars = sys.props contains "scalac.debug.tvar"
private final val breakCycles = settings.breakCycles.value
/** In case anyone wants to turn off type parameter bounds being used
@@ -142,8 +139,6 @@ trait Types
override def typeConstructor: Type = underlying.typeConstructor
override def isError = underlying.isError
override def isErroneous = underlying.isErroneous
- override def isStable: Boolean = underlying.isStable
- override def isVolatile = underlying.isVolatile
override def paramSectionCount = underlying.paramSectionCount
override def paramss = underlying.paramss
override def params = underlying.params
@@ -270,7 +265,7 @@ trait Types
def takesTypeArgs: Boolean = this.isHigherKinded
/** Does this type denote a stable reference (i.e. singleton type)? */
- def isStable: Boolean = false
+ final def isStable: Boolean = definitions isStable this
/** Is this type dangerous (i.e. it might contain conflicting
* type information when empty, so that it can be constructed
@@ -278,7 +273,7 @@ trait Types
* type of the form T_1 with T_n { decls }, where one of the
* T_i (i > 1) is an abstract type.
*/
- def isVolatile: Boolean = false
+ final def isVolatile: Boolean = definitions isVolatile this
/** Is this type a structural refinement type (it ''refines'' members that have not been inherited) */
def isStructuralRefinement: Boolean = false
@@ -979,6 +974,18 @@ trait Types
else (baseClasses.head.newOverloaded(this, alts))
}
+ /** Find all members meeting the flag requirements.
+ *
+ * If you require a DEFERRED member, you will get it if it exists -- even if there's an overriding concrete member.
+ * If you exclude DEFERRED members, or don't specify any requirements,
+ * you won't get deferred members (whether they have an overriding concrete member or not)
+ *
+ * Thus, findMember requiring DEFERRED flags yields deferred members,
+ * while `findMember(excludedFlags = 0, requiredFlags = 0).filter(_.isDeferred)` may not (if there's a corresponding concrete member)
+ *
+ * Requirements take precedence over exclusions, so requiring and excluding DEFERRED will yield a DEFERRED member (if there is one).
+ *
+ */
def findMembers(excludedFlags: Long, requiredFlags: Long): Scope = {
def findMembersInternal: Scope = {
var members: Scope = null
@@ -988,10 +995,10 @@ trait Types
//Console.println("find member " + name.decode + " in " + this + ":" + this.baseClasses)//DEBUG
var required = requiredFlags
var excluded = excludedFlags | DEFERRED
- var continue = true
+ var retryForDeferred = true
var self: Type = null
- while (continue) {
- continue = false
+ while (retryForDeferred) {
+ retryForDeferred = false
val bcs0 = baseClasses
var bcs = bcs0
while (!bcs.isEmpty) {
@@ -1023,7 +1030,7 @@ trait Types
}
if (others eq null) members enter sym
} else if (excl == DEFERRED) {
- continue = true
+ retryForDeferred = (excludedFlags & DEFERRED) == 0
}
}
entry = entry.next
@@ -1033,7 +1040,7 @@ trait Types
} // while (!bcs.isEmpty)
required |= DEFERRED
excluded &= ~(DEFERRED.toLong)
- } // while (continue)
+ } // while (retryForDeferred)
if (Statistics.canEnable) Statistics.popTimer(typeOpsStack, start)
if (members eq null) EmptyScope else members
}
@@ -1221,8 +1228,6 @@ trait Types
abstract class SingletonType extends SubType with SimpleTypeProxy {
def supertype = underlying
override def isTrivial = false
- override def isStable = true
- override def isVolatile = underlying.isVolatile
override def widen: Type = underlying.widen
override def baseTypeSeq: BaseTypeSeq = {
if (Statistics.canEnable) Statistics.incCounter(singletonBaseTypeSeqCount)
@@ -1300,7 +1305,6 @@ trait Types
/** An object representing a non-existing prefix */
case object NoPrefix extends Type {
override def isTrivial: Boolean = true
- override def isStable: Boolean = true
override def prefixString = ""
override def safeToString: String = "<noprefix>"
override def kind = "NoPrefixType"
@@ -1318,7 +1322,6 @@ trait Types
override def isTrivial: Boolean = sym.isPackageClass
override def typeSymbol = sym
override def underlying: Type = sym.typeOfThis
- override def isVolatile = false
override def isHigherKinded = sym.isRefinementClass && underlying.isHigherKinded
override def prefixString =
if (settings.debug) sym.nameString + ".this."
@@ -1367,8 +1370,6 @@ trait Types
// more precise conceptually, but causes cyclic errors: (paramss exists (_ contains sym))
override def isImmediatelyDependent = (sym ne NoSymbol) && (sym.owner.isMethod && sym.isValueParameter)
-
- override def isVolatile : Boolean = underlying.isVolatile && (sym.hasVolatileType || !sym.isStable)
/*
override def narrow: Type = {
if (phase.erasedTypes) this
@@ -1482,6 +1483,14 @@ trait Types
}
}
+ object CompoundType {
+ def unapply(tp: Type): Option[(List[Type], Scope, Symbol)] = tp match {
+ case ClassInfoType(parents, decls, clazz) => Some((parents, decls, clazz))
+ case RefinedType(parents, decls) => Some((parents, decls, tp.typeSymbol))
+ case _ => None
+ }
+ }
+
/** A common base class for intersection types and class types
*/
abstract class CompoundType extends Type {
@@ -1764,33 +1773,6 @@ trait Types
typeSymbol))
} else super.normalize
}
-
- /** A refined type P1 with ... with Pn { decls } is volatile if
- * one of the parent types Pi is an abstract type, and
- * either i > 1, or decls or a following parent Pj, j > 1, contributes
- * an abstract member.
- * A type contributes an abstract member if it has an abstract member which
- * is also a member of the whole refined type. A scope `decls` contributes
- * an abstract member if it has an abstract definition which is also
- * a member of the whole type.
- */
- override def isVolatile = {
- def isVisible(m: Symbol) =
- this.nonPrivateMember(m.name).alternatives contains m
- def contributesAbstractMembers(p: Type) =
- p.deferredMembers exists isVisible
-
- ((parents exists (_.isVolatile))
- ||
- (parents dropWhile (! _.typeSymbol.isAbstractType) match {
- case ps @ (_ :: ps1) =>
- (ps ne parents) ||
- (ps1 exists contributesAbstractMembers) ||
- (decls.iterator exists (m => m.isDeferred && isVisible(m)))
- case _ =>
- false
- }))
- }
override def kind = "RefinedType"
}
@@ -2026,7 +2008,6 @@ trait Types
class ModuleTypeRef(pre0: Type, sym0: Symbol) extends NoArgsTypeRef(pre0, sym0) with ClassTypeRef {
require(sym.isModuleClass, sym)
private[this] var narrowedCache: Type = _
- override def isStable = pre.isStable
override def narrow = {
if (narrowedCache eq null)
narrowedCache = singleType(pre, sym.sourceModule)
@@ -2041,7 +2022,6 @@ trait Types
}
class PackageTypeRef(pre0: Type, sym0: Symbol) extends ModuleTypeRef(pre0, sym0) {
require(sym.isPackageClass, sym)
- override def isStable = true
override protected def finishPrefix(rest: String) = packagePrefix + rest
}
class RefinementTypeRef(pre0: Type, sym0: Symbol) extends NoArgsTypeRef(pre0, sym0) with ClassTypeRef {
@@ -2148,8 +2128,6 @@ trait Types
require(sym.isAliasType, sym)
override def dealias = if (typeParamsMatchArgs) betaReduce.dealias else super.dealias
- override def isStable = normalize.isStable
- override def isVolatile = normalize.isVolatile
override def narrow = normalize.narrow
override def thisInfo = normalize
override def prefix = if (this ne normalize) normalize.prefix else pre
@@ -2204,30 +2182,6 @@ trait Types
private var symInfoCache: Type = _
private var thisInfoCache: Type = _
- override def isVolatile = {
- // need to be careful not to fall into an infinite recursion here
- // because volatile checking is done before all cycles are detected.
- // the case to avoid is an abstract type directly or
- // indirectly upper-bounded by itself. See #2918
- try {
- volatileRecursions += 1
- if (volatileRecursions < LogVolatileThreshold)
- bounds.hi.isVolatile
- else if (pendingVolatiles(sym))
- true // we can return true here, because a cycle will be detected
- // here afterwards and an error will result anyway.
- else
- try {
- pendingVolatiles += sym
- bounds.hi.isVolatile
- } finally {
- pendingVolatiles -= sym
- }
- } finally {
- volatileRecursions -= 1
- }
- }
-
override def thisInfo = {
val symInfo = sym.info
if (thisInfoCache == null || (symInfo ne symInfoCache)) {
@@ -2242,7 +2196,6 @@ trait Types
}
thisInfoCache
}
- override def isStable = bounds.hi.typeSymbol isSubClass SingletonClass
override def bounds = thisInfo.bounds
override protected[Types] def baseTypeSeqImpl: BaseTypeSeq = transform(bounds.hi).baseTypeSeq prepend this
override def kind = "AbstractTypeRef"
@@ -2328,7 +2281,6 @@ trait Types
override def baseClasses = thisInfo.baseClasses
override def baseTypeSeqDepth = baseTypeSeq.maxDepth
- override def isStable = (sym eq NothingClass) || (sym eq SingletonClass)
override def prefix = pre
override def termSymbol = super.termSymbol
override def termSymbolDirect = super.termSymbol
@@ -2595,7 +2547,6 @@ trait Types
override def baseClasses: List[Symbol] = resultType.baseClasses
override def baseType(clazz: Symbol): Type = resultType.baseType(clazz)
override def boundSyms = resultType.boundSyms
- override def isVolatile = resultType.isVolatile
override def safeToString: String = "=> "+ resultType
override def kind = "NullaryMethodType"
}
@@ -2634,7 +2585,6 @@ trait Types
override def baseClasses: List[Symbol] = resultType.baseClasses
override def baseType(clazz: Symbol): Type = resultType.baseType(clazz)
override def narrow: Type = resultType.narrow
- override def isVolatile = resultType.isVolatile
/** @M: typeDefSig wraps a TypeBounds in a PolyType
* to represent a higher-kinded type parameter
@@ -2679,7 +2629,6 @@ trait Types
override protected def rewrap(newtp: Type) = existentialAbstraction(quantified, newtp)
override def isTrivial = false
- override def isStable: Boolean = false
override def bounds = TypeBounds(maybeRewrap(underlying.bounds.lo), maybeRewrap(underlying.bounds.hi))
override def parents = underlying.parents map maybeRewrap
override def boundSyms = quantified.toSet
@@ -3239,8 +3188,6 @@ trait Types
else super.normalize
)
override def typeSymbol = origin.typeSymbol
- override def isStable = origin.isStable
- override def isVolatile = origin.isVolatile
private def tparamsOfSym(sym: Symbol) = sym.info match {
case PolyType(tparams, _) if tparams.nonEmpty =>
@@ -3366,6 +3313,13 @@ trait Types
object AnnotatedType extends AnnotatedTypeExtractor
+ object StaticallyAnnotatedType {
+ def unapply(tp: Type): Option[(List[AnnotationInfo], Type)] = tp.staticAnnotations match {
+ case Nil => None
+ case annots => Some((annots, tp.withoutAnnotations))
+ }
+ }
+
/** A class representing types with a name. When an application uses
* named arguments, the named argument types for calling isApplicable
* are represented as NamedType.
@@ -4651,6 +4605,12 @@ trait Types
}
+object TypeConstants {
+ final val DefaultLogThreshhold = 50
+ final val LogPendingBaseTypesThreshold = DefaultLogThreshhold
+ final val LogVolatileThreshold = DefaultLogThreshhold
+}
+
object TypesStats {
import BaseTypeSeqsStats._
val rawTypeCount = Statistics.newCounter ("#raw type creations")
diff --git a/src/reflect/scala/reflect/internal/Variances.scala b/src/reflect/scala/reflect/internal/Variances.scala
index bf00a7ac87..5280467055 100644
--- a/src/reflect/scala/reflect/internal/Variances.scala
+++ b/src/reflect/scala/reflect/internal/Variances.scala
@@ -142,7 +142,8 @@ trait Variances {
// No variance check for object-private/protected methods/values.
// Or constructors, or case class factory or extractor.
def skip = (
- sym.hasLocalFlag
+ sym == NoSymbol
+ || sym.hasLocalFlag
|| sym.owner.isConstructor
|| sym.owner.isCaseApplyOrUnapply
)
diff --git a/src/reflect/scala/reflect/internal/pickling/Translations.scala b/src/reflect/scala/reflect/internal/pickling/Translations.scala
new file mode 100644
index 0000000000..e56cf796cb
--- /dev/null
+++ b/src/reflect/scala/reflect/internal/pickling/Translations.scala
@@ -0,0 +1,128 @@
+/* NSC -- new Scala compiler
+ * Copyright 2005-2013 LAMP/EPFL
+ * @author Paul Phillips
+ */
+
+package scala
+package reflect
+package internal
+package pickling
+
+import PickleFormat._
+import util.shortClassOfInstance
+
+trait Translations {
+ self: SymbolTable =>
+
+ def isTreeSymbolPickled(code: Int): Boolean = (code: @annotation.switch) match {
+ case PACKAGEtree | CLASStree | MODULEtree | VALDEFtree | DEFDEFtree | TYPEDEFtree | LABELtree => true
+ case IMPORTtree | TEMPLATEtree | BINDtree | FUNCTIONtree | RETURNtree => true
+ case APPLYDYNAMICtree | SUPERtree | THIStree | SELECTtree | IDENTtree => true
+ case _ => false
+ }
+ /** This method should be equivalent to tree.hasSymbolField, but that method
+ * doesn't do us any good when we're unpickling because we need to know based
+ * on the Int tag - the tree doesn't exist yet. Thus, this method is documentation only.
+ */
+ def isTreeSymbolPickled(tree: Tree): Boolean = isTreeSymbolPickled(picklerSubTag(tree))
+
+ // The ad hoc pattern matching of tuples out of AnyRefs is a
+ // truly terrible idea. It reaches the height of its powers in
+ // combination with scala's insistence on helpfully tupling
+ // multiple arguments passed to a single-arg AnyRef.
+ def picklerTag(ref: AnyRef): Int = ref match {
+ case tp: Type => picklerTag(tp)
+ case sym: Symbol => picklerTag(sym)
+ case const: Constant => LITERAL + const.tag
+ case _: Tree => TREE // its sub tag more precisely identifies it
+ case _: TermName => TERMname
+ case _: TypeName => TYPEname
+ case _: ArrayAnnotArg => ANNOTARGARRAY // an array of annotation arguments
+ case _: AnnotationInfo => ANNOTINFO // annotations on types (not linked to a symbol)
+ case (_: Symbol, _: AnnotationInfo) => SYMANNOT // symbol annotations, i.e. on terms
+ case (_: Symbol, _: List[_]) => CHILDREN // the direct subclasses of a sealed symbol
+ case _: Modifiers => MODIFIERS
+ case _ => sys.error(s"unpicklable entry ${shortClassOfInstance(ref)} $ref")
+ }
+
+ /** Local symbols only. The assessment of locality depends
+ * on convoluted conditions which depends in part on the root
+ * symbol being pickled, so it cannot be reproduced here.
+ * The pickler tags at stake are EXTMODCLASSref and EXTref.
+ * Those tags are never produced here - such symbols must be
+ * excluded prior to calling this method.
+ */
+ def picklerTag(sym: Symbol): Int = sym match {
+ case NoSymbol => NONEsym
+ case _: ClassSymbol => CLASSsym
+ case _: TypeSymbol if sym.isAbstractType => TYPEsym
+ case _: TypeSymbol => ALIASsym
+ case _: TermSymbol if sym.isModule => MODULEsym
+ case _: TermSymbol => VALsym
+ }
+
+ def picklerTag(tpe: Type): Int = tpe match {
+ case NoType => NOtpe
+ case NoPrefix => NOPREFIXtpe
+ case _: ThisType => THIStpe
+ case _: SingleType => SINGLEtpe
+ case _: SuperType => SUPERtpe
+ case _: ConstantType => CONSTANTtpe
+ case _: TypeBounds => TYPEBOUNDStpe
+ case _: TypeRef => TYPEREFtpe
+ case _: RefinedType => REFINEDtpe
+ case _: ClassInfoType => CLASSINFOtpe
+ case _: MethodType => METHODtpe
+ case _: PolyType => POLYtpe
+ case _: NullaryMethodType => POLYtpe // bad juju, distinct ints are not at a premium!
+ case _: ExistentialType => EXISTENTIALtpe
+ case _: AnnotatedType => ANNOTATEDtpe
+ }
+
+ def picklerSubTag(tree: Tree): Int = tree match {
+ case EmptyTree => EMPTYtree
+ case _: PackageDef => PACKAGEtree
+ case _: ClassDef => CLASStree
+ case _: ModuleDef => MODULEtree
+ case _: ValDef => VALDEFtree
+ case _: DefDef => DEFDEFtree
+ case _: TypeDef => TYPEDEFtree
+ case _: LabelDef => LABELtree
+ case _: Import => IMPORTtree
+ // case _: DocDef => DOCDEFtree
+ case _: Template => TEMPLATEtree
+ case _: Block => BLOCKtree
+ case _: CaseDef => CASEtree
+ case _: Alternative => ALTERNATIVEtree
+ case _: Star => STARtree
+ case _: Bind => BINDtree
+ case _: UnApply => UNAPPLYtree
+ case _: ArrayValue => ARRAYVALUEtree
+ case _: Function => FUNCTIONtree
+ case _: Assign => ASSIGNtree
+ case _: If => IFtree
+ case _: Match => MATCHtree
+ case _: Return => RETURNtree
+ case _: Try => TREtree // TREtree?
+ case _: Throw => THROWtree
+ case _: New => NEWtree
+ case _: Typed => TYPEDtree
+ case _: TypeApply => TYPEAPPLYtree
+ case _: Apply => APPLYtree
+ case _: ApplyDynamic => APPLYDYNAMICtree
+ case _: Super => SUPERtree
+ case _: This => THIStree
+ case _: Select => SELECTtree
+ case _: Ident => IDENTtree
+ case _: Literal => LITERALtree
+ case _: TypeTree => TYPEtree
+ case _: Annotated => ANNOTATEDtree
+ case _: SingletonTypeTree => SINGLETONTYPEtree
+ case _: SelectFromTypeTree => SELECTFROMTYPEtree
+ case _: CompoundTypeTree => COMPOUNDTYPEtree
+ case _: AppliedTypeTree => APPLIEDTYPEtree
+ case _: TypeBoundsTree => TYPEBOUNDStree
+ case _: ExistentialTypeTree => EXISTENTIALTYPEtree
+ }
+}
+
diff --git a/src/reflect/scala/reflect/internal/pickling/UnPickler.scala b/src/reflect/scala/reflect/internal/pickling/UnPickler.scala
index f42dbf56e1..c4f1f0cf96 100644
--- a/src/reflect/scala/reflect/internal/pickling/UnPickler.scala
+++ b/src/reflect/scala/reflect/internal/pickling/UnPickler.scala
@@ -65,36 +65,38 @@ abstract class UnPickler {
/** A map from symbols to their associated `decls` scopes */
private val symScopes = mutable.HashMap[Symbol, Scope]()
+ private def expect(expected: Int, msg: => String) {
+ val tag = readByte()
+ if (tag != expected)
+ errorBadSignature(s"$msg ($tag)")
+ }
+
//println("unpickled " + classRoot + ":" + classRoot.rawInfo + ", " + moduleRoot + ":" + moduleRoot.rawInfo);//debug
+ @inline private def runAtIndex[T](i: Int)(body: => T): T = {
+ val saved = readIndex
+ readIndex = index(i)
+ try body finally readIndex = saved
+ }
+
// Laboriously unrolled for performance.
def run() {
var i = 0
while (i < index.length) {
- if (entries(i) == null && isSymbolEntry(i)) {
- val savedIndex = readIndex
- readIndex = index(i)
- entries(i) = readSymbol()
- readIndex = savedIndex
- }
+ if (entries(i) == null && isSymbolEntry(i))
+ runAtIndex(i)(entries(i) = readSymbol())
+
i += 1
}
+
// read children last, fix for #3951
i = 0
while (i < index.length) {
if (entries(i) == null) {
- if (isSymbolAnnotationEntry(i)) {
- val savedIndex = readIndex
- readIndex = index(i)
- readSymbolAnnotation()
- readIndex = savedIndex
- }
- else if (isChildrenEntry(i)) {
- val savedIndex = readIndex
- readIndex = index(i)
- readChildren()
- readIndex = savedIndex
- }
+ if (isSymbolAnnotationEntry(i))
+ runAtIndex(i)(readSymbolAnnotation())
+ else if (isChildrenEntry(i))
+ runAtIndex(i)(readChildren())
}
i += 1
}
@@ -145,6 +147,11 @@ abstract class UnPickler {
tag == CHILDREN
}
+ private def maybeReadSymbol(): Either[Int, Symbol] = readNat() match {
+ case index if isSymbolRef(index) => Right(at(index, readSymbol))
+ case index => Left(index)
+ }
+
/** Does entry represent a refinement symbol?
* pre: Entry is a class symbol
*/
@@ -256,14 +263,11 @@ abstract class UnPickler {
val name = at(nameref, readName)
val owner = readSymbolRef()
val flags = pickledToRawFlags(readLongNat())
- var inforef = readNat()
- val privateWithin =
- if (!isSymbolRef(inforef)) NoSymbol
- else {
- val pw = at(inforef, readSymbol)
- inforef = readNat()
- pw
- }
+
+ val (privateWithin, inforef) = maybeReadSymbol() match {
+ case Left(index) => NoSymbol -> index
+ case Right(sym) => sym -> readNat()
+ }
def isModuleFlag = (flags & MODULE) != 0L
def isClassRoot = (name == classRoot.name) && (owner == classRoot.owner)
@@ -305,7 +309,7 @@ abstract class UnPickler {
sym
case MODULEsym =>
- val clazz = at(inforef, () => readType()).typeSymbol // after the NMT_TRANSITION period, we can leave off the () => ... ()
+ val clazz = at(inforef, () => readType()).typeSymbol // after NMT_TRANSITION, we can leave off the () => ... ()
if (isModuleRoot) moduleRoot setFlag pflags
else owner.newLinkedModule(clazz, pflags)
case VALsym =>
@@ -317,84 +321,48 @@ abstract class UnPickler {
})
}
- /** Read a type
- *
- * @param forceProperType is used to ease the transition to NullaryMethodTypes (commentmarker: NMT_TRANSITION)
- * the flag say that a type of kind * is expected, so that PolyType(tps, restpe) can be disambiguated to PolyType(tps, NullaryMethodType(restpe))
- * (if restpe is not a ClassInfoType, a MethodType or a NullaryMethodType, which leaves TypeRef/SingletonType -- the latter would make the polytype a type constructor)
- */
protected def readType(forceProperType: Boolean = false): Type = {
val tag = readByte()
val end = readEnd()
+ @inline def all[T](body: => T): List[T] = until(end, () => body)
+
+ def readTypes() = all(readTypeRef)
+ def readSymbols() = all(readSymbolRef)
+ def readAnnots() = all(readAnnotationRef)
+
+ // if the method is overloaded, the params cannot be determined (see readSymbol) => return NoType.
+ // Only happen for trees, "case Apply" in readTree() takes care of selecting the correct
+ // alternative after parsing the arguments.
+ def MethodTypeRef(restpe: Type, params: List[Symbol]): Type = (
+ if (restpe == NoType || (params contains NoSymbol)) NoType
+ else MethodType(params, restpe)
+ )
+ def PolyOrNullaryType(restpe: Type, tparams: List[Symbol]): Type = tparams match {
+ case Nil => NullaryMethodType(restpe)
+ case _ => PolyType(tparams, restpe)
+ }
+ def CompoundType(clazz: Symbol, parents: List[Type]): Type = tag match {
+ case REFINEDtpe => RefinedType(parents, symScope(clazz), clazz)
+ case CLASSINFOtpe => ClassInfoType(parents, symScope(clazz), clazz)
+ }
+
+ // We're stuck with the order types are pickled in, but with judicious use
+ // of named parameters we can recapture a declarative flavor in a few cases.
+ // But it's still a rat's nest of adhockery.
(tag: @switch) match {
- case NOtpe =>
- NoType
- case NOPREFIXtpe =>
- NoPrefix
- case THIStpe =>
- ThisType(readSymbolRef())
- case SINGLEtpe =>
- SingleType(readTypeRef(), readSymbolRef()) // !!! was singleType
- case SUPERtpe =>
- val thistpe = readTypeRef()
- val supertpe = readTypeRef()
- SuperType(thistpe, supertpe)
- case CONSTANTtpe =>
- ConstantType(readConstantRef())
- case TYPEREFtpe =>
- val pre = readTypeRef()
- val sym = readSymbolRef()
- val args = until(end, readTypeRef)
- TypeRef(pre, sym, args)
- case TYPEBOUNDStpe =>
- TypeBounds(readTypeRef(), readTypeRef())
- case REFINEDtpe =>
- val clazz = readSymbolRef()
- RefinedType(until(end, readTypeRef), symScope(clazz), clazz)
- case CLASSINFOtpe =>
- val clazz = readSymbolRef()
- ClassInfoType(until(end, readTypeRef), symScope(clazz), clazz)
- case METHODtpe | IMPLICITMETHODtpe =>
- val restpe = readTypeRef()
- val params = until(end, readSymbolRef)
- // if the method is overloaded, the params cannot be determined (see readSymbol) => return NoType.
- // Only happen for trees, "case Apply" in readTree() takes care of selecting the correct
- // alternative after parsing the arguments.
- if (params.contains(NoSymbol) || restpe == NoType) NoType
- else MethodType(params, restpe)
- case POLYtpe =>
- val restpe = readTypeRef()
- val typeParams = until(end, readSymbolRef)
- if (typeParams.nonEmpty) {
- // NMT_TRANSITION: old class files denoted a polymorphic nullary method as PolyType(tps, restpe), we now require PolyType(tps, NullaryMethodType(restpe))
- // when a type of kind * is expected (forceProperType is true), we know restpe should be wrapped in a NullaryMethodType (if it wasn't suitably wrapped yet)
- def transitionNMT(restpe: Type) = {
- val resTpeCls = restpe.getClass.toString // what's uglier than isInstanceOf? right! -- isInstanceOf does not work since the concrete types are defined in the compiler (not in scope here)
- if(forceProperType /*&& pickleformat < 2.9 */ && !(resTpeCls.endsWith("MethodType"))) { assert(!resTpeCls.contains("ClassInfoType"))
- NullaryMethodType(restpe) }
- else restpe
- }
- PolyType(typeParams, transitionNMT(restpe))
- }
- else
- NullaryMethodType(restpe)
- case EXISTENTIALtpe =>
- val restpe = readTypeRef()
- newExistentialType(until(end, readSymbolRef), restpe)
-
- case ANNOTATEDtpe =>
- var typeRef = readNat()
- val selfsym = if (isSymbolRef(typeRef)) {
- val s = at(typeRef, readSymbol)
- typeRef = readNat()
- s
- } else NoSymbol // selfsym can go.
- val tp = at(typeRef, () => readType(forceProperType)) // NMT_TRANSITION
- val annots = until(end, readAnnotationRef)
- if (selfsym == NoSymbol) AnnotatedType(annots, tp, selfsym)
- else tp
- case _ =>
- noSuchTypeTag(tag, end)
+ case NOtpe => NoType
+ case NOPREFIXtpe => NoPrefix
+ case THIStpe => ThisType(readSymbolRef())
+ case SINGLEtpe => SingleType(readTypeRef(), readSymbolRef())
+ case SUPERtpe => SuperType(readTypeRef(), readTypeRef())
+ case CONSTANTtpe => ConstantType(readConstantRef())
+ case TYPEREFtpe => TypeRef(readTypeRef(), readSymbolRef(), readTypes())
+ case TYPEBOUNDStpe => TypeBounds(readTypeRef(), readTypeRef())
+ case REFINEDtpe | CLASSINFOtpe => CompoundType(readSymbolRef(), readTypes())
+ case METHODtpe => MethodTypeRef(readTypeRef(), readSymbols())
+ case POLYtpe => PolyOrNullaryType(readTypeRef(), readSymbols())
+ case EXISTENTIALtpe => ExistentialType(underlying = readTypeRef(), quantified = readSymbols())
+ case ANNOTATEDtpe => AnnotatedType(underlying = readTypeRef(), annotations = readAnnots(), selfsym = NoSymbol)
}
}
@@ -483,9 +451,7 @@ abstract class UnPickler {
* the symbol it requests. Called at top-level, for all
* (symbol, annotInfo) entries. */
protected def readSymbolAnnotation() {
- val tag = readByte()
- if (tag != SYMANNOT)
- errorBadSignature("symbol annotation expected ("+ tag +")")
+ expect(SYMANNOT, "symbol annotation expected")
val end = readEnd()
val target = readSymbolRef()
target.addAnnotation(readAnnotationInfo(end))
@@ -501,260 +467,100 @@ abstract class UnPickler {
readAnnotationInfo(end)
}
- /* Read an abstract syntax tree */
- protected def readTree(): Tree = {
- val outerTag = readByte()
- if (outerTag != TREE)
- errorBadSignature("tree expected (" + outerTag + ")")
- val end = readEnd()
- val tag = readByte()
- val tpe = if (tag == EMPTYtree) NoType else readTypeRef()
-
- // Set by the three functions to follow. If symbol is non-null
- // after the new tree 't' has been created, t has its Symbol
- // set to symbol; and it always has its Type set to tpe.
- var symbol: Symbol = null
- var mods: Modifiers = null
- var name: Name = null
-
- /* Read a Symbol, Modifiers, and a Name */
- def setSymModsName() {
- symbol = readSymbolRef()
- mods = readModifiersRef()
- name = readNameRef()
+ private def readNonEmptyTree(tag: Int, end: Int): Tree = {
+ @inline def all[T](body: => T): List[T] = until(end, () => body)
+ @inline def rep[T](body: => T): List[T] = times(readNat(), () => body)
+
+ // !!! What is this doing here?
+ def fixApply(tree: Apply, tpe: Type): Apply = {
+ val Apply(fun, args) = tree
+ if (fun.symbol.isOverloaded) {
+ fun setType fun.symbol.info
+ inferMethodAlternative(fun, args map (_.tpe), tpe)
+ }
+ tree
}
- /* Read a Symbol and a Name */
- def setSymName() {
- symbol = readSymbolRef()
- name = readNameRef()
+ def ref() = readTreeRef()
+ def caseRef() = readCaseDefRef()
+ def modsRef() = readModifiersRef()
+ def implRef() = readTemplateRef()
+ def nameRef() = readNameRef()
+ def tparamRef() = readTypeDefRef()
+ def vparamRef() = readValDefRef()
+ def constRef() = readConstantRef()
+ def idRef() = readIdentRef()
+ def termNameRef() = readNameRef().toTermName
+ def typeNameRef() = readNameRef().toTypeName
+ def refTreeRef() = ref() match {
+ case t: RefTree => t
+ case t => errorBadSignature("RefTree expected, found " + t.shortClass)
}
- /* Read a Symbol */
- def setSym() {
- symbol = readSymbolRef()
+ def selectorsRef() = all(ImportSelector(nameRef(), -1, nameRef(), -1))
+
+ /** A few of the most popular trees have been pulled to the top for
+ * switch efficiency purposes.
+ */
+ def readTree(tpe: Type): Tree = (tag: @switch) match {
+ case IDENTtree => Ident(nameRef)
+ case SELECTtree => Select(ref, nameRef)
+ case APPLYtree => fixApply(Apply(ref, all(ref)), tpe) // !!!
+ case BINDtree => Bind(nameRef, ref)
+ case BLOCKtree => all(ref) match { case stats :+ expr => Block(stats, expr) }
+ case IFtree => If(ref, ref, ref)
+ case LITERALtree => Literal(constRef)
+ case TYPEAPPLYtree => TypeApply(ref, all(ref))
+ case TYPEDtree => Typed(ref, ref)
+ case ALTERNATIVEtree => Alternative(all(ref))
+ case ANNOTATEDtree => Annotated(ref, ref)
+ case APPLIEDTYPEtree => AppliedTypeTree(ref, all(ref))
+ case APPLYDYNAMICtree => ApplyDynamic(ref, all(ref))
+ case ARRAYVALUEtree => ArrayValue(ref, all(ref))
+ case ASSIGNtree => Assign(ref, ref)
+ case CASEtree => CaseDef(ref, ref, ref)
+ case CLASStree => ClassDef(modsRef, typeNameRef, rep(tparamRef), implRef)
+ case COMPOUNDTYPEtree => CompoundTypeTree(implRef)
+ case DEFDEFtree => DefDef(modsRef, termNameRef, rep(tparamRef), rep(rep(vparamRef)), ref, ref)
+ case EXISTENTIALTYPEtree => ExistentialTypeTree(ref, all(ref))
+ case FUNCTIONtree => Function(rep(vparamRef), ref)
+ case IMPORTtree => Import(ref, selectorsRef)
+ case LABELtree => LabelDef(termNameRef, rep(idRef), ref)
+ case MATCHtree => Match(ref, all(caseRef))
+ case MODULEtree => ModuleDef(modsRef, termNameRef, implRef)
+ case NEWtree => New(ref)
+ case PACKAGEtree => PackageDef(refTreeRef, all(ref))
+ case RETURNtree => Return(ref)
+ case SELECTFROMTYPEtree => SelectFromTypeTree(ref, typeNameRef)
+ case SINGLETONTYPEtree => SingletonTypeTree(ref)
+ case STARtree => Star(ref)
+ case SUPERtree => Super(ref, typeNameRef)
+ case TEMPLATEtree => Template(rep(ref), vparamRef, all(ref))
+ case THIStree => This(typeNameRef)
+ case THROWtree => Throw(ref)
+ case TREtree => Try(ref, rep(caseRef), ref)
+ case TYPEBOUNDStree => TypeBoundsTree(ref, ref)
+ case TYPEDEFtree => TypeDef(modsRef, typeNameRef, rep(tparamRef), ref)
+ case TYPEtree => TypeTree()
+ case UNAPPLYtree => UnApply(ref, all(ref))
+ case VALDEFtree => ValDef(modsRef, termNameRef, ref, ref)
+ case _ => noSuchTreeTag(tag, end)
}
- val t = tag match {
- case EMPTYtree =>
- EmptyTree
-
- case PACKAGEtree =>
- setSym()
- val pid = readTreeRef().asInstanceOf[RefTree]
- val stats = until(end, readTreeRef)
- PackageDef(pid, stats)
-
- case CLASStree =>
- setSymModsName()
- val impl = readTemplateRef()
- val tparams = until(end, readTypeDefRef)
- ClassDef(mods, name.toTypeName, tparams, impl)
-
- case MODULEtree =>
- setSymModsName()
- ModuleDef(mods, name.toTermName, readTemplateRef())
-
- case VALDEFtree =>
- setSymModsName()
- val tpt = readTreeRef()
- val rhs = readTreeRef()
- ValDef(mods, name.toTermName, tpt, rhs)
-
- case DEFDEFtree =>
- setSymModsName()
- val tparams = times(readNat(), readTypeDefRef)
- val vparamss = times(readNat(), () => times(readNat(), readValDefRef))
- val tpt = readTreeRef()
- val rhs = readTreeRef()
- DefDef(mods, name.toTermName, tparams, vparamss, tpt, rhs)
-
- case TYPEDEFtree =>
- setSymModsName()
- val rhs = readTreeRef()
- val tparams = until(end, readTypeDefRef)
- TypeDef(mods, name.toTypeName, tparams, rhs)
-
- case LABELtree =>
- setSymName()
- val rhs = readTreeRef()
- val params = until(end, readIdentRef)
- LabelDef(name.toTermName, params, rhs)
-
- case IMPORTtree =>
- setSym()
- val expr = readTreeRef()
- val selectors = until(end, () => {
- val from = readNameRef()
- val to = readNameRef()
- ImportSelector(from, -1, to, -1)
- })
-
- Import(expr, selectors)
-
- case TEMPLATEtree =>
- setSym()
- val parents = times(readNat(), readTreeRef)
- val self = readValDefRef()
- val body = until(end, readTreeRef)
-
- Template(parents, self, body)
-
- case BLOCKtree =>
- val expr = readTreeRef()
- val stats = until(end, readTreeRef)
- Block(stats, expr)
-
- case CASEtree =>
- val pat = readTreeRef()
- val guard = readTreeRef()
- val body = readTreeRef()
- CaseDef(pat, guard, body)
-
- case ALTERNATIVEtree =>
- Alternative(until(end, readTreeRef))
-
- case STARtree =>
- Star(readTreeRef())
-
- case BINDtree =>
- setSymName()
- Bind(name, readTreeRef())
-
- case UNAPPLYtree =>
- val fun = readTreeRef()
- val args = until(end, readTreeRef)
- UnApply(fun, args)
-
- case ARRAYVALUEtree =>
- val elemtpt = readTreeRef()
- val trees = until(end, readTreeRef)
- ArrayValue(elemtpt, trees)
-
- case FUNCTIONtree =>
- setSym()
- val body = readTreeRef()
- val vparams = until(end, readValDefRef)
- Function(vparams, body)
-
- case ASSIGNtree =>
- val lhs = readTreeRef()
- val rhs = readTreeRef()
- Assign(lhs, rhs)
-
- case IFtree =>
- val cond = readTreeRef()
- val thenp = readTreeRef()
- val elsep = readTreeRef()
- If(cond, thenp, elsep)
-
- case MATCHtree =>
- val selector = readTreeRef()
- val cases = until(end, readCaseDefRef)
- Match(selector, cases)
-
- case RETURNtree =>
- setSym()
- Return(readTreeRef())
-
- case TREtree =>
- val block = readTreeRef()
- val finalizer = readTreeRef()
- val catches = until(end, readCaseDefRef)
- Try(block, catches, finalizer)
-
- case THROWtree =>
- Throw(readTreeRef())
-
- case NEWtree =>
- New(readTreeRef())
-
- case TYPEDtree =>
- val expr = readTreeRef()
- val tpt = readTreeRef()
- Typed(expr, tpt)
-
- case TYPEAPPLYtree =>
- val fun = readTreeRef()
- val args = until(end, readTreeRef)
- TypeApply(fun, args)
-
- case APPLYtree =>
- val fun = readTreeRef()
- val args = until(end, readTreeRef)
- if (fun.symbol.isOverloaded) {
- fun.setType(fun.symbol.info)
- inferMethodAlternative(fun, args map (_.tpe), tpe)
- }
- Apply(fun, args)
-
- case APPLYDYNAMICtree =>
- setSym()
- val qual = readTreeRef()
- val args = until(end, readTreeRef)
- ApplyDynamic(qual, args)
-
- case SUPERtree =>
- setSym()
- val qual = readTreeRef()
- val mix = readTypeNameRef()
- Super(qual, mix)
-
- case THIStree =>
- setSym()
- This(readTypeNameRef())
-
- case SELECTtree =>
- setSym()
- val qualifier = readTreeRef()
- val selector = readNameRef()
- Select(qualifier, selector)
-
- case IDENTtree =>
- setSymName()
- Ident(name)
-
- case LITERALtree =>
- Literal(readConstantRef())
-
- case TYPEtree =>
- TypeTree()
-
- case ANNOTATEDtree =>
- val annot = readTreeRef()
- val arg = readTreeRef()
- Annotated(annot, arg)
-
- case SINGLETONTYPEtree =>
- SingletonTypeTree(readTreeRef())
-
- case SELECTFROMTYPEtree =>
- val qualifier = readTreeRef()
- val selector = readTypeNameRef()
- SelectFromTypeTree(qualifier, selector)
-
- case COMPOUNDTYPEtree =>
- CompoundTypeTree(readTemplateRef())
-
- case APPLIEDTYPEtree =>
- val tpt = readTreeRef()
- val args = until(end, readTreeRef)
- AppliedTypeTree(tpt, args)
-
- case TYPEBOUNDStree =>
- val lo = readTreeRef()
- val hi = readTreeRef()
- TypeBoundsTree(lo, hi)
-
- case EXISTENTIALTYPEtree =>
- val tpt = readTreeRef()
- val whereClauses = until(end, readTreeRef)
- ExistentialTypeTree(tpt, whereClauses)
+ val tpe = readTypeRef()
+ val sym = if (isTreeSymbolPickled(tag)) readSymbolRef() else null
+ val result = readTree(tpe)
- case _ =>
- noSuchTreeTag(tag, end)
- }
+ if (sym ne null) result setSymbol sym
+ result setType tpe
+ }
- if (symbol == null) t setType tpe
- else t setSymbol symbol setType tpe
+ /* Read an abstract syntax tree */
+ protected def readTree(): Tree = {
+ expect(TREE, "tree expected")
+ val end = readEnd()
+ readByte() match {
+ case EMPTYtree => EmptyTree
+ case tag => readNonEmptyTree(tag, end)
+ }
}
def noSuchTreeTag(tag: Int, end: Int) =
diff --git a/src/reflect/scala/reflect/internal/settings/MutableSettings.scala b/src/reflect/scala/reflect/internal/settings/MutableSettings.scala
index e21e95903b..28afd18fe0 100644
--- a/src/reflect/scala/reflect/internal/settings/MutableSettings.scala
+++ b/src/reflect/scala/reflect/internal/settings/MutableSettings.scala
@@ -33,23 +33,26 @@ abstract class MutableSettings extends AbsSettings {
}
}
- def overrideObjects: BooleanSetting
- def printtypes: BooleanSetting
+ def Xexperimental: BooleanSetting
+ def XfullLubs: BooleanSetting
+ def XnoPatmatAnalysis: BooleanSetting
+ def Xprintpos: BooleanSetting
+ def Yposdebug: BooleanSetting
+ def Yrangepos: BooleanSetting
+ def Yshowsymkinds: BooleanSetting
+ def breakCycles: BooleanSetting
def debug: BooleanSetting
+ def developer: BooleanSetting
def explaintypes: BooleanSetting
- def verbose: BooleanSetting
+ def overrideObjects: BooleanSetting
+ def printtypes: BooleanSetting
def uniqid: BooleanSetting
- def Yshowsymkinds: BooleanSetting
- def Yposdebug: BooleanSetting
- def Yrangepos: BooleanSetting
- def Xprintpos: BooleanSetting
+ def verbose: BooleanSetting
+
def Yrecursion: IntSetting
def maxClassfileName: IntSetting
- def Xexperimental: BooleanSetting
- def XnoPatmatAnalysis: BooleanSetting
- def XfullLubs: BooleanSetting
- def breakCycles: BooleanSetting
}
+
object MutableSettings {
import scala.language.implicitConversions
/** Support the common use case, `if (settings.debug) println("Hello, martin.")` */
diff --git a/src/reflect/scala/reflect/internal/tpe/TypeComparers.scala b/src/reflect/scala/reflect/internal/tpe/TypeComparers.scala
index 152c689c56..6532bce9f0 100644
--- a/src/reflect/scala/reflect/internal/tpe/TypeComparers.scala
+++ b/src/reflect/scala/reflect/internal/tpe/TypeComparers.scala
@@ -12,7 +12,7 @@ trait TypeComparers {
import definitions._
import TypesStats._
- private final val LogPendingSubTypesThreshold = DefaultLogThreshhold
+ private final val LogPendingSubTypesThreshold = TypeConstants.DefaultLogThreshhold
private val pendingSubTypes = new mutable.HashSet[SubTypePair]
diff --git a/src/reflect/scala/reflect/internal/tpe/TypeMaps.scala b/src/reflect/scala/reflect/internal/tpe/TypeMaps.scala
index 7e98ac03d5..9a54ad8217 100644
--- a/src/reflect/scala/reflect/internal/tpe/TypeMaps.scala
+++ b/src/reflect/scala/reflect/internal/tpe/TypeMaps.scala
@@ -581,6 +581,7 @@ private[internal] trait TypeMaps {
else if (!matchesPrefixAndClass(pre, clazz)(tparam.owner))
loop(nextBase.prefix, clazz.owner)
else nextBase match {
+ case NoType => loop(NoType, clazz.owner) // backstop for SI-2797, must remove `SingletonType#isHigherKinded` and run pos/t2797.scala to get here.
case applied @ TypeRef(_, _, _) => correspondingTypeArgument(classParam, applied)
case ExistentialType(eparams, qtpe) => captureSkolems(eparams) ; loop(qtpe, clazz)
case t => abort(s"$tparam in ${tparam.owner} cannot be instantiated from ${seenFromPrefix.widen}")
@@ -593,10 +594,8 @@ private[internal] trait TypeMaps {
// Since pre may be something like ThisType(A) where trait A { self: B => },
// we have to test the typeSymbol of the widened type, not pre.typeSymbol, or
// B will not be considered.
- private def matchesPrefixAndClass(pre: Type, clazz: Symbol)(candidate: Symbol) = pre.widen match {
- case _: TypeVar => false
- case wide => (clazz == candidate) && (wide.typeSymbol isSubClass clazz)
- }
+ private def matchesPrefixAndClass(pre: Type, clazz: Symbol)(candidate: Symbol) =
+ (clazz == candidate) && (pre.widen.typeSymbol isSubClass clazz)
// Whether the annotation tree currently being mapped over has had a This(_) node rewritten.
private[this] var wroteAnnotation = false
diff --git a/src/reflect/scala/reflect/runtime/Settings.scala b/src/reflect/scala/reflect/runtime/Settings.scala
index d65e9329ed..11db83d7d5 100644
--- a/src/reflect/scala/reflect/runtime/Settings.scala
+++ b/src/reflect/scala/reflect/runtime/Settings.scala
@@ -34,16 +34,17 @@ private[reflect] class Settings extends MutableSettings {
val XfullLubs = new BooleanSetting(false)
val XnoPatmatAnalysis = new BooleanSetting(false)
val Xprintpos = new BooleanSetting(false)
- val Yshowsymkinds = new BooleanSetting(false)
val Yposdebug = new BooleanSetting(false)
val Yrangepos = new BooleanSetting(false)
+ val Yshowsymkinds = new BooleanSetting(false)
+ val breakCycles = new BooleanSetting(false)
val debug = new BooleanSetting(false)
+ val developer = new BooleanSetting(false)
val explaintypes = new BooleanSetting(false)
val overrideObjects = new BooleanSetting(false)
val printtypes = new BooleanSetting(false)
val uniqid = new BooleanSetting(false)
val verbose = new BooleanSetting(false)
- val breakCycles = new BooleanSetting(false)
val Yrecursion = new IntSetting(0)
val maxClassfileName = new IntSetting(255)
diff --git a/test/files/jvm/deprecation.check b/test/files/jvm/deprecation.check
index e263e4909d..d116778d3f 100644
--- a/test/files/jvm/deprecation.check
+++ b/test/files/jvm/deprecation.check
@@ -1,3 +1,3 @@
-warning: there were 5 deprecation warning(s); re-run with -deprecation for details
+warning: there were 4 deprecation warning(s); re-run with -deprecation for details
Note: deprecation/Use_2.java uses or overrides a deprecated API.
Note: Recompile with -Xlint:deprecation for details.
diff --git a/test/files/neg/accesses.check b/test/files/neg/accesses.check
index db58af12ce..5a5e03233e 100644
--- a/test/files/neg/accesses.check
+++ b/test/files/neg/accesses.check
@@ -1,7 +1,3 @@
-accesses.scala:23: error: overriding method f2 in class A of type ()Unit;
- method f2 has weaker access privileges; it should not be private
- private def f2(): Unit = ()
- ^
accesses.scala:24: error: overriding method f3 in class A of type ()Unit;
method f3 has weaker access privileges; it should be at least protected
private[p2] def f3(): Unit = ()
@@ -14,4 +10,4 @@ accesses.scala:26: error: overriding method f5 in class A of type ()Unit;
method f5 has weaker access privileges; it should be at least protected[p1]
protected[p2] def f5(): Unit
^
-four errors found
+three errors found
diff --git a/test/files/neg/accesses2.check b/test/files/neg/accesses2.check
new file mode 100644
index 0000000000..554a7b4c81
--- /dev/null
+++ b/test/files/neg/accesses2.check
@@ -0,0 +1,4 @@
+accesses2.scala:5: error: class B1 needs to be abstract, since method f2 in class A of type ()Int is not defined
+ class B1 extends A {
+ ^
+one error found
diff --git a/test/files/neg/accesses2.scala b/test/files/neg/accesses2.scala
new file mode 100644
index 0000000000..c7640f84b5
--- /dev/null
+++ b/test/files/neg/accesses2.scala
@@ -0,0 +1,11 @@
+package p2 {
+ abstract class A {
+ private[p2] def f2(): Int
+ }
+ class B1 extends A {
+ private def f2(): Int = 1
+ }
+ abstract class B2 extends A {
+ private def f2(): Int = 1
+ }
+}
diff --git a/test/files/neg/any-vs-anyref.check b/test/files/neg/any-vs-anyref.check
index 63c4853130..7378f0495f 100644
--- a/test/files/neg/any-vs-anyref.check
+++ b/test/files/neg/any-vs-anyref.check
@@ -36,12 +36,28 @@ Such types can participate in value classes, but instances
cannot appear in singleton types or in reference comparisons.
def foo5(x: Quux with Product) = (x eq "abc") && ("abc" eq x)
^
+any-vs-anyref.scala:10: error: type mismatch;
+ found : Quux with Product
+ required: AnyRef
+Note that the parents of this type (Quux, Product) extend Any, not AnyRef.
+Such types can participate in value classes, but instances
+cannot appear in singleton types or in reference comparisons.
+ def foo5(x: Quux with Product) = (x eq "abc") && ("abc" eq x)
+ ^
any-vs-anyref.scala:11: error: value eq is not a member of Quux with Product{def f: Int}
Note that the parents of this type (Quux, Product) extend Any, not AnyRef.
Such types can participate in value classes, but instances
cannot appear in singleton types or in reference comparisons.
def foo6(x: Quux with Product { def f: Int }) = (x eq "abc") && ("abc" eq x)
^
+any-vs-anyref.scala:11: error: type mismatch;
+ found : Quux with Product{def f: Int}
+ required: AnyRef
+Note that the parents of this type (Quux, Product) extend Any, not AnyRef.
+Such types can participate in value classes, but instances
+cannot appear in singleton types or in reference comparisons.
+ def foo6(x: Quux with Product { def f: Int }) = (x eq "abc") && ("abc" eq x)
+ ^
any-vs-anyref.scala:12: error: type mismatch;
found : Quux with Product{def eq(other: String): Boolean}
required: AnyRef
@@ -61,4 +77,4 @@ any-vs-anyref.scala:27: error: type mismatch;
required: Quux{def g(x: Int): Int}
f(new Quux { def g(x: String) = x })
^
-9 errors found
+11 errors found
diff --git a/test/files/neg/applydynamic_sip.check b/test/files/neg/applydynamic_sip.check
index dcf97b29fc..f28f26c147 100644
--- a/test/files/neg/applydynamic_sip.check
+++ b/test/files/neg/applydynamic_sip.check
@@ -4,9 +4,18 @@ applydynamic_sip.scala:7: error: applyDynamic does not support passing a vararg
applydynamic_sip.scala:8: error: applyDynamicNamed does not support passing a vararg parameter
qual.sel(arg = a, a2: _*)
^
+applydynamic_sip.scala:8: error: not found: value arg
+ qual.sel(arg = a, a2: _*)
+ ^
applydynamic_sip.scala:9: error: applyDynamicNamed does not support passing a vararg parameter
qual.sel(arg, arg2 = "a2", a2: _*)
^
+applydynamic_sip.scala:9: error: not found: value arg
+ qual.sel(arg, arg2 = "a2", a2: _*)
+ ^
+applydynamic_sip.scala:9: error: not found: value arg2
+ qual.sel(arg, arg2 = "a2", a2: _*)
+ ^
applydynamic_sip.scala:18: error: type mismatch;
found : String("sel")
required: Int
@@ -28,6 +37,9 @@ error after rewriting to Test.this.bad1.applyDynamicNamed("sel")
possible cause: maybe a wrong Dynamic method signature?
bad1.sel(a = 1)
^
+applydynamic_sip.scala:20: error: reassignment to val
+ bad1.sel(a = 1)
+ ^
applydynamic_sip.scala:21: error: type mismatch;
found : String("sel")
required: Int
@@ -50,9 +62,12 @@ error after rewriting to Test.this.bad2.applyDynamicNamed("sel")
possible cause: maybe a wrong Dynamic method signature?
bad2.sel(a = 1)
^
+applydynamic_sip.scala:31: error: reassignment to val
+ bad2.sel(a = 1)
+ ^
applydynamic_sip.scala:32: error: Int does not take parameters
error after rewriting to Test.this.bad2.updateDynamic("sel")
possible cause: maybe a wrong Dynamic method signature?
bad2.sel = 1
^
-11 errors found
+16 errors found
diff --git a/test/files/neg/macro-basic-mamdmi.check b/test/files/neg/macro-basic-mamdmi.check
index 621d318ceb..9328fbd51c 100644
--- a/test/files/neg/macro-basic-mamdmi.check
+++ b/test/files/neg/macro-basic-mamdmi.check
@@ -1,5 +1,5 @@
-Impls_Macros_Test_1.scala:36: error: macro implementation not found: foo
+Impls_Macros_Test_1.scala:36: error: macro implementation not found: quux
(the most common reason for that is that you cannot use macro implementations in the same compilation run that defines them)
println(foo(2) + Macros.bar(2) * new Macros().quux(4))
- ^
+ ^
one error found
diff --git a/test/files/neg/names-defaults-neg.check b/test/files/neg/names-defaults-neg.check
index cdc12c2490..880ddc4327 100644
--- a/test/files/neg/names-defaults-neg.check
+++ b/test/files/neg/names-defaults-neg.check
@@ -7,6 +7,11 @@ names-defaults-neg.scala:5: error: type mismatch;
required: Int
test1(b = 2, a = "#")
^
+names-defaults-neg.scala:5: error: type mismatch;
+ found : Int(2)
+ required: String
+ test1(b = 2, a = "#")
+ ^
names-defaults-neg.scala:8: error: positional after named argument.
test1(b = "(*", 23)
^
@@ -122,6 +127,12 @@ names-defaults-neg.scala:131: error: reference to var2 is ambiguous; it is both
names-defaults-neg.scala:134: error: missing parameter type for expanded function ((x$1) => a = x$1)
val taf2: Int => Unit = testAnnFun(a = _, b = get("+"))
^
+names-defaults-neg.scala:134: error: not found: value a
+ val taf2: Int => Unit = testAnnFun(a = _, b = get("+"))
+ ^
+names-defaults-neg.scala:134: error: not found: value get
+ val taf2: Int => Unit = testAnnFun(a = _, b = get("+"))
+ ^
names-defaults-neg.scala:135: error: parameter 'a' is already specified at parameter position 1
val taf3 = testAnnFun(b = _: String, a = get(8))
^
@@ -131,6 +142,9 @@ names-defaults-neg.scala:136: error: missing parameter type for expanded functio
names-defaults-neg.scala:136: error: missing parameter type for expanded function ((x$4) => b = x$4)
val taf4: (Int, String) => Unit = testAnnFun(_, b = _)
^
+names-defaults-neg.scala:136: error: not found: value b
+ val taf4: (Int, String) => Unit = testAnnFun(_, b = _)
+ ^
names-defaults-neg.scala:144: error: variable definition needs type because 'x' is used as a named argument in its body.
def t3 { var x = t.f(x = 1) }
^
@@ -168,4 +182,4 @@ names-defaults-neg.scala:180: error: reference to x is ambiguous; it is both a m
class u18 { var x: Int = u.f(x = 1) }
^
four warnings found
-42 errors found
+46 errors found
diff --git a/test/files/neg/reflection-names-neg.check b/test/files/neg/reflection-names-neg.check
index a56a19e7fd..f941ec8dc1 100644
--- a/test/files/neg/reflection-names-neg.check
+++ b/test/files/neg/reflection-names-neg.check
@@ -7,4 +7,7 @@ Note that implicit conversions are not applicable because they are ambiguous:
are possible conversion functions from String("abc") to reflect.runtime.universe.Name
val x2 = ("abc": Name) drop 1 // error
^
-one error found
+reflection-names-neg.scala:5: error: value drop is not a member of reflect.runtime.universe.Name
+ val x2 = ("abc": Name) drop 1 // error
+ ^
+two errors found
diff --git a/test/files/neg/sammy_restrictions.check b/test/files/neg/sammy_restrictions.check
new file mode 100644
index 0000000000..8cc49f9aa9
--- /dev/null
+++ b/test/files/neg/sammy_restrictions.check
@@ -0,0 +1,49 @@
+sammy_restrictions.scala:31: error: type mismatch;
+ found : () => Int
+ required: NoAbstract
+ (() => 0) : NoAbstract
+ ^
+sammy_restrictions.scala:32: error: type mismatch;
+ found : Int => Int
+ required: TwoAbstract
+ ((x: Int) => 0): TwoAbstract
+ ^
+sammy_restrictions.scala:34: error: class type required but DerivedOneAbstract with OneAbstract found
+ ((x: Int) => 0): NonClassType // "class type required". I think we should avoid SAM translation here.
+ ^
+sammy_restrictions.scala:35: error: type mismatch;
+ found : Int => Int
+ required: NoEmptyConstructor
+ ((x: Int) => 0): NoEmptyConstructor
+ ^
+sammy_restrictions.scala:37: error: type mismatch;
+ found : Int => Int
+ required: OneEmptySecondaryConstructor
+ ((x: Int) => 0): OneEmptySecondaryConstructor // derived class must have an empty *primary* to call.
+ ^
+sammy_restrictions.scala:38: error: type mismatch;
+ found : Int => Int
+ required: MultipleConstructorLists
+ ((x: Int) => 0): MultipleConstructorLists
+ ^
+sammy_restrictions.scala:39: error: type mismatch;
+ found : Int => Int
+ required: MultipleMethodLists
+ ((x: Int) => 0): MultipleMethodLists
+ ^
+sammy_restrictions.scala:40: error: type mismatch;
+ found : Int => Int
+ required: ImplicitConstructorParam
+ ((x: Int) => 0): ImplicitConstructorParam
+ ^
+sammy_restrictions.scala:41: error: type mismatch;
+ found : Int => Int
+ required: ImplicitMethodParam
+ ((x: Int) => 0): ImplicitMethodParam
+ ^
+sammy_restrictions.scala:44: error: type mismatch;
+ found : Int => Int
+ required: PolyMethod
+ ((x: Int) => 0): PolyMethod
+ ^
+10 errors found
diff --git a/test/files/neg/sammy_restrictions.flags b/test/files/neg/sammy_restrictions.flags
new file mode 100644
index 0000000000..48fd867160
--- /dev/null
+++ b/test/files/neg/sammy_restrictions.flags
@@ -0,0 +1 @@
+-Xexperimental
diff --git a/test/files/neg/sammy_restrictions.scala b/test/files/neg/sammy_restrictions.scala
new file mode 100644
index 0000000000..5f1a04cd20
--- /dev/null
+++ b/test/files/neg/sammy_restrictions.scala
@@ -0,0 +1,45 @@
+class NoAbstract
+
+class TwoAbstract { def ap(a: Int): Int; def pa(a: Int): Int }
+
+class Base // check that the super class constructor isn't considered.
+class NoEmptyConstructor(a: Int) extends Base { def this(a: String) = this(0); def ap(a: Int): Int }
+
+class OneEmptyConstructor() { def this(a: Int) = this(); def ap(a: Int): Int }
+
+class OneEmptySecondaryConstructor(a: Int) { def this() = this(0); def ap(a: Int): Int }
+
+class MultipleConstructorLists()() { def ap(a: Int): Int }
+
+class MultipleMethodLists()() { def ap(a: Int)(): Int }
+
+class ImplicitConstructorParam()(implicit a: String) { def ap(a: Int): Int }
+
+class ImplicitMethodParam() { def ap(a: Int)(implicit b: String): Int }
+
+class PolyClass[T] { def ap(a: T): T }
+
+class PolyMethod { def ap[T](a: T): T }
+
+class OneAbstract { def ap(a: Any): Any }
+class DerivedOneAbstract extends OneAbstract
+
+object Test {
+ implicit val s: String = ""
+ type NonClassType = DerivedOneAbstract with OneAbstract
+
+ (() => 0) : NoAbstract
+ ((x: Int) => 0): TwoAbstract
+ ((x: Int) => 0): DerivedOneAbstract // okay
+ ((x: Int) => 0): NonClassType // "class type required". I think we should avoid SAM translation here.
+ ((x: Int) => 0): NoEmptyConstructor
+ ((x: Int) => 0): OneEmptyConstructor // okay
+ ((x: Int) => 0): OneEmptySecondaryConstructor // derived class must have an empty *primary* to call.
+ ((x: Int) => 0): MultipleConstructorLists
+ ((x: Int) => 0): MultipleMethodLists
+ ((x: Int) => 0): ImplicitConstructorParam
+ ((x: Int) => 0): ImplicitMethodParam
+
+ ((x: Int) => 0): PolyClass[Int] // okay
+ ((x: Int) => 0): PolyMethod
+}
diff --git a/test/files/neg/sammy_wrong_arity.check b/test/files/neg/sammy_wrong_arity.check
new file mode 100644
index 0000000000..af547a201d
--- /dev/null
+++ b/test/files/neg/sammy_wrong_arity.check
@@ -0,0 +1,52 @@
+sammy_wrong_arity.scala:6: error: type mismatch;
+ found : () => Int
+ required: T1
+ (() => 0): T1
+ ^
+sammy_wrong_arity.scala:7: error: type mismatch;
+ found : Any => Int
+ required: T2
+ ((x: Any) => 0): T2
+ ^
+sammy_wrong_arity.scala:9: error: type mismatch;
+ found : Any => Int
+ required: T0
+ ((x: Any) => 0): T0
+ ^
+sammy_wrong_arity.scala:10: error: type mismatch;
+ found : Any => Int
+ required: T2
+ ((x: Any) => 0): T2
+ ^
+sammy_wrong_arity.scala:12: error: type mismatch;
+ found : (Any, Any) => Int
+ required: T0
+ ((x: Any, y: Any) => 0): T0
+ ^
+sammy_wrong_arity.scala:13: error: type mismatch;
+ found : (Any, Any) => Int
+ required: T1
+ ((x: Any, y: Any) => 0): T1
+ ^
+sammy_wrong_arity.scala:15: error: missing parameter type
+ ((x) => 0): T2
+ ^
+sammy_wrong_arity.scala:17: error: missing parameter type
+ ((x) => 0): T0
+ ^
+sammy_wrong_arity.scala:18: error: missing parameter type
+ ((x) => 0): T2
+ ^
+sammy_wrong_arity.scala:20: error: missing parameter type
+ ((x, y) => 0): T0
+ ^
+sammy_wrong_arity.scala:20: error: missing parameter type
+ ((x, y) => 0): T0
+ ^
+sammy_wrong_arity.scala:21: error: missing parameter type
+ ((x, y) => 0): T1
+ ^
+sammy_wrong_arity.scala:21: error: missing parameter type
+ ((x, y) => 0): T1
+ ^
+13 errors found
diff --git a/test/files/neg/sammy_wrong_arity.flags b/test/files/neg/sammy_wrong_arity.flags
new file mode 100644
index 0000000000..48fd867160
--- /dev/null
+++ b/test/files/neg/sammy_wrong_arity.flags
@@ -0,0 +1 @@
+-Xexperimental
diff --git a/test/files/neg/sammy_wrong_arity.scala b/test/files/neg/sammy_wrong_arity.scala
new file mode 100644
index 0000000000..d03d266a0b
--- /dev/null
+++ b/test/files/neg/sammy_wrong_arity.scala
@@ -0,0 +1,22 @@
+trait T0 { def ap(): Int }
+trait T1 { def ap(a: Any): Int }
+trait T2 { def ap(a: Any, b: Any): Int }
+
+class Test {
+ (() => 0): T1
+ ((x: Any) => 0): T2
+
+ ((x: Any) => 0): T0
+ ((x: Any) => 0): T2
+
+ ((x: Any, y: Any) => 0): T0
+ ((x: Any, y: Any) => 0): T1
+
+ ((x) => 0): T2
+
+ ((x) => 0): T0
+ ((x) => 0): T2
+
+ ((x, y) => 0): T0
+ ((x, y) => 0): T1
+}
diff --git a/test/files/neg/t0259.check b/test/files/neg/t0259.check
index 24e35e6176..8c15d98419 100644
--- a/test/files/neg/t0259.check
+++ b/test/files/neg/t0259.check
@@ -1,6 +1,6 @@
t0259.scala:4: error: double definition:
-constructor TestCase3:(groups: String*)test.TestCase3 and
-constructor TestCase3:(groups: (String, Int)*)test.TestCase3 at line 3
+constructor TestCase3: (groups: (String, Int)*)test.TestCase3 at line 3 and
+constructor TestCase3: (groups: String*)test.TestCase3 at line 4
have same type after erasure: (groups: Seq)test.TestCase3
def this( groups: String*) = this()
^
diff --git a/test/files/neg/t0418.check b/test/files/neg/t0418.check
index 4e9ad2f9ae..b95f8e4e1b 100644
--- a/test/files/neg/t0418.check
+++ b/test/files/neg/t0418.check
@@ -1,7 +1,4 @@
t0418.scala:2: error: not found: value Foo12340771
null match { case Foo12340771.Bar(x) => x }
^
-t0418.scala:2: error: not found: value x
- null match { case Foo12340771.Bar(x) => x }
- ^
-two errors found
+one error found
diff --git a/test/files/neg/t3653.check b/test/files/neg/t3653.check
index ac6e2ca9dc..ad68e29fb4 100644
--- a/test/files/neg/t3653.check
+++ b/test/files/neg/t3653.check
@@ -1,7 +1,7 @@
t3653.scala:3: error: double definition:
-method x:(implicit x: Int)Int and
-method x:(i: Int)Int at line 2
-have same type after erasure: (x: Int)Int
+def x(i: Int): Int at line 2 and
+def x(implicit x: Int): Int at line 3
+have same type after erasure: (i: Int)Int
def x(implicit x: Int) = 5
^
one error found
diff --git a/test/files/neg/t418.check b/test/files/neg/t418.check
index 1489547823..1b99717b82 100644
--- a/test/files/neg/t418.check
+++ b/test/files/neg/t418.check
@@ -1,7 +1,4 @@
t418.scala:2: error: not found: value Foo12340771
null match { case Foo12340771.Bar(x) => x }
^
-t418.scala:2: error: not found: value x
- null match { case Foo12340771.Bar(x) => x }
- ^
-two errors found
+one error found
diff --git a/test/files/neg/t4515.check b/test/files/neg/t4515.check
index 64e7cc1ca7..708fcfbd29 100644
--- a/test/files/neg/t4515.check
+++ b/test/files/neg/t4515.check
@@ -3,4 +3,14 @@ t4515.scala:37: error: type mismatch;
required: _$2
handler.onEvent(target, ctx.getEvent, node, ctx)
^
-one error found
+t4515.scala:37: error: type mismatch;
+ found : Main.DerivedPushNode[_$1] where type _$1
+ required: Main.PushNode[_$2]
+ handler.onEvent(target, ctx.getEvent, node, ctx)
+ ^
+t4515.scala:37: error: type mismatch;
+ found : Main.PushEventContext[_$1] where type _$1
+ required: Main.PushEventContext[_$2]
+ handler.onEvent(target, ctx.getEvent, node, ctx)
+ ^
+three errors found
diff --git a/test/files/neg/t512.check b/test/files/neg/t512.check
index 814e65e405..051e5ee19f 100644
--- a/test/files/neg/t512.check
+++ b/test/files/neg/t512.check
@@ -1,4 +1,7 @@
t512.scala:3: error: not found: value something
val xxx = something ||
^
-one error found
+t512.scala:4: error: not found: value something_else
+ something_else;
+ ^
+two errors found
diff --git a/test/files/neg/t545.check b/test/files/neg/t545.check
index 8ebbf9bdf6..aae575fa96 100644
--- a/test/files/neg/t545.check
+++ b/test/files/neg/t545.check
@@ -1,7 +1,4 @@
t545.scala:4: error: value blah is not a member of Test.Foo
val x = foo.blah match {
^
-t545.scala:5: error: recursive value x needs type
- case List(x) => x
- ^
-two errors found
+one error found
diff --git a/test/files/neg/t556.check b/test/files/neg/t556.check
index 5135dc92ef..30cc296b35 100644
--- a/test/files/neg/t556.check
+++ b/test/files/neg/t556.check
@@ -1,4 +1,7 @@
t556.scala:3: error: missing parameter type
def g:Int = f((x,y)=>x)
^
-one error found
+t556.scala:3: error: missing parameter type
+ def g:Int = f((x,y)=>x)
+ ^
+two errors found
diff --git a/test/files/neg/t5572.check b/test/files/neg/t5572.check
index 7b1e290861..3c9adf41cd 100644
--- a/test/files/neg/t5572.check
+++ b/test/files/neg/t5572.check
@@ -3,9 +3,14 @@ t5572.scala:16: error: type mismatch;
required: A
Z.transf(a, b) match {
^
+t5572.scala:16: error: type mismatch;
+ found : A
+ required: B
+ Z.transf(a, b) match {
+ ^
t5572.scala:18: error: type mismatch;
found : A
required: B
run(sth, b)
^
-two errors found
+three errors found
diff --git a/test/files/neg/t5761.check b/test/files/neg/t5761.check
index 89d766fe34..2d66af26f6 100644
--- a/test/files/neg/t5761.check
+++ b/test/files/neg/t5761.check
@@ -13,4 +13,7 @@ Unspecified value parameter x.
t5761.scala:13: error: not found: type Tread
new Tread("sth") { }.run()
^
-four errors found
+t5761.scala:13: error: value run is not a member of AnyRef
+ new Tread("sth") { }.run()
+ ^
+5 errors found
diff --git a/test/files/neg/t588.check b/test/files/neg/t588.check
index f8b5516fdc..ff08f77a6f 100644
--- a/test/files/neg/t588.check
+++ b/test/files/neg/t588.check
@@ -1,13 +1,13 @@
t588.scala:3: error: double definition:
-method visit:(f: Int => String)Boolean and
-method visit:(f: Int => Unit)Boolean at line 2
+def visit(f: Int => Unit): Boolean at line 2 and
+def visit(f: Int => String): Boolean at line 3
have same type after erasure: (f: Function1)Boolean
def visit(f: Int => String): Boolean
^
t588.scala:10: error: double definition:
-method f:(brac: Test.this.TypeB)Unit and
-method f:(node: Test.this.TypeA)Unit at line 9
-have same type after erasure: (brac: Test#TraitA)Unit
+def f(node: Test.this.TypeA): Unit at line 9 and
+def f(brac: Test.this.TypeB): Unit at line 10
+have same type after erasure: (node: Test#TraitA)Unit
def f(brac : TypeB) : Unit;
^
two errors found
diff --git a/test/files/neg/t5903a.check b/test/files/neg/t5903a.check
index cbdcfd1bdd..2e5cc87167 100644
--- a/test/files/neg/t5903a.check
+++ b/test/files/neg/t5903a.check
@@ -1,7 +1,4 @@
Test_2.scala:4: error: wrong number of patterns for <$anon: AnyRef> offering (SomeTree.type, SomeTree.type): expected 2, found 3
case nq"$x + $y + $z" => println((x, y))
^
-Test_2.scala:4: error: not found: value x
- case nq"$x + $y + $z" => println((x, y))
- ^
-two errors found
+one error found
diff --git a/test/files/neg/t5903b.check b/test/files/neg/t5903b.check
index faeb73ad03..e7637d3edb 100644
--- a/test/files/neg/t5903b.check
+++ b/test/files/neg/t5903b.check
@@ -3,7 +3,4 @@ Test_2.scala:4: error: type mismatch;
required: String
case t"$x" => println(x)
^
-Test_2.scala:4: error: not found: value x
- case t"$x" => println(x)
- ^
-two errors found
+one error found
diff --git a/test/files/neg/t5903c.check b/test/files/neg/t5903c.check
index c9476edd11..05bd775d30 100644
--- a/test/files/neg/t5903c.check
+++ b/test/files/neg/t5903c.check
@@ -1,7 +1,4 @@
Test_2.scala:4: error: String is not supported
case t"$x" => println(x)
^
-Test_2.scala:4: error: not found: value x
- case t"$x" => println(x)
- ^
-two errors found
+one error found
diff --git a/test/files/neg/t5903d.check b/test/files/neg/t5903d.check
index d5d3fdcc28..9b8526b7f5 100644
--- a/test/files/neg/t5903d.check
+++ b/test/files/neg/t5903d.check
@@ -1,7 +1,4 @@
Test_2.scala:4: error: extractor macros can only expand into extractor calls
case t"$x" => println(x)
^
-Test_2.scala:4: error: not found: value x
- case t"$x" => println(x)
- ^
-two errors found
+one error found
diff --git a/test/files/neg/t6443c.check b/test/files/neg/t6443c.check
index 7cf8d23f4b..7b7f419f6c 100644
--- a/test/files/neg/t6443c.check
+++ b/test/files/neg/t6443c.check
@@ -1,6 +1,6 @@
t6443c.scala:16: error: double definition:
-method foo:(d: B.D)(a: Any)(d2: d.type)Unit and
-method foo:(d: B.D)(a: Any, d2: d.type)Unit at line 11
+def foo(d: B.D)(a: Any,d2: d.type): Unit at line 11 and
+def foo(d: B.D)(a: Any)(d2: d.type): Unit at line 16
have same type after erasure: (d: B.D, a: Object, d2: B.D)Unit
def foo(d: D)(a: Any)(d2: d.type): Unit = ()
^
diff --git a/test/files/neg/t663.check b/test/files/neg/t663.check
index 40161fb3e3..633e27ee12 100644
--- a/test/files/neg/t663.check
+++ b/test/files/neg/t663.check
@@ -1,7 +1,7 @@
t663.scala:11: error: name clash between defined and inherited member:
-method asMatch:(m: Test.this.Node)Any and
-method asMatch:(node: Test.this.Matchable)Any in trait MatchableImpl
-have same type after erasure: (m: test.Test#NodeImpl)Object
+def asMatch(node: Test.this.Matchable): Any in trait MatchableImpl and
+def asMatch(m: Test.this.Node): Any at line 11
+have same type after erasure: (node: test.Test#NodeImpl)Object
def asMatch(m : Node) : Any = {
^
one error found
diff --git a/test/files/neg/t6829.check b/test/files/neg/t6829.check
index c7c641844e..a0b43e3b52 100644
--- a/test/files/neg/t6829.check
+++ b/test/files/neg/t6829.check
@@ -20,11 +20,31 @@ t6829.scala:50: error: type mismatch;
required: _53.State where val _53: G
val r = rewards(agent).r(s,a,s2)
^
+t6829.scala:50: error: type mismatch;
+ found : a.type (with underlying type T2)
+ required: _53.Action where val _53: G
+ val r = rewards(agent).r(s,a,s2)
+ ^
+t6829.scala:50: error: type mismatch;
+ found : s2.type (with underlying type T3)
+ required: _53.State where val _53: G
+ val r = rewards(agent).r(s,a,s2)
+ ^
t6829.scala:51: error: type mismatch;
found : s.type (with underlying type T1)
required: _50.State
agent.learn(s,a,s2,r): G#Agent
^
+t6829.scala:51: error: type mismatch;
+ found : a.type (with underlying type T2)
+ required: _50.Action
+ agent.learn(s,a,s2,r): G#Agent
+ ^
+t6829.scala:51: error: type mismatch;
+ found : s2.type (with underlying type T3)
+ required: _50.State
+ agent.learn(s,a,s2,r): G#Agent
+ ^
t6829.scala:53: error: not found: value nextState
Error occurred in an application involving default arguments.
copy(agents = updatedAgents, state = nextState, pastHistory = currentHistory)
@@ -33,4 +53,4 @@ t6829.scala:53: error: not found: value currentHistory
Error occurred in an application involving default arguments.
copy(agents = updatedAgents, state = nextState, pastHistory = currentHistory)
^
-9 errors found
+13 errors found
diff --git a/test/files/neg/t7239.check b/test/files/neg/t7239.check
new file mode 100644
index 0000000000..80b14f8fc6
--- /dev/null
+++ b/test/files/neg/t7239.check
@@ -0,0 +1,4 @@
+t7239.scala:10: error: not found: value foBar
+ fooBar = foBar.toInt
+ ^
+one error found
diff --git a/test/files/neg/t7239.scala b/test/files/neg/t7239.scala
new file mode 100644
index 0000000000..f62cac0a49
--- /dev/null
+++ b/test/files/neg/t7239.scala
@@ -0,0 +1,12 @@
+class Foo {
+ def toInt = 12
+}
+case class Bar( fooBar : Int )
+
+// spurious "erroneous or inaccessible type" error in 2.10.1
+class Test {
+ var fooBar : Foo = null
+ def build = Bar(
+ fooBar = foBar.toInt
+ )
+}
diff --git a/test/files/neg/t7783.check b/test/files/neg/t7783.check
new file mode 100644
index 0000000000..647cfee121
--- /dev/null
+++ b/test/files/neg/t7783.check
@@ -0,0 +1,18 @@
+t7783.scala:1: warning: type D in object O is deprecated:
+object O { class C; @deprecated("", "") type D = C; def foo: Seq[D] = Nil }
+ ^
+t7783.scala:11: warning: type D in object O is deprecated:
+ type T = O.D
+ ^
+t7783.scala:12: warning: type D in object O is deprecated:
+ locally(null: O.D)
+ ^
+t7783.scala:13: warning: type D in object O is deprecated:
+ val x: O.D = null
+ ^
+t7783.scala:14: warning: type D in object O is deprecated:
+ locally(null.asInstanceOf[O.D])
+ ^
+error: No warnings can be incurred under -Xfatal-warnings.
+5 warnings found
+one error found
diff --git a/test/files/neg/t7783.flags b/test/files/neg/t7783.flags
new file mode 100644
index 0000000000..d1b831ea87
--- /dev/null
+++ b/test/files/neg/t7783.flags
@@ -0,0 +1 @@
+-deprecation -Xfatal-warnings \ No newline at end of file
diff --git a/test/files/neg/t7783.scala b/test/files/neg/t7783.scala
new file mode 100644
index 0000000000..995b644a09
--- /dev/null
+++ b/test/files/neg/t7783.scala
@@ -0,0 +1,15 @@
+object O { class C; @deprecated("", "") type D = C; def foo: Seq[D] = Nil }
+
+object NoWarn {
+ O.foo // nowarn
+ O.foo +: Nil // nowarn
+ def bar(a: Any, b: Any) = () // nowarn
+ bar(b = O.foo, a = ()) // nowarn
+}
+
+object Warn {
+ type T = O.D
+ locally(null: O.D)
+ val x: O.D = null
+ locally(null.asInstanceOf[O.D])
+}
diff --git a/test/files/neg/t7895.check b/test/files/neg/t7895.check
new file mode 100644
index 0000000000..1a58e24b77
--- /dev/null
+++ b/test/files/neg/t7895.check
@@ -0,0 +1,4 @@
+t7895.scala:4: error: not found: value Goop
+ case Goop(a, b, c) => Tuple2(a, b)
+ ^
+one error found
diff --git a/test/files/neg/t7895.scala b/test/files/neg/t7895.scala
new file mode 100644
index 0000000000..87a586a82d
--- /dev/null
+++ b/test/files/neg/t7895.scala
@@ -0,0 +1,6 @@
+class A {
+ (null: Any) match {
+ // We don't want "symbol not found errors" for `a` and `b` in the case body.
+ case Goop(a, b, c) => Tuple2(a, b)
+ }
+}
diff --git a/test/files/neg/t7895b.check b/test/files/neg/t7895b.check
new file mode 100644
index 0000000000..87ea72704e
--- /dev/null
+++ b/test/files/neg/t7895b.check
@@ -0,0 +1,7 @@
+t7895b.scala:4: error: not found: value a
+ foo(a, b)
+ ^
+t7895b.scala:4: error: not found: value b
+ foo(a, b)
+ ^
+two errors found
diff --git a/test/files/neg/t7895b.scala b/test/files/neg/t7895b.scala
new file mode 100644
index 0000000000..1603027446
--- /dev/null
+++ b/test/files/neg/t7895b.scala
@@ -0,0 +1,5 @@
+object Test {
+ def foo(a: Any*) = ()
+
+ foo(a, b)
+}
diff --git a/test/files/neg/t7895c.check b/test/files/neg/t7895c.check
new file mode 100644
index 0000000000..d4745b1f4b
--- /dev/null
+++ b/test/files/neg/t7895c.check
@@ -0,0 +1,13 @@
+t7895c.scala:2: error: not found: value bong
+ def booboo = bong + booble + bippity - bazingo
+ ^
+t7895c.scala:2: error: not found: value booble
+ def booboo = bong + booble + bippity - bazingo
+ ^
+t7895c.scala:2: error: not found: value bippity
+ def booboo = bong + booble + bippity - bazingo
+ ^
+t7895c.scala:2: error: not found: value bazingo
+ def booboo = bong + booble + bippity - bazingo
+ ^
+four errors found
diff --git a/test/files/neg/t7895c.scala b/test/files/neg/t7895c.scala
new file mode 100644
index 0000000000..53d2a8672e
--- /dev/null
+++ b/test/files/neg/t7895c.scala
@@ -0,0 +1,3 @@
+class A {
+ def booboo = bong + booble + bippity - bazingo
+}
diff --git a/test/files/neg/t7899.check b/test/files/neg/t7899.check
new file mode 100644
index 0000000000..febfe76b8a
--- /dev/null
+++ b/test/files/neg/t7899.check
@@ -0,0 +1,6 @@
+t7899.scala:5: error: type mismatch;
+ found : Int => Int
+ required: (=> Int) => ?
+ foo(identity)()
+ ^
+one error found
diff --git a/test/files/neg/t7899.scala b/test/files/neg/t7899.scala
new file mode 100644
index 0000000000..f2dea3ab1f
--- /dev/null
+++ b/test/files/neg/t7899.scala
@@ -0,0 +1,7 @@
+object Test {
+ def foo[B](f: (=> Int) => B): () => B = () => f(0)
+
+ def main(args: Array[String]) {
+ foo(identity)()
+ }
+}
diff --git a/test/files/neg/t997.check b/test/files/neg/t997.check
index be1e92c369..8c41060ba2 100644
--- a/test/files/neg/t997.check
+++ b/test/files/neg/t997.check
@@ -4,7 +4,4 @@ t997.scala:13: error: wrong number of patterns for object Foo offering (String,
t997.scala:13: error: wrong number of patterns for object Foo offering (String, String): expected 2, found 3
"x" match { case Foo(a, b, c) => Console.println((a,b,c)) }
^
-t997.scala:13: error: not found: value a
-"x" match { case Foo(a, b, c) => Console.println((a,b,c)) }
- ^
-three errors found
+two errors found
diff --git a/test/files/neg/typeerror.check b/test/files/neg/typeerror.check
index 3ce11dad8a..f117e702f0 100644
--- a/test/files/neg/typeerror.check
+++ b/test/files/neg/typeerror.check
@@ -3,4 +3,9 @@ typeerror.scala:6: error: type mismatch;
required: scala.Long
else add2(x.head, y.head) :: add(x.tail, y.tail)
^
-one error found
+typeerror.scala:6: error: type mismatch;
+ found : Long(in method add)
+ required: scala.Long
+ else add2(x.head, y.head) :: add(x.tail, y.tail)
+ ^
+two errors found
diff --git a/test/files/neg/valueclasses-doubledefs.check b/test/files/neg/valueclasses-doubledefs.check
index 556d7a0900..ec513aca6b 100644
--- a/test/files/neg/valueclasses-doubledefs.check
+++ b/test/files/neg/valueclasses-doubledefs.check
@@ -1,6 +1,6 @@
valueclasses-doubledefs.scala:5: error: double definition:
-method apply:(x: Meter)String and
-method apply:(x: Double)String at line 4
+def apply(x: Double): String at line 4 and
+def apply(x: Meter): String at line 5
have same type after erasure: (x: Double)String
def apply(x: Meter) = x.toString
^
diff --git a/test/files/neg/valueclasses-pavlov.check b/test/files/neg/valueclasses-pavlov.check
index 031589edad..17102a0c68 100644
--- a/test/files/neg/valueclasses-pavlov.check
+++ b/test/files/neg/valueclasses-pavlov.check
@@ -1,6 +1,6 @@
valueclasses-pavlov.scala:8: error: double definition:
-method foo:(x: Box2)String and
-method foo:(x: String)String at line 7
+def foo(x: String): String at line 7 and
+def foo(x: Box2): String at line 8
have same type after erasure: (x: String)String
def foo(x: Box2) = "foo(Box2): ok"
^
diff --git a/test/files/pos/sammy_poly.flags b/test/files/pos/sammy_poly.flags
new file mode 100644
index 0000000000..48fd867160
--- /dev/null
+++ b/test/files/pos/sammy_poly.flags
@@ -0,0 +1 @@
+-Xexperimental
diff --git a/test/files/pos/sammy_poly.scala b/test/files/pos/sammy_poly.scala
new file mode 100644
index 0000000000..c629be7166
--- /dev/null
+++ b/test/files/pos/sammy_poly.scala
@@ -0,0 +1,7 @@
+// test synthesizeSAMFunction where the sam type is not fully defined
+class T {
+ trait F[T, U] { def apply(x: T): U }
+ // NOTE: the f(x) desugaring for now assumes the single abstract method is called 'apply'
+ def app[T, U](x: T)(f: F[T, U]): U = f(x)
+ app(1)(x => List(x))
+} \ No newline at end of file
diff --git a/test/files/pos/sammy_scope.flags b/test/files/pos/sammy_scope.flags
new file mode 100644
index 0000000000..48fd867160
--- /dev/null
+++ b/test/files/pos/sammy_scope.flags
@@ -0,0 +1 @@
+-Xexperimental
diff --git a/test/files/pos/sammy_scope.scala b/test/files/pos/sammy_scope.scala
new file mode 100644
index 0000000000..8f1fe7058e
--- /dev/null
+++ b/test/files/pos/sammy_scope.scala
@@ -0,0 +1,8 @@
+// test synthesizeSAMFunction: scope hygiene
+abstract class SamFun[T1, R] { self =>
+ def apply(v1: T1): R
+
+ // this should type check, as the apply ref is equivalent to self.apply
+ // it shouldn't resolve to the sam's apply that's synthesized (that wouldn't type check, hence the pos test)
+ def compose[A](g: SamFun[A, T1]): SamFun[A, R] = { x => apply(g(x)) }
+} \ No newline at end of file
diff --git a/test/files/pos/sammy_single.flags b/test/files/pos/sammy_single.flags
new file mode 100644
index 0000000000..48fd867160
--- /dev/null
+++ b/test/files/pos/sammy_single.flags
@@ -0,0 +1 @@
+-Xexperimental
diff --git a/test/files/pos/sammy_single.scala b/test/files/pos/sammy_single.scala
new file mode 100644
index 0000000000..7a3d272983
--- /dev/null
+++ b/test/files/pos/sammy_single.scala
@@ -0,0 +1,9 @@
+// test that dependent types work
+// TODO: def apply(x: String): x.type does NOT work yet
+object Test {
+ val s: String = ""
+
+ trait T { def apply(x: s.type): s.type }
+
+ val preservedResult: s.type = ((x => x): T)(s)
+} \ No newline at end of file
diff --git a/test/files/pos/sammy_twice.flags b/test/files/pos/sammy_twice.flags
new file mode 100644
index 0000000000..48fd867160
--- /dev/null
+++ b/test/files/pos/sammy_twice.flags
@@ -0,0 +1 @@
+-Xexperimental
diff --git a/test/files/pos/sammy_twice.scala b/test/files/pos/sammy_twice.scala
new file mode 100644
index 0000000000..c91f5b9fd2
--- /dev/null
+++ b/test/files/pos/sammy_twice.scala
@@ -0,0 +1,9 @@
+// test repeated synthesizeSAMFunction where the sam type is not fully defined
+// the naive implementation would enter the same apply$body in the same scope twice
+trait F[T, U] { def apply(x: T): U }
+
+class C {
+ def app[T, U](x: T)(f: F[T, U]): U = f(x)
+ app(1)(x => List(x))
+ app(2)(x => List(x))
+} \ No newline at end of file
diff --git a/test/files/pos/t6221.scala b/test/files/pos/t6221.scala
index dd7776f596..34f02859f3 100644
--- a/test/files/pos/t6221.scala
+++ b/test/files/pos/t6221.scala
@@ -7,23 +7,27 @@ class MyCollection[A] {
class OtherFunc[-A, +B] {}
object Test {
- implicit def functionToMyFunc[A, B](f: A => B): MyFunc[A, B] = new MyFunc
+ implicit def functionToMyFunc[A, B](f: A => B): MyFunc[A, B] = new MyFunc // = new MyFunc[A,Nothing]();
- implicit def otherFuncToMyFunc[A, B](f: OtherFunc[A, B]): MyFunc[A, B] = new MyFunc
+ implicit def otherFuncToMyFunc[A, B](f: OtherFunc[A, B]): MyFunc[A, B] = new MyFunc // = new MyFunc[A,Nothing]();
def main(args: Array[String]) {
val col = new MyCollection[Int]
// Doesn't compile: error: missing parameter type for expanded function ((x$1) => x$1.toString)
println(col.map(_.toString))
+ // scala.this.Predef.println(col.map[String](Test.this.functionToMyFunc[Int, String](((x$1: Int) => x$1.toString()))));
// Doesn't compile: error: missing parameter type
println(col.map(x => x.toString))
+ // scala.this.Predef.println(col.map[String](Test.this.functionToMyFunc[Int, String](((x: Int) => x.toString()))));
// Does compile
println(col.map((x: Int) => x.toString))
+ // scala.this.Predef.println(col.map[String](Test.this.functionToMyFunc[Int, String](((x: Int) => x.toString()))));
// Does compile (even though type params of OtherFunc not given)
println(col.map(new OtherFunc))
+ // scala.this.Predef.println(col.map[Nothing](Test.this.otherFuncToMyFunc[Any, Nothing](new OtherFunc[Any,Nothing]())))
}
} \ No newline at end of file
diff --git a/test/files/pos/t7584.scala b/test/files/pos/t7584.scala
deleted file mode 100644
index 52d127ecb9..0000000000
--- a/test/files/pos/t7584.scala
+++ /dev/null
@@ -1,11 +0,0 @@
-object Test {
- def fold[A, B](f: (A, => B) => B) = ???
- def f[A, B](x: A, y: B): B = ???
- def bip[A, B] = fold[A, B]((x, y) => f(x, y))
- def bop[A, B] = fold[A, B](f)
-
- // these work:
- fold[Int, Int]((x, y) => f(x, y))
- fold[Int, Int](f)
-}
-
diff --git a/test/files/pos/t7688.scala b/test/files/pos/t7688.scala
new file mode 100644
index 0000000000..5a846b97e9
--- /dev/null
+++ b/test/files/pos/t7688.scala
@@ -0,0 +1,7 @@
+import scala.reflect.macros._
+
+class A[C <: Context with Singleton](position: C#Position)
+
+object A {
+ def apply(c: Context)(in: c.Tree): A[c.type] = new A(in.pos)
+}
diff --git a/test/files/pos/t7902.scala b/test/files/pos/t7902.scala
new file mode 100644
index 0000000000..47c525c179
--- /dev/null
+++ b/test/files/pos/t7902.scala
@@ -0,0 +1,17 @@
+import scala.language.higherKinds
+
+object Bug {
+ class Tag[W[M1[X1]]]
+
+ def ofType[W[M2[X2]]]: Tag[W] = ???
+ type InSeq [M3[X3]] = Some[M3[Any]]
+
+ // fail
+ val x = ofType[InSeq]
+
+ // okay
+ val y: Any = ofType[InSeq]
+ object T {
+ val z = ofType[InSeq]
+ }
+}
diff --git a/test/files/res/t687.check b/test/files/res/t687.check
index b741b262b9..5f72c98636 100644
--- a/test/files/res/t687.check
+++ b/test/files/res/t687.check
@@ -1,8 +1,8 @@
nsc>
nsc> t687/QueryB.scala:3: error: name clash between defined and inherited member:
-method equals:(o: Object)Boolean and
-method equals:(x$1: Any)Boolean in class Any
-have same type after erasure: (o: Object)Boolean
+def equals(x$1: Any): Boolean in class Any and
+override def equals(o: Object): Boolean at line 3
+have same type after erasure: (x$1: Object)Boolean
override def equals(o : Object) = false;
^
diff --git a/test/files/run/constrained-types.check b/test/files/run/constrained-types.check
index f022aac1b2..d965d8a2ff 100644
--- a/test/files/run/constrained-types.check
+++ b/test/files/run/constrained-types.check
@@ -138,6 +138,15 @@ scala> val x = 3 : Int @Annot(e+f+g+h) // should have a graceful error message
<console>:8: error: not found: value e
val x = 3 : Int @Annot(e+f+g+h) // should have a graceful error message
^
+<console>:8: error: not found: value f
+ val x = 3 : Int @Annot(e+f+g+h) // should have a graceful error message
+ ^
+<console>:8: error: not found: value g
+ val x = 3 : Int @Annot(e+f+g+h) // should have a graceful error message
+ ^
+<console>:8: error: not found: value h
+ val x = 3 : Int @Annot(e+f+g+h) // should have a graceful error message
+ ^
scala>
diff --git a/test/files/run/macro-vampire-false-warning.check b/test/files/run/macro-vampire-false-warning.check
new file mode 100644
index 0000000000..4792e70f33
--- /dev/null
+++ b/test/files/run/macro-vampire-false-warning.check
@@ -0,0 +1,2 @@
+2
+3
diff --git a/test/files/run/macro-vampire-false-warning.flags b/test/files/run/macro-vampire-false-warning.flags
new file mode 100644
index 0000000000..e8fb65d50c
--- /dev/null
+++ b/test/files/run/macro-vampire-false-warning.flags
@@ -0,0 +1 @@
+-Xfatal-warnings \ No newline at end of file
diff --git a/test/files/run/macro-vampire-false-warning/Macros_1.scala b/test/files/run/macro-vampire-false-warning/Macros_1.scala
new file mode 100644
index 0000000000..2d384fbb85
--- /dev/null
+++ b/test/files/run/macro-vampire-false-warning/Macros_1.scala
@@ -0,0 +1,52 @@
+// As per http://meta.plasm.us/posts/2013/08/31/feeding-our-vampires/
+
+import scala.annotation.StaticAnnotation
+import scala.reflect.macros.Context
+import scala.language.experimental.macros
+
+class body(tree: Any) extends StaticAnnotation
+
+object Macros {
+ def selFieldImpl(c: Context) = {
+ import c.universe._
+ val field = c.macroApplication.symbol
+ val bodyAnn = field.annotations.filter(_.tpe <:< typeOf[body]).head
+ c.Expr[Any](bodyAnn.scalaArgs.head)
+ }
+
+ def mkObjectImpl(c: Context)(xs: c.Expr[Any]*) = {
+ import c.universe._
+ import Flag._
+ // val kvps = xs.toList map { case q"${_}(${Literal(Constant(name: String))}).->[${_}]($value)" => name -> value }
+ val kvps = xs.map(_.tree).toList map { case Apply(TypeApply(Select(Apply(_, List(Literal(Constant(name: String)))), _), _), List(value)) => name -> value }
+ // val fields = kvps map { case (k, v) => q"@body($v) def ${TermName(k)} = macro Macros.selFieldImpl" }
+ val fields = kvps map { case (k, v) => DefDef(
+ Modifiers(MACRO, tpnme.EMPTY, List(Apply(Select(New(Ident(TypeName("body"))), nme.CONSTRUCTOR), List(v)))),
+ TermName(k), Nil, Nil, TypeTree(), Select(Ident(TermName("Macros")), TermName("selFieldImpl"))) }
+ // q"import scala.language.experimental.macros; class Workaround { ..$fields }; new Workaround{}"
+ c.Expr[Any](Block(
+ List(
+ Import(Select(Select(Ident(TermName("scala")), TermName("language")), TermName("experimental")), List(ImportSelector(TermName("macros"), 51, TermName("macros"), 51))),
+ ClassDef(
+ NoMods, TypeName("Workaround"), Nil,
+ Template(
+ List(Select(Ident(TermName("scala")), TypeName("AnyRef"))), noSelfType,
+ DefDef(
+ NoMods, nme.CONSTRUCTOR, Nil, List(Nil), TypeTree(),
+ Block(List(Apply(Select(Super(This(tpnme.EMPTY), tpnme.EMPTY), nme.CONSTRUCTOR), List())), Literal(Constant(()))))
+ +: fields)),
+ ClassDef(
+ Modifiers(FINAL), TypeName("$anon"), Nil,
+ Template(
+ List(Ident(TypeName("Workaround"))), noSelfType,
+ List(
+ DefDef(
+ NoMods, nme.CONSTRUCTOR, Nil, List(Nil), TypeTree(),
+ Block(List(Apply(Select(Super(This(tpnme.EMPTY), tpnme.EMPTY), nme.CONSTRUCTOR), List())), Literal(Constant(())))))))),
+ Apply(Select(New(Ident(TypeName("$anon"))), nme.CONSTRUCTOR), List())))
+ }
+}
+
+object mkObject {
+ def apply(xs: Any*) = macro Macros.mkObjectImpl
+}
diff --git a/test/files/run/macro-vampire-false-warning/Test_2.scala b/test/files/run/macro-vampire-false-warning/Test_2.scala
new file mode 100644
index 0000000000..6e44b68635
--- /dev/null
+++ b/test/files/run/macro-vampire-false-warning/Test_2.scala
@@ -0,0 +1,6 @@
+object Test extends App {
+ val foo = mkObject("x" -> "2", "y" -> 3)
+ println(foo.x)
+ println(foo.y)
+ // println(foo.z) => will result in a compilation error
+} \ No newline at end of file
diff --git a/test/files/run/private-override.check b/test/files/run/private-override.check
new file mode 100644
index 0000000000..00750edc07
--- /dev/null
+++ b/test/files/run/private-override.check
@@ -0,0 +1 @@
+3
diff --git a/test/files/run/private-override.scala b/test/files/run/private-override.scala
new file mode 100644
index 0000000000..0a3f57f97c
--- /dev/null
+++ b/test/files/run/private-override.scala
@@ -0,0 +1,17 @@
+package test.p1.p2 {
+ abstract class A {
+ private[p2] def f2(): Int = 1
+ }
+ abstract class Other extends A {
+ // It's a private method - not a private[p2] method. Not a failed
+ // "weaker access privileges" override, a different namespace.
+ private def f2(): Int = super.f2() + 2
+ def go() = f2()
+ }
+}
+
+object Test extends test.p1.p2.Other {
+ def main(args: Array[String]): Unit = {
+ println(go())
+ }
+}
diff --git a/test/files/run/repl-reset.check b/test/files/run/repl-reset.check
index c6e147977a..ed95c7b8ff 100644
--- a/test/files/run/repl-reset.check
+++ b/test/files/run/repl-reset.check
@@ -33,6 +33,12 @@ scala> x1 + x2 + x3
<console>:8: error: not found: value x1
x1 + x2 + x3
^
+<console>:8: error: not found: value x2
+ x1 + x2 + x3
+ ^
+<console>:8: error: not found: value x3
+ x1 + x2 + x3
+ ^
scala> val x1 = 4
x1: Int = 4
diff --git a/test/files/run/sammy_java8.flags b/test/files/run/sammy_java8.flags
new file mode 100644
index 0000000000..48fd867160
--- /dev/null
+++ b/test/files/run/sammy_java8.flags
@@ -0,0 +1 @@
+-Xexperimental
diff --git a/test/files/run/sammy_java8.scala b/test/files/run/sammy_java8.scala
new file mode 100644
index 0000000000..db9df7f5fe
--- /dev/null
+++ b/test/files/run/sammy_java8.scala
@@ -0,0 +1,34 @@
+import scala.tools.partest._
+
+// java8 version of sammy_poly.scala
+object Test extends CompilerTest {
+ import global._
+
+ override lazy val units: List[CompilationUnit] = {
+ global.settings.Xexperimental.value = true
+
+ // This test itself does not depend on JDK8.
+ javaCompilationUnits(global)(samSource) ++
+ compilationUnits(global)(useSamSource)
+ }
+
+ private def samSource = """
+// trait F[T, U] { def apply(x: T): U }
+public interface F<T, U> {
+ U apply(T t);
+ default void yadayada() {
+ throw new UnsupportedOperationException("yadayada");
+ }
+}
+ """
+
+ private def useSamSource = """
+class T {
+ def app[T, U](x: T)(f: F[T, U]): U = f(x)
+ app(1)(x => List(x))
+}
+ """
+
+ // We're only checking we can compile it.
+ def check(source: String, unit: global.CompilationUnit): Unit = ()
+}
diff --git a/test/files/run/t4542.check b/test/files/run/t4542.check
index 5a8108dcbc..a53f31a3c7 100644
--- a/test/files/run/t4542.check
+++ b/test/files/run/t4542.check
@@ -9,9 +9,6 @@ defined class Foo
scala> val f = new Foo
<console>:8: warning: class Foo is deprecated: foooo
val f = new Foo
- ^
-<console>:8: warning: class Foo is deprecated: foooo
- val f = new Foo
^
f: Foo = Bippy
diff --git a/test/files/run/t7398.scala b/test/files/run/t7398.scala
index 493c4dcf40..4b46850768 100644
--- a/test/files/run/t7398.scala
+++ b/test/files/run/t7398.scala
@@ -21,6 +21,6 @@ public interface Iterator<E> {
}
"""
- // We're only checking we can parse it.
+ // We're only checking we can compile it.
def check(source: String, unit: global.CompilationUnit): Unit = ()
}
diff --git a/test/files/run/t7584b.scala b/test/files/run/t7584b.scala
new file mode 100644
index 0000000000..fd560f0418
--- /dev/null
+++ b/test/files/run/t7584b.scala
@@ -0,0 +1,14 @@
+object Test extends App {
+ def fold[A, B](f: (A, => B) => B) = (b: B) => f(null.asInstanceOf[A], b)
+ def f[A, B](x: A, y: B): B = y
+ def bip[A, B] = fold[A, B]((x, y) => f(x, y))
+ def bop[A, B] = fold[A, B](f(_, _))
+
+ // these work:
+ fold[Int, Int]((x, y) => f(x, y))(0)
+ fold[Int, Int](f(_, _))(0)
+
+ // Used to throw a ClassCastException. Since the fix for SI-7899, these issue type errors.
+ // fold[Int, Int](f _)(0)
+ // fold[Int, Int](f)(0)
+}
diff --git a/test/files/run/t7899-regression.check b/test/files/run/t7899-regression.check
new file mode 100644
index 0000000000..602b03a1d1
--- /dev/null
+++ b/test/files/run/t7899-regression.check
@@ -0,0 +1 @@
+warning: -Yinfer-by-name is deprecated: This flag is scheduled for removal in 2.12. If you have a case where you need this flag then please report a bug.
diff --git a/test/files/run/t7899-regression.flags b/test/files/run/t7899-regression.flags
new file mode 100644
index 0000000000..553a27eafd
--- /dev/null
+++ b/test/files/run/t7899-regression.flags
@@ -0,0 +1 @@
+-Yinfer-by-name -deprecation
diff --git a/test/files/run/t7899-regression.scala b/test/files/run/t7899-regression.scala
new file mode 100644
index 0000000000..67d38cdd1d
--- /dev/null
+++ b/test/files/run/t7899-regression.scala
@@ -0,0 +1,24 @@
+import language.higherKinds
+
+object Test {
+ trait Monad[M[_]] {
+ def foo[A](ma: M[A])(f: M[A] => Any) = f(ma)
+ }
+ implicit def function1Covariant[T]: Monad[({type l[a] = (T => a)})#l] =
+ new Monad[({type l[a] = (T => a)})#l] {}
+
+ def main(args: Array[String]) {
+ // inference of T = (=> Any) here was outlawed by SI-7899 / 8ed7099
+ // but this pattern is used in Scalaz in just a few places and caused
+ // a regression.
+ //
+ // Inference of a by-name type doesn't *always* lead to a ClassCastException,
+ // it only gets there if a method in generic code accepts a parameter of
+ // that type.
+ //
+ // We need to introduce the stricter inference rules gradually, probably
+ // with a warning.
+ val m = implicitly[Monad[({type f[+x] = (=> Any) => x})#f]]
+ assert(m.foo[Int]((x => 0))(f => f(???)) == 0)
+ }
+}
diff --git a/test/files/run/t7899.scala b/test/files/run/t7899.scala
new file mode 100644
index 0000000000..5879d4b9fe
--- /dev/null
+++ b/test/files/run/t7899.scala
@@ -0,0 +1,5 @@
+object Test extends App {
+ def id[A](a: => A): A = null.asInstanceOf[A]
+ def foo(f: (=> Int) => Int) = () => f(???)
+ foo(id)() // should be allowed and not throw ???
+}