summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/compiler/scala/tools/nsc/Global.scala4
-rw-r--r--src/compiler/scala/tools/nsc/Settings.scala2
-rw-r--r--src/compiler/scala/tools/nsc/ast/TreeBrowsers.scala4
-rw-r--r--src/compiler/scala/tools/nsc/ast/TreeGen.scala33
-rw-r--r--src/compiler/scala/tools/nsc/ast/TreeInfo.scala3
-rw-r--r--src/compiler/scala/tools/nsc/ast/TreePrinters.scala3
-rw-r--r--src/compiler/scala/tools/nsc/ast/Trees.scala31
-rw-r--r--src/compiler/scala/tools/nsc/backend/icode/TypeKinds.scala3
-rw-r--r--src/compiler/scala/tools/nsc/symtab/AnnotationInfos.scala128
-rw-r--r--src/compiler/scala/tools/nsc/symtab/Definitions.scala3
-rw-r--r--src/compiler/scala/tools/nsc/symtab/GenerateIdeMaps.scala2
-rw-r--r--src/compiler/scala/tools/nsc/symtab/StdNames.scala1
-rw-r--r--src/compiler/scala/tools/nsc/symtab/SymbolTable.scala2
-rw-r--r--src/compiler/scala/tools/nsc/symtab/Symbols.scala7
-rw-r--r--src/compiler/scala/tools/nsc/symtab/Types.scala401
-rw-r--r--src/compiler/scala/tools/nsc/symtab/classfile/PickleFormat.scala189
-rw-r--r--src/compiler/scala/tools/nsc/symtab/classfile/Pickler.scala851
-rw-r--r--src/compiler/scala/tools/nsc/symtab/classfile/UnPickler.scala602
-rw-r--r--src/compiler/scala/tools/nsc/transform/Erasure.scala2
-rw-r--r--src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala2
-rw-r--r--src/compiler/scala/tools/nsc/transform/LiftCode.scala147
-rw-r--r--src/compiler/scala/tools/nsc/transform/Reifiers.scala (renamed from src/compiler/scala/tools/nsc/transform/SymbolReifier.scala)152
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Infer.scala2
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Namers.scala22
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/RefChecks.scala2
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala2
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Typers.scala145
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Variances.scala2
-rw-r--r--src/compiler/scala/tools/nsc/util/RegexCache.scala40
-rw-r--r--src/library/scala/TypeConstraint.scala30
-rw-r--r--test/files/run/constrained-types.check136
-rw-r--r--test/files/run/constrained-types.scala103
32 files changed, 2174 insertions, 882 deletions
diff --git a/src/compiler/scala/tools/nsc/Global.scala b/src/compiler/scala/tools/nsc/Global.scala
index 626b9bf885..6326b9e130 100644
--- a/src/compiler/scala/tools/nsc/Global.scala
+++ b/src/compiler/scala/tools/nsc/Global.scala
@@ -32,7 +32,7 @@ import backend.msil.GenMSIL
import backend.opt.{Inliners, ClosureElimination, DeadCodeElimination}
import backend.icode.analysis._
-class Global(var settings: Settings, var reporter: Reporter) extends Trees
+class Global(var settings: Settings, var reporter: Reporter) extends SymbolTable
with CompilationUnits
with Plugins
{
@@ -55,6 +55,8 @@ class Global(var settings: Settings, var reporter: Reporter) extends Trees
object gen extends TreeGen {
val global: Global.this.type = Global.this
+ def mkAttributedCast(tree: Tree, pt: Type): Tree =
+ typer.typed(mkAttributedCastUntyped(tree, pt))
}
object constfold extends ConstantFolder {
diff --git a/src/compiler/scala/tools/nsc/Settings.scala b/src/compiler/scala/tools/nsc/Settings.scala
index 68df5f5ade..b827ef5ea5 100644
--- a/src/compiler/scala/tools/nsc/Settings.scala
+++ b/src/compiler/scala/tools/nsc/Settings.scala
@@ -155,6 +155,8 @@ class Settings(error: String => Unit) {
val Xcasetags = ChoiceSetting("-Ycasetags", "test integer tags for case classes", List("on","off"),
/*default*/"off")
+ val selfInAnnots = BooleanSetting ("-Yself-in-annots", "Include a \"self\" identifier inside of annotations")
+
/** scaladoc specific options */
val memberaccess = ChoiceSetting ("-access", "Show only public, protected/public (default) or all classes and members",
List("public", "protected", "private"), "protected").dependsOn(doc)
diff --git a/src/compiler/scala/tools/nsc/ast/TreeBrowsers.scala b/src/compiler/scala/tools/nsc/ast/TreeBrowsers.scala
index d91aa6fa75..6ef9f61610 100644
--- a/src/compiler/scala/tools/nsc/ast/TreeBrowsers.scala
+++ b/src/compiler/scala/tools/nsc/ast/TreeBrowsers.scala
@@ -17,6 +17,7 @@ import javax.swing.tree._
import scala.concurrent.Lock
import scala.text._
import symtab.Flags._
+import symtab.SymbolTable
/**
* Tree browsers can show the AST in a graphical and interactive
@@ -26,7 +27,6 @@ import symtab.Flags._
* @version 1.0
*/
abstract class TreeBrowsers {
-
val global: Global
import global._
import nme.EMPTY
@@ -663,7 +663,7 @@ abstract class TreeBrowsers {
toDocument(result) :: ")")
)
- case AnnotatedType(attribs, tp) =>
+ case AnnotatedType(attribs, tp, _) =>
Document.group(
Document.nest(4, "AnnotatedType(" :/:
attribs.mkString("[", ",", "]") :/:
diff --git a/src/compiler/scala/tools/nsc/ast/TreeGen.scala b/src/compiler/scala/tools/nsc/ast/TreeGen.scala
index 6bc136e976..d4544252fc 100644
--- a/src/compiler/scala/tools/nsc/ast/TreeGen.scala
+++ b/src/compiler/scala/tools/nsc/ast/TreeGen.scala
@@ -8,10 +8,11 @@ package scala.tools.nsc.ast
import scala.collection.mutable.ListBuffer
import symtab.Flags._
+import symtab.SymbolTable
abstract class TreeGen {
- val global: Global
+ val global: SymbolTable
import global._
import definitions._
@@ -44,10 +45,26 @@ abstract class TreeGen {
case _ =>
qual
}
- } else {
- assert(phase.erasedTypes)
+ } else if (sym.isModule || sym.isClass) {
+ assert(phase.erasedTypes, tpe)
mkAttributedThis(sym)
+ } else {
+ mkAttributedRef(pre, sym)
}
+
+ case ConstantType(value) =>
+ Literal(value) setType tpe
+
+ case AnnotatedType(_, atp, _) =>
+ mkAttributedQualifier(atp)
+
+ case RefinedType(parents, _) =>
+ // I am unclear whether this is reachable, but
+ // the following implementation looks logical -Lex
+ val firstStable = parents.find(_.isStable)
+ assert(!firstStable.isEmpty)
+ mkAttributedQualifier(firstStable.get)
+
case _ =>
throw new Error("bad qualifier: " + tpe)
}
@@ -83,14 +100,12 @@ abstract class TreeGen {
}
/** Cast `tree' to type `pt' */
- def mkAttributedCast(tree: Tree, pt: Type): Tree = {
+ def mkAttributedCastUntyped(tree: Tree, pt: Type): Tree = {
if (settings.debug.value) log("casting " + tree + ":" + tree.tpe + " to " + pt)
assert(!tree.tpe.isInstanceOf[MethodType], tree)
assert(pt eq pt.normalize) //@MAT only called during erasure, which already takes care of that
- typer.typed {
- atPos(tree.pos) {
- Apply(TypeApply(mkAttributedSelect(tree, Object_asInstanceOf), List(TypeTree(pt))), List())
- }
+ atPos(tree.pos) {
+ Apply(TypeApply(mkAttributedSelect(tree, Object_asInstanceOf), List(TypeTree(pt))), List())
}
}
@@ -105,7 +120,7 @@ abstract class TreeGen {
This(sym.name) setSymbol sym setType sym.thisType
def mkAttributedIdent(sym: Symbol): Tree = {
- assert(sym.isTerm)
+ assert(sym.isTerm, sym)
Ident(sym.name) setSymbol sym setType sym.tpe
}
diff --git a/src/compiler/scala/tools/nsc/ast/TreeInfo.scala b/src/compiler/scala/tools/nsc/ast/TreeInfo.scala
index 25941d3081..d814c5cd6c 100644
--- a/src/compiler/scala/tools/nsc/ast/TreeInfo.scala
+++ b/src/compiler/scala/tools/nsc/ast/TreeInfo.scala
@@ -7,6 +7,7 @@
package scala.tools.nsc.ast
import symtab.Flags._
+import symtab.SymbolTable
import util.HashSet
/** This class ...
@@ -16,7 +17,7 @@ import util.HashSet
*/
abstract class TreeInfo {
- val trees: Trees
+ val trees: SymbolTable
import trees._
def isTerm(tree: Tree): Boolean = tree.isTerm
diff --git a/src/compiler/scala/tools/nsc/ast/TreePrinters.scala b/src/compiler/scala/tools/nsc/ast/TreePrinters.scala
index 81e050945c..b148bb9b56 100644
--- a/src/compiler/scala/tools/nsc/ast/TreePrinters.scala
+++ b/src/compiler/scala/tools/nsc/ast/TreePrinters.scala
@@ -9,10 +9,11 @@ package scala.tools.nsc.ast
import compat.Platform.{EOL => LINE_SEPARATOR}
import java.io.{OutputStream, PrintWriter, Writer}
import symtab.Flags._
+import symtab.SymbolTable
abstract class TreePrinters {
- val trees: Trees
+ val trees: SymbolTable
import trees._
final val showOuterTests = false
diff --git a/src/compiler/scala/tools/nsc/ast/Trees.scala b/src/compiler/scala/tools/nsc/ast/Trees.scala
index 1949c4cc7c..4412aa0896 100644
--- a/src/compiler/scala/tools/nsc/ast/Trees.scala
+++ b/src/compiler/scala/tools/nsc/ast/Trees.scala
@@ -10,11 +10,13 @@ import java.io.{PrintWriter, StringWriter}
import scala.tools.nsc.symtab.{Flags, SymbolTable}
import scala.tools.nsc.symtab.Flags._
-import scala.tools.nsc.util.{HashSet, Position, NoPosition, SourceFile}
+import scala.tools.nsc.util.{FreshNameCreator, HashSet, Position, NoPosition, SourceFile}
import scala.collection.mutable.ListBuffer
-abstract class Trees extends SymbolTable {
+trait Trees {
+ self: SymbolTable =>
+
//statistics
var nodeCount = 0
@@ -22,6 +24,7 @@ abstract class Trees extends SymbolTable {
trait CompilationUnitTrait {
var body: Tree
val source: SourceFile
+ def fresh : FreshNameCreator
}
type CompilationUnit <: CompilationUnitTrait
@@ -122,11 +125,11 @@ abstract class Trees extends SymbolTable {
def isErroneous = (tpe ne null) && tpe.isErroneous
/** Apply `f' to each subtree */
- def foreach(f: Tree => Unit): Unit = new ForeachTraverser(f).traverse(this)
+ def foreach(f: Tree => Unit): Unit = new ForeachTreeTraverser(f).traverse(this)
/** Find all subtrees matching predicate `p' */
def filter(f: Tree => Boolean): List[Tree] = {
- val ft = new FilterTraverser(f)
+ val ft = new FilterTreeTraverser(f)
ft.traverse(this)
ft.hits.toList
}
@@ -135,7 +138,7 @@ abstract class Trees extends SymbolTable {
* or None if none exists.
*/
def find(p: Tree => Boolean): Option[Tree] = {
- val ft = new FindTraverser(p)
+ val ft = new FindTreeTraverser(p)
ft.traverse(this)
ft.result
}
@@ -207,6 +210,9 @@ abstract class Trees extends SymbolTable {
def duplicate: this.type =
(duplicator transform this).asInstanceOf[this.type]
+ def shallowDuplicate: this.type =
+ ((new ShallowDuplicator(this)) transform this).asInstanceOf[this.type]
+
def copyAttrs(tree: Tree): this.type = {
rawpos = tree.rawpos
tpe = tree.tpe
@@ -241,6 +247,15 @@ abstract class Trees extends SymbolTable {
override val copy = new StrictTreeCopier
}
+ private class ShallowDuplicator(orig: Tree) extends Transformer {
+ override val copy = new StrictTreeCopier
+ override def transform(tree: Tree) =
+ if (tree eq orig)
+ super.transform(tree)
+ else
+ tree
+ }
+
private def syntheticParams(owner: Symbol, mtp: Type): List[List[Symbol]] = {
var cnt = 0
def freshName() = { cnt += 1; newTermName("x$" + cnt) }
@@ -1586,14 +1601,14 @@ abstract class Trees extends SymbolTable {
}
}
- class ForeachTraverser(f: Tree => Unit) extends Traverser {
+ class ForeachTreeTraverser(f: Tree => Unit) extends Traverser {
override def traverse(t: Tree) {
f(t)
super.traverse(t)
}
}
- class FilterTraverser(p: Tree => Boolean) extends Traverser {
+ class FilterTreeTraverser(p: Tree => Boolean) extends Traverser {
val hits = new ListBuffer[Tree]
override def traverse(t: Tree) {
if (p(t)) hits += t
@@ -1601,7 +1616,7 @@ abstract class Trees extends SymbolTable {
}
}
- class FindTraverser(p: Tree => Boolean) extends Traverser {
+ class FindTreeTraverser(p: Tree => Boolean) extends Traverser {
var result: Option[Tree] = None
override def traverse(t: Tree) {
if (result.isEmpty) {
diff --git a/src/compiler/scala/tools/nsc/backend/icode/TypeKinds.scala b/src/compiler/scala/tools/nsc/backend/icode/TypeKinds.scala
index 79fdbbfce4..7519f28fc4 100644
--- a/src/compiler/scala/tools/nsc/backend/icode/TypeKinds.scala
+++ b/src/compiler/scala/tools/nsc/backend/icode/TypeKinds.scala
@@ -448,9 +448,6 @@ trait TypeKinds { self: ICodes =>
REFERENCE(sym)
}
- case AnnotatedType(attribs, tp) =>
- toTypeKind(tp)
-
//case WildcardType => // bq: useful hack when wildcard types come here
// REFERENCE(definitions.ObjectClass)
diff --git a/src/compiler/scala/tools/nsc/symtab/AnnotationInfos.scala b/src/compiler/scala/tools/nsc/symtab/AnnotationInfos.scala
index 1293c4702c..9ce0dae534 100644
--- a/src/compiler/scala/tools/nsc/symtab/AnnotationInfos.scala
+++ b/src/compiler/scala/tools/nsc/symtab/AnnotationInfos.scala
@@ -6,127 +6,76 @@
package scala.tools.nsc.symtab
-import scala.tools.nsc.transform.SymbolReifier
+import scala.tools.nsc.transform.Reifiers
import util._
/** AnnotationInfo and its helpers */
trait AnnotationInfos {
self: SymbolTable =>
- /** Convert a reflect tree to a Constant, if possible */
- private def refltree2cons(tree: reflect.Tree): Option[Constant] =
+ /** Convert a tree to a Constant, if possible */
+ private def tree2cons(tree: Tree): Option[Constant] =
tree match {
- case reflect.Literal(v) =>
- Some(Constant(v))
+ case Literal(v) => Some(v)
- case reflect.Apply(
- reflect.TypeApply(
- reflect.Select(_,
- reflect.Method(
- "scala.Array.apply",
- reflect.PolyType(_, _,
- reflect.MethodType(_, reflect.AppliedType(arrayType,_))))),
- List(elemType)),
- members) =>
+ case Apply(
+ TypeApply(
+ meth@Select(_,_),
+ List(elemType)),
+ members)
+ if (definitions.ArrayModule_apply.alternatives contains meth.symbol) =>
+ trees2consArray(members, tree.tpe)
- refltrees2consArray(
- members,
- reflect.AppliedType(arrayType, List(elemType)))
+ case Apply(meth, members)
+ if (definitions.ArrayModule_apply.alternatives contains meth.symbol) =>
+ trees2consArray(members, tree.tpe)
- case reflect.Apply(
- reflect.Select(_,
- reflect.Method(
- "scala.Array.apply",
- reflect.MethodType(_, arrayType))),
- members) =>
-
- refltrees2consArray(members, arrayType)
case tree =>
//println("could not convert: " + tree);
None
}
- private object symbolReifier extends SymbolReifier {
- val symbols: AnnotationInfos.this.type = AnnotationInfos.this
- }
-
- /** Convert a sequence of trees to an array type,
- * if all of the array elements are constants.
- * Use arrayType as type of the resulting constant.
- */
- private def refltrees2consArray(
- trees: Seq[reflect.Tree],
- arrayType: reflect.Type)
+ private def trees2consArray(trees: Seq[Tree], arrayType:Type)
: Option[Constant] =
{
- // println("arrayType is " + arrayType + " (" +
- // symbolReifier.unreify(arrayType) + ")")
-
- val mems = trees.map(refltree2cons)
+ val mems = trees.map(tree2cons)
if (mems.exists(_.isEmpty))
None
else
Some(new ArrayConstant(
mems.map(_.get).toArray,
- symbolReifier.unreify(arrayType)))
+ arrayType))
}
- /** Convert a constant to an equivalent reflect tree. */
- private def cons2refltree(cons: Constant): reflect.Tree = {
- import reflect._
-
- (cons: @unchecked) match {
- case acons:ArrayConstant =>
- val elems = acons.arrayValue.toList
- val arrayType = symbolReifier.reify(cons.tpe)
- val elemType: reflect.Type = arrayType match {
- case AppliedType(_, List(et)) => et
- case _ =>
- assert(false, "array type is not an array type");
- reflect.NoType
- }
- val elemTrees = elems map cons2refltree
-
- val arrayObject = reflect.This(reflect.Class("scala.Array"))
-
- // The following two gigantic trees were found by printing
- // out what the reifier makes. If the reifier changes, they
- // should be updated.
- if (symbolReifier.unreify(elemType) <:< definitions.AnyValClass.tpe)
- Apply(Select(Select(Ident(Field("scala",PrefixedType(reflect.ThisType(RootSymbol),Class("scala")))),Field("scala.Array",PrefixedType(reflect.ThisType(Class("scala")),Class("scala.Array")))),Method("scala.Array.apply",reflect.MethodType(List(AppliedType(PrefixedType(reflect.ThisType(Class("scala")),Class("scala.<repeated>")),List(PrefixedType(reflect.ThisType(Class("scala")),Class("scala.Int"))))),AppliedType(PrefixedType(reflect.ThisType(Class("scala")),Class("scala.Array")),
- List(elemType))))), elemTrees)
+ /** An argument to an annotation. It includes a parse tree,
+ * and it includes a compile-time constant for the tree if possible.
+ */
+ class AnnotationArgument(val intTree: Tree) {
+ def this(cons: Constant) = this(
+ Literal(cons).setType(cons.tpe))
- else
- Apply(TypeApply(Select(Select(Ident(Field("scala",PrefixedType(reflect.ThisType(RootSymbol),Class("scala")))),Field("scala.Array",PrefixedType(reflect.ThisType(Class("scala")),Class("scala.Array")))),Method("scala.Array.apply",reflect.PolyType(List(reflect.NoSymbol),List((PrefixedType(reflect.ThisType(Class("scala")),Class("scala.Nothing")),PrefixedType(reflect.ThisType(Class("scala")),TypeField("scala.AnyRef",PrefixedType(reflect.ThisType(Class("java.lang")),Class("java.lang.Object")))))),reflect.MethodType(List(AppliedType(PrefixedType(reflect.ThisType(Class("scala")),Class("scala.<repeated>")),List(PrefixedType(reflect.NoType,reflect.NoSymbol)))),AppliedType(PrefixedType(reflect.ThisType(Class("scala")),Class("scala.Array")),List(PrefixedType(reflect.NoType,reflect.NoSymbol))))))),
- List(elemType)), elemTrees)
+ @deprecated
+ lazy val tree = {
+ object reifiers extends Reifiers {
+ val symbols: AnnotationInfos.this.type = AnnotationInfos.this
+ }
- case Constant(value) => reflect.Literal(value)
+ reifiers.reify(intTree)
}
- }
-
-
-
-
- /** An argument to an annotation. It includes a parse tree,
- * and it includes a compile-time constant for the tree if possible.
- */
- class AnnotationArgument(val tree: reflect.Tree) {
- def this(cons: Constant) = this(cons2refltree(cons))
-
- val constant: Option[Constant] = refltree2cons(tree)
+ val constant: Option[Constant] = tree2cons(intTree)
def isConstant = !constant.isEmpty
override def toString: String =
constant match {
case Some(cons) => cons.escapedStringValue
- case None => reflect.Print(tree)
+ case None => intTree.toString
}
}
@@ -149,5 +98,20 @@ trait AnnotationInfos {
def isConstant =
((args forall (_.isConstant)) &&
(assocs map (_._2) forall (_.isConstant)))
+
+ /** Check whether the type or any of the arguments are erroneous */
+ def isErroneous = atp.isErroneous || args.exists(_.intTree.isErroneous)
+
+ /** Check whether any of the arguments mention a symbol */
+ def refsSymbol(sym: Symbol) =
+ args.exists(_.intTree.exists(_.symbol == sym))
+
+ /** Change all ident's with Symbol "from" to instead use symbol "to" */
+ def substIdentSyms(from: Symbol, to: Symbol) = {
+ val subs = new TreeSymSubstituter(List(from), List(to))
+ AnnotationInfo(atp,
+ args.map(arg => new AnnotationArgument(subs(arg.intTree))),
+ assocs)
+ }
}
}
diff --git a/src/compiler/scala/tools/nsc/symtab/Definitions.scala b/src/compiler/scala/tools/nsc/symtab/Definitions.scala
index 72f6e3882a..42a3336137 100644
--- a/src/compiler/scala/tools/nsc/symtab/Definitions.scala
+++ b/src/compiler/scala/tools/nsc/symtab/Definitions.scala
@@ -91,6 +91,8 @@ trait Definitions {
lazy val AnnotationClass: Symbol = getClass("scala.Annotation")
lazy val ClassfileAnnotationClass: Symbol = getClass("scala.ClassfileAnnotation")
lazy val StaticAnnotationClass: Symbol = getClass("scala.StaticAnnotation")
+ lazy val TypeConstraintClass: Symbol = getClass("scala.TypeConstraint")
+
var CodeClass: Symbol = _
var CodeModule: Symbol = _
def Code_lift = getMember(CodeModule, nme.lift_)
@@ -116,6 +118,7 @@ trait Definitions {
lazy val ArrayClass: Symbol = getClass("scala.Array")
def Array_apply = getMember(ArrayClass, nme.apply)
lazy val ArrayModule: Symbol = getModule("scala.Array")
+ def ArrayModule_apply = getMember(ArrayModule, nme.apply)
lazy val SerializableClass: Symbol = getClass(sn.Serializable)
lazy val PredefModule: Symbol = getModule("scala.Predef")
def Predef_classOf = getMember(PredefModule, nme.classOf)
diff --git a/src/compiler/scala/tools/nsc/symtab/GenerateIdeMaps.scala b/src/compiler/scala/tools/nsc/symtab/GenerateIdeMaps.scala
index 9f83e655e4..d6855760aa 100644
--- a/src/compiler/scala/tools/nsc/symtab/GenerateIdeMaps.scala
+++ b/src/compiler/scala/tools/nsc/symtab/GenerateIdeMaps.scala
@@ -503,7 +503,7 @@ abstract class GenerateIdeMaps extends SubComponent {
case (p : OffsetPosition, sym) =>
(p.offset0, if (sym.sourceFile == unit.source.file) {
// internal reference
- if (!sym.pos.offset.isDefined) scala.Console.println("ERROR: " + sym + " in " + sym.sourceFile)
+ //if (!sym.pos.offset.isDefined) scala.Console.println("ERROR: " + sym + " in " + sym.sourceFile)
":" + sym.pos.offset.getOrElse(0)
} else {
val url = sym2url(sym)
diff --git a/src/compiler/scala/tools/nsc/symtab/StdNames.scala b/src/compiler/scala/tools/nsc/symtab/StdNames.scala
index 105a6466d4..68e5e35f60 100644
--- a/src/compiler/scala/tools/nsc/symtab/StdNames.scala
+++ b/src/compiler/scala/tools/nsc/symtab/StdNames.scala
@@ -316,6 +316,7 @@ trait StdNames {
val runtime = newTermName("runtime")
val sameElements = newTermName("sameElements")
val scala_ = newTermName("scala")
+ val self = newTermName("self")
val send = newTermName("send")
val synchronized_ = newTermName("synchronized")
val tail = newTermName("tail")
diff --git a/src/compiler/scala/tools/nsc/symtab/SymbolTable.scala b/src/compiler/scala/tools/nsc/symtab/SymbolTable.scala
index d324bf6312..4b9b9292cf 100644
--- a/src/compiler/scala/tools/nsc/symtab/SymbolTable.scala
+++ b/src/compiler/scala/tools/nsc/symtab/SymbolTable.scala
@@ -5,6 +5,7 @@
// $Id$
package scala.tools.nsc.symtab
+import nsc.ast.Trees
import util._
@@ -17,6 +18,7 @@ abstract class SymbolTable extends Names
with InfoTransformers
with StdNames
with AnnotationInfos
+ with Trees
{
def settings: Settings
def rootLoader: LazyType
diff --git a/src/compiler/scala/tools/nsc/symtab/Symbols.scala b/src/compiler/scala/tools/nsc/symtab/Symbols.scala
index cf89332ae9..7ab287383a 100644
--- a/src/compiler/scala/tools/nsc/symtab/Symbols.scala
+++ b/src/compiler/scala/tools/nsc/symtab/Symbols.scala
@@ -9,6 +9,8 @@ package scala.tools.nsc.symtab
import scala.tools.nsc.io.AbstractFile
import scala.tools.nsc.util.{Position, NoPosition, SourceFile, BatchSourceFile}
import Flags._
+import java.util.regex.Pattern
+import nsc.util.RegexCache
trait Symbols {
self: SymbolTable =>
@@ -1055,6 +1057,8 @@ trait Symbols {
var s = simpleName.decode.toString
if (s endsWith nme.LOCAL_SUFFIX)
s = s.substring(0, s.length - nme.LOCAL_SUFFIX.length)
+ if (s endsWith ".type")
+ s = s.substring(0, s.length - ".type".length)
s + idString
}
@@ -1320,7 +1324,7 @@ trait Symbols {
initName: Name, origin: AnyRef)
extends TypeSymbol(initOwner, initPos, initName) {
- /** The skolemizatuon level in place when the skolem was constructed */
+ /** The skolemization level in place when the skolem was constructed */
val level = skolemizationLevel
override def isSkolem = true
@@ -1338,6 +1342,7 @@ trait Symbols {
else super.nameString
}
+
/** A class for class symbols */
class ClassSymbol(initOwner: Symbol, initPos: Position, initName: Name)
extends TypeSymbol(initOwner, initPos, initName) {
diff --git a/src/compiler/scala/tools/nsc/symtab/Types.scala b/src/compiler/scala/tools/nsc/symtab/Types.scala
index 80c9c080e7..8a28452072 100644
--- a/src/compiler/scala/tools/nsc/symtab/Types.scala
+++ b/src/compiler/scala/tools/nsc/symtab/Types.scala
@@ -7,8 +7,10 @@
package scala.tools.nsc.symtab
import scala.collection.mutable.{ListBuffer, HashMap}
+import scala.collection.immutable
import scala.compat.Platform.currentTime
import scala.tools.nsc.util.{HashSet, Position, NoPosition}
+import scala.tools.nsc.ast.TreeGen
import Flags._
/* A standard type pattern match:
@@ -28,7 +30,7 @@ import Flags._
// pre.sym[targs]
case RefinedType(parents, defs) =>
// parent1 with ... with parentn { defs }
- case AnnotatedType(attribs, tp) =>
+ case AnnotatedType(attribs, tp, selfsym) =>
// tp @attribs
// the following are non-value types; you cannot write them down in Scala source.
@@ -96,6 +98,11 @@ trait Types {
*/
var intersectionWitness = new HashMap[List[Type], Type]
+ private object gen extends TreeGen {
+ val global : Types.this.type = Types.this
+ }
+ import gen._
+
// @M toString that is safe during debugging (does not normalize, ...)
def debugString(tp: Type): String = tp match {
case TypeRef(pre, sym, args) => "TypeRef"+(debugString(pre), sym, args map debugString)
@@ -441,18 +448,18 @@ trait Types {
/** Returns all parts of this type which satisfy predicate `p' */
def filter(p: Type => Boolean): List[Type] = {
- new FilterTraverser(p).traverse(this).hits.toList
+ new FilterTypeTraverser(p).traverse(this).hits.toList
}
/** Returns optionally first type (in a preorder traversal) which satisfies predicate `p',
* or None if none exists.
*/
def find(p: Type => Boolean): Option[Type] = {
- new FindTraverser(p).traverse(this).result
+ new FindTypeTraverser(p).traverse(this).result
}
/** Apply `f' to each part of this type */
- def foreach(f: Type => Unit): Unit = new ForEachTraverser(f).traverse(this)
+ def foreach(f: Type => Unit): Unit = new ForEachTypeTraverser(f).traverse(this)
/** Is there part of this type which satisfies predicate `p'? */
def exists(p: Type => Boolean): Boolean = !find(p).isEmpty
@@ -726,12 +733,19 @@ trait Types {
def withAttributes(attribs: List[AnnotationInfo]): Type =
attribs match {
case Nil => this
- case _ => AnnotatedType(attribs, this)
+ case _ => AnnotatedType(attribs, this, NoSymbol)
}
/** Remove any attributes from this type */
def withoutAttributes = this
+ /** Set the self symbol of an annotated type, or do nothing
+ * otherwise. */
+ def withSelfsym(sym: Symbol) = this
+
+ /** The selfsym of an annotated type, or NoSymbol of anything else */
+ def selfsym: Symbol = NoSymbol
+
/** The kind of this type; used for debugging */
def kind: String = "unknown type of class "+getClass()
}
@@ -1547,8 +1561,15 @@ A type's typeSymbol should never be inspected directly.
//assert(paramTypes forall (pt => !pt.typeSymbol.isImplClass))//DEBUG
override def paramSectionCount: Int = resultType.paramSectionCount + 1
- override def resultType(actuals: List[Type]) =
- new InstantiateDeBruijnMap(actuals).apply(resultType)
+ override def resultType(actuals: List[Type]) = {
+ val map = new InstantiateDeBruijnMap(actuals)
+ val rawResTpe = map.apply(resultType)
+
+ if (phase.erasedTypes)
+ rawResTpe
+ else
+ existentialAbstraction(map.existentialsNeeded, rawResTpe)
+ }
override def finalResultType: Type = resultType.finalResultType
@@ -1730,32 +1751,46 @@ A type's typeSymbol should never be inspected directly.
override def kind = "TypeVar"
}
- /** A type carrying some attributes. The attributes have no significance
- * to the core compiler, but can be observed by type-system plugins. The
- * core compiler does take care to propagate attributes and to save them
- * in the symbol tables of object files. */
+ /** A type carrying some annotations. The annotations have
+ * no significance to the core compiler, but can be observed
+ * by type-system plugins. The core compiler does take care
+ * to propagate annotations and to save them in the symbol
+ * tables of object files.
+ *
+ * @param attributes the list of annotations on the type
+ * @param underlying the type without the annotation
+ * @param selfsym a "self" symbol with type <code>underlying</code>;
+ * only available if -Yself-in-annots is
+ * turned on. Can be NoSymbol if it is not used.
+ */
case class AnnotatedType(override val attributes: List[AnnotationInfo],
- override val underlying: Type) extends RewrappingTypeProxy {
+ override val underlying: Type,
+ override val selfsym: Symbol)
+ extends RewrappingTypeProxy {
- override protected def rewrap(tp: Type) = AnnotatedType(attributes, tp)
+ override protected def rewrap(tp: Type) = AnnotatedType(attributes, tp, selfsym)
override def toString: String = {
val attString =
if (attributes.isEmpty)
""
else
- attributes.mkString("@", " @", " ")
+ attributes.mkString(" @", " @", "")
- attString + underlying
+ underlying + attString
}
/** Add a number of attributes to this type */
override def withAttributes(attribs: List[AnnotationInfo]): Type =
- AnnotatedType(attribs:::this.attributes, this)
+ AnnotatedType(attribs:::this.attributes, this, selfsym)
/** Remove any attributes from this type */
override def withoutAttributes = underlying.withoutAttributes
+ /** Set the self symbol */
+ override def withSelfsym(sym: Symbol) =
+ AnnotatedType(attributes, underlying, sym)
+
/** Drop the annotations on the bounds, unless but the low and high bounds are
* exactly tp. */
override def bounds: TypeBounds = {
@@ -2018,7 +2053,7 @@ A type's typeSymbol should never be inspected directly.
* type varianble in `tparams'.
* The abstraction drops all type parameters that are not directly or indirectly
* referenced by type `tpe1'.
- * If there are no such type parameters, simply returns result type `tpe'.
+ * If there are no remaining type parameters, simply returns result type `tpe'.
*/
def existentialAbstraction(tparams: List[Symbol], tpe: Type): Type =
if (tparams.isEmpty) tpe
@@ -2034,6 +2069,7 @@ A type's typeSymbol should never be inspected directly.
case _ =>
}
}
+
val extrapolate = new TypeMap {
variance = 1
def apply(tp: Type): Type = {
@@ -2043,16 +2079,35 @@ A type's typeSymbol should never be inspected directly.
val repl = if (variance == 1) dropSingletonType(tp1.bounds.hi) else tp1.bounds.lo
//println("eliminate "+sym+"/"+repl+"/"+occurCount(sym)+"/"+(tparams exists (repl.contains)))//DEBUG
if (repl.typeSymbol != AllClass && repl.typeSymbol != AllRefClass &&
- occurCount(sym) == 1 && !(tparams exists (repl.contains))) repl
+ occurCount(sym) == 1 && !(tparams exists (repl.contains)))
+ repl
else tp1
case _ =>
tp1
}
}
+ override def mapOver(tree: Tree) =
+ tree match {
+ case tree:Ident
+ if tree.tpe.isStable
+ =>
+ // Do not discard the types of existential ident's.
+ // The symbol of the Ident itself cannot be listed
+ // in the existential's parameters, so the
+ // resulting existential type would be ill-formed.
+ Some(tree)
+
+ case _ =>
+ super.mapOver(tree)
+ }
+
+
+
}
val tpe1 = extrapolate(tpe)
var tparams0 = tparams
var tparams1 = tparams0 filter tpe1.contains
+
while (tparams1 != tparams0) {
tparams0 = tparams1
tparams1 = tparams filter { p =>
@@ -2141,6 +2196,22 @@ A type's typeSymbol should never be inspected directly.
*/
var variance = 0
+ /** Should this map drop annotations that are not
+ * type-constraint annotations?
+ */
+ val dropNonConstraintAnnotations = false
+
+ /** Check whether two lists have elements that are eq-equal */
+ def allEq[T <: AnyRef](l1: List[T], l2: List[T]): Boolean =
+ (l1, l2) match {
+ case (Nil, Nil) => true
+ case (hd1::tl1, hd2::tl2) =>
+ if (!(hd1 eq hd2))
+ return false
+ allEq(tl1, tl2)
+ case _ => false
+ }
+
/** Map this function over given type */
def mapOver(tp: Type): Type = tp match {
case ErrorType => tp
@@ -2232,10 +2303,11 @@ A type's typeSymbol should never be inspected directly.
val tp1 = this(tp)
if (tp1 eq tp) tp
else NotNullType(tp1)
- case AnnotatedType(attribs, atp) =>
+ case AnnotatedType(annots, atp, selfsym) =>
+ val annots1 = mapOverAnnotations(annots)
val atp1 = this(atp)
- if (atp1 eq atp) tp
- else AnnotatedType(attribs, atp1)
+ if ((annots1 eq annots) && (atp1 eq atp)) tp
+ else AnnotatedType(annots1, atp1, selfsym)
case _ =>
tp
// throw new Error("mapOver inapplicable for " + tp);
@@ -2282,6 +2354,90 @@ A type's typeSymbol should never be inspected directly.
}
}
+
+ def mapOverAnnotations(annots: List[AnnotationInfo])
+ : List[AnnotationInfo] = {
+ val newAnnots = annots.flatMap(mapOver(_))
+ if (allEq(newAnnots, annots))
+ annots
+ else
+ newAnnots
+ }
+
+
+ def mapOver(annot: AnnotationInfo): Option[AnnotationInfo] = {
+ val AnnotationInfo(atp, args, assocs) = annot
+
+ if (dropNonConstraintAnnotations &&
+ !(atp.typeSymbol isNonBottomSubClass TypeConstraintClass))
+ return None
+
+ val atp1 = mapOver(atp)
+ val args1 = mapOverAnnotationArgs(args)
+ // there is no need to rewrite assocs, as they should be constants
+
+ if ((args eq args1) && (atp eq atp1))
+ Some(annot)
+ else if (args1.length == args.length)
+ Some(AnnotationInfo(atp1, args1, assocs))
+ else
+ None
+ }
+
+ /** Map over a set of annotation arguments. If any
+ * of the arguments cannot be mapped, then return Nil. */
+ def mapOverAnnotationArgs(args: List[AnnotationArgument])
+ : List[AnnotationArgument] = {
+ val args1 = args.flatMap(mapOver(_))
+ if (args1.length != args.length)
+ Nil
+ else if (allEq(args, args1))
+ args
+ else
+ args1
+ }
+
+
+ def mapOver(arg: AnnotationArgument): Option[AnnotationArgument] = {
+ if (arg.isConstant)
+ Some(arg)
+ else {
+ mapOver(arg.intTree) match {
+ case None => None
+
+ case Some(tree1)
+ if (tree1 eq arg.intTree) => Some(arg)
+
+ case Some(tree1) => Some(new AnnotationArgument(tree1))
+ }
+ }
+ }
+
+
+ def mapOver(tree: Tree): Option[Tree] =
+ Some(mapOver(tree, ()=>return None))
+
+ /** Map a tree that is part of an annotation argument.
+ * If the tree cannot be mapped, then invoke giveup().
+ * The default is to transform the tree with
+ * TypeMapTransformer.
+ */
+ def mapOver(tree: Tree, giveup: ()=>Nothing): Tree =
+ (new TypeMapTransformer).transform(tree)
+
+ /** This transformer leaves the tree alone except to remap
+ * its types. */
+ class TypeMapTransformer extends Transformer {
+ override def transform(tree: Tree) = {
+ val tree1 = super.transform(tree)
+ val tpe1 = TypeMap.this(tree1.tpe)
+ if ((tree eq tree1) && (tree.tpe eq tpe1))
+ tree
+ else
+ tree1.shallowDuplicate.setType(tpe1)
+ }
+ }
+
protected def copyMethodType(tp: Type, formals: List[Type], restpe: Type): Type = tp match {
case _: ImplicitMethodType => ImplicitMethodType(formals, restpe)
case _: JavaMethodType => JavaMethodType(formals, restpe)
@@ -2289,6 +2445,11 @@ A type's typeSymbol should never be inspected directly.
}
}
+ /** A type map that always returns the input type unchanged */
+ object IdentityTypeMap extends TypeMap {
+ def apply(tp: Type) = tp
+ }
+
abstract class TypeTraverser extends TypeMap {
def traverse(tp: Type): TypeTraverser //todo: return Unit instead?
def apply(tp: Type): Type = { traverse(tp); tp }
@@ -2304,7 +2465,35 @@ A type's typeSymbol should never be inspected directly.
/** A map to compute the asSeenFrom method */
class AsSeenFromMap(pre: Type, clazz: Symbol) extends TypeMap {
+ override val dropNonConstraintAnnotations = true
+
var capturedParams: List[Symbol] = List()
+
+ override def mapOver(tree: Tree, giveup: ()=>Nothing): Tree = {
+ object annotationArgRewriter extends TypeMapTransformer {
+ /** Rewrite "this" trees as needed for asSeenFrom */
+ def rewriteThis(tree: Tree): Tree =
+ tree match {
+ case This(_)
+ if (tree.symbol isNonBottomSubClass clazz) &&
+ (pre.widen.typeSymbol isNonBottomSubClass tree.symbol) =>
+ if (pre.isStable)
+ mkAttributedQualifier(pre)
+ else
+ giveup()
+
+ case tree => tree
+ }
+
+ override def transform(tree: Tree): Tree = {
+ val tree1 = rewriteThis(super.transform(tree))
+ tree1
+ }
+ }
+
+ annotationArgRewriter.transform(tree)
+ }
+
var capturedPre = emptySymMap
def stabilize(pre: Type, clazz: Symbol): Type = {
@@ -2407,7 +2596,6 @@ A type's typeSymbol should never be inspected directly.
/** A base class to compute all substitutions */
abstract class SubstMap[T](from: List[Symbol], to: List[T]) extends TypeMap {
-
/** Are `sym' and `sym1' the same.
* Can be tuned by subclasses.
*/
@@ -2416,14 +2604,14 @@ A type's typeSymbol should never be inspected directly.
/** Map target to type, can be tuned by subclasses */
protected def toType(fromtp: Type, t: T): Type
- def apply(tp0: Type): Type = if (from.isEmpty) tp0 else {
- val tp = mapOver(tp0)
-
- def subst(sym: Symbol, from: List[Symbol], to: List[T]): Type =
+ def subst(tp: Type, sym: Symbol, from: List[Symbol], to: List[T]): Type =
if (from.isEmpty) tp
else if (to.isEmpty && inIDE) throw new TypeError(NoPosition, "type parameter list problem");
else if (matches(from.head, sym)) toType(tp, to.head)
- else subst(sym, from.tail, to.tail)
+ else subst(tp, sym, from.tail, to.tail)
+
+ def apply(tp0: Type): Type = if (from.isEmpty) tp0 else {
+ val tp = mapOver(tp0)
tp match {
// @M
@@ -2438,7 +2626,7 @@ A type's typeSymbol should never be inspected directly.
// (must not recurse --> loops)
// 3) replacing m by List in m[Int] should yield List[Int], not just List
case TypeRef(NoPrefix, sym, args) =>
- subst(sym, from, to) match {
+ subst(tp, sym, from, to) match {
case r @ TypeRef(pre1, sym1, args1) =>
if (args.isEmpty) r
else rawTypeRef(pre1, sym1, args)
@@ -2446,7 +2634,7 @@ A type's typeSymbol should never be inspected directly.
r
}
case SingleType(NoPrefix, sym) =>
- subst(sym, from, to)
+ subst(tp, sym, from, to)
case PolyType(tparams, restp) =>
assert(!(tparams exists (from contains)))
tp
@@ -2482,12 +2670,64 @@ A type's typeSymbol should never be inspected directly.
super.apply(tp)
}
}
+
+
+ override def mapOver(tree: Tree, giveup: ()=>Nothing): Tree = {
+ object trans extends TypeMapTransformer {
+
+ def termMapsTo(sym: Symbol) =
+ if (from contains sym)
+ Some(to(from.indexOf(sym)))
+ else
+ None
+
+ override def transform(tree: Tree) =
+ tree match {
+ case tree@Ident(_) =>
+ termMapsTo(tree.symbol) match {
+ case Some(tosym) =>
+ if (tosym.info.bounds.hi.typeSymbol isSubClass SingletonClass) {
+ Ident(tosym.existentialToString)
+ .setSymbol(tosym)
+ .setPos(tosym.pos)
+ .setType(dropSingletonType(tosym.info.bounds.hi))
+ } else {
+ giveup()
+ }
+ case None => super.transform(tree)
+ }
+ case tree => super.transform(tree)
+ }
+ }
+ trans.transform(tree)
+ }
}
/** A map to implement the `subst' method. */
class SubstTypeMap(from: List[Symbol], to: List[Type])
extends SubstMap(from, to) {
protected def toType(fromtp: Type, tp: Type) = tp
+
+
+ override def mapOver(tree: Tree, giveup: ()=>Nothing): Tree = {
+ object trans extends TypeMapTransformer {
+ override def transform(tree: Tree) =
+ tree match {
+ case tree@Ident(_) if from contains tree.symbol =>
+ val totpe = to(from.indexOf(tree.symbol))
+ if (!totpe.isStable) {
+ giveup()
+ } else {
+ tree.duplicate.setType(totpe)
+ }
+
+ case _ => super.transform(tree)
+ }
+ }
+ trans.transform(tree)
+ }
+
+
}
/** A map to implement the `substThis' method. */
@@ -2514,7 +2754,44 @@ A type's typeSymbol should never be inspected directly.
}
}
+ /** Most of the implementation for MethodType.resultType. The
+ * caller also needs to existentially quantify over the
+ * variables in existentialsNeeded.
+ */
class InstantiateDeBruijnMap(actuals: List[Type]) extends TypeMap {
+ override val dropNonConstraintAnnotations = true
+
+
+ private var existSyms = immutable.Map.empty[Int, Symbol]
+ def existentialsNeeded: List[Symbol] = existSyms.values.toList
+
+ private def boundFor(actualIdx: Int) =
+ mkTypeBounds(
+ AllClass.tpe,
+ intersectionType(List(actuals(actualIdx), SingletonClass.tpe)))
+
+ /* Return the type symbol for referencing a parameter index
+ * inside the existential quantifier. */
+ def existSymFor(actualIdx: Int, oldSym: Symbol) =
+ if (existSyms.isDefinedAt(actualIdx))
+ existSyms(actualIdx)
+ else {
+ val symowner = oldSym.owner // what should be used??
+ val bound = boundFor(actualIdx)
+
+ val sym =
+ symowner.newAbstractType(
+ oldSym.pos, oldSym.name+".type")
+
+ sym.setInfo(bound)
+ sym.setFlag(oldSym.flags)
+ sym.setFlag(EXISTENTIAL)
+
+
+ existSyms = existSyms + actualIdx -> sym
+ sym
+ }
+
def apply(tp: Type): Type = tp match {
case DeBruijnIndex(level, pid) =>
if (level == 1)
@@ -2523,6 +2800,35 @@ A type's typeSymbol should never be inspected directly.
case _ =>
mapOver(tp)
}
+
+ override def mapOver(arg: Tree, giveup: ()=>Nothing): Tree = {
+ object treeTrans extends TypeMapTransformer {
+ override def transform(tree: Tree): Tree =
+ tree match {
+ case tree@Ident(name) =>
+ tree.tpe.withoutAttributes match {
+ case DeBruijnIndex(level, pid) =>
+ if (level == 1) {
+ if (actuals(pid).isStable)
+ mkAttributedQualifier(actuals(pid))
+ else {
+ val sym = existSymFor(pid, tree.symbol)
+ (Ident(tree.symbol.name)
+ copyAttrs tree
+ setType typeRef(NoPrefix, sym, Nil))
+ }
+ } else
+ tree.duplicate.setType(
+ DeBruijnIndex(level-1, pid))
+ case _ => super.transform(tree)
+
+ }
+ case _ => super.transform(tree)
+ }
+ }
+
+ treeTrans.transform(arg)
+ }
}
object ApproximateDeBruijnMap extends TypeMap {
@@ -2550,6 +2856,7 @@ A type's typeSymbol should never be inspected directly.
/** A map to implement the `contains' method */
class ContainsTraverser(sym: Symbol) extends TypeTraverser {
var result = false
+
def traverse(tp: Type): ContainsTraverser = {
if (!result) {
tp.normalize match {
@@ -2560,8 +2867,18 @@ A type's typeSymbol should never be inspected directly.
}
this
}
+
+ override def mapOver(arg: Tree) = {
+ for (t <- arg) {
+ traverse(t.tpe)
+ if (t.symbol == sym)
+ result = true
+ }
+ Some(arg)
+ }
}
+
/** A map to implement the `contains' method */
class ContainsTypeTraverser(t: Type) extends TypeTraverser {
var result = false
@@ -2572,19 +2889,25 @@ A type's typeSymbol should never be inspected directly.
}
this
}
+ override def mapOver(arg: Tree) = {
+ for (t <- arg) {
+ traverse(t.tpe)
+ }
+ Some(arg)
+ }
}
/** A map to implement the `filter' method */
- class FilterTraverser(p: Type => Boolean) extends TypeTraverser {
+ class FilterTypeTraverser(p: Type => Boolean) extends TypeTraverser {
val hits = new ListBuffer[Type]
- def traverse(tp: Type): FilterTraverser = {
+ def traverse(tp: Type): FilterTypeTraverser = {
if (p(tp)) hits += tp
mapOver(tp)
this
}
}
- class ForEachTraverser(f: Type => Unit) extends TypeTraverser {
+ class ForEachTypeTraverser(f: Type => Unit) extends TypeTraverser {
def traverse(tp: Type): TypeTraverser = {
f(tp)
mapOver(tp)
@@ -2593,9 +2916,9 @@ A type's typeSymbol should never be inspected directly.
}
/** A map to implement the `filter' method */
- class FindTraverser(p: Type => Boolean) extends TypeTraverser {
+ class FindTypeTraverser(p: Type => Boolean) extends TypeTraverser {
var result: Option[Type] = None
- def traverse(tp: Type): FindTraverser = {
+ def traverse(tp: Type): FindTypeTraverser = {
if (result.isEmpty) {
if (p(tp)) result = Some(tp)
mapOver(tp)
@@ -2729,7 +3052,7 @@ A type's typeSymbol should never be inspected directly.
case TypeBounds(_, _) => mapOver(tp)
case MethodType(_, _) => mapOver(tp)
case TypeVar(_, _) => mapOver(tp)
- case AnnotatedType(_,_) => mapOver(tp)
+ case AnnotatedType(_,_,_) => mapOver(tp)
case NotNullType(_) => mapOver(tp)
case ExistentialType(_, _) => mapOver(tp)
case _ => tp
@@ -3009,9 +3332,9 @@ A type's typeSymbol should never be inspected directly.
case (_, tv2 @ TypeVar(_, constr2)) =>
if (constr2.inst != NoType) tp1 =:= constr2.inst
else isRelatable(tv2, tp1) && (constr2 instantiate wildcardToTypeVarMap(tp1))
- case (AnnotatedType(_,atp), _) =>
+ case (AnnotatedType(_,atp,_), _) =>
isSameType(atp, tp2)
- case (_, AnnotatedType(_,atp)) =>
+ case (_, AnnotatedType(_,atp,_)) =>
isSameType(tp1, atp)
case (_: SingletonType, _: SingletonType) =>
var origin1 = tp1
@@ -3164,9 +3487,9 @@ A type's typeSymbol should never be inspected directly.
case (tv1 @ TypeVar(_, constr1), _) =>
if (constr1.inst != NoType) constr1.inst <:< tp2
else isRelatable(tv1, tp2) && { constr1.hibounds = tp2 :: constr1.hibounds; true }
- case (AnnotatedType(_,atp1), _) =>
+ case (AnnotatedType(_,atp1,_), _) =>
atp1 <:< tp2
- case (_, AnnotatedType(_,atp2)) =>
+ case (_, AnnotatedType(_,atp2,_)) =>
tp1 <:< atp2
case (_, _) if (tp1.isHigherKinded || tp2.isHigherKinded) =>
(tp1.typeSymbol == AllClass
diff --git a/src/compiler/scala/tools/nsc/symtab/classfile/PickleFormat.scala b/src/compiler/scala/tools/nsc/symtab/classfile/PickleFormat.scala
index ce90bd9627..43750479b2 100644
--- a/src/compiler/scala/tools/nsc/symtab/classfile/PickleFormat.scala
+++ b/src/compiler/scala/tools/nsc/symtab/classfile/PickleFormat.scala
@@ -8,6 +8,9 @@ package scala.tools.nsc.symtab.classfile
/** This object provides constants for pickling attributes.
*
+ * If you extend the format, be sure to increase the
+ * version minor number.
+ *
* @author Martin Odersky
* @version 1.0
*/
@@ -53,46 +56,56 @@ object PickleFormat {
* | 40 ATTRIBUTE len_Nat sym_Ref info_Ref {constant_Ref} {nameRef constantRef}
* | 41 CHILDREN len_Nat sym_Ref {sym_Ref}
* | 42 ANNOTATEDtpe len_Nat tpe_Ref {attribtree_Ref}
- * | 43 ATTRIBTREE refltree_Ref len_Nat attarg_Ref {constant_Ref attarg_Ref}
- * | 44 REFLTREE len_Nat 1 IDENTtree sym_Ref
- * | 44 REFLTREE len_Nat 2 SELECTtree qual_Ref sym_Ref
- * | 44 REFLTREE len_Nat 3 LITERALtree constant_Ref
- * | 44 REFLTREE len_Nat 4 APPLYtree fun_Ref {arg_Ref}
- * | 44 REFLTREE len_Nat 5 TYPEAPPLYtree fun_Ref {arg_Ref}
- * | 44 REFLTREE len_Nat 6 FUNCTIONtree body_Ref {param_Ref}
- * | 44 REFLTREE len_Nat 7 THIStree sym_Ref
- * | 44 REFLTREE len_Nat 8 BLOCKtree exp_Ref {stat_Ref}
- * | 44 REFLTREE len_Nat 9 NEWtree clz_Ref
- * | 44 REFLTREE len_Nat 10 IFtree cond_Ref true_Ref false_Ref
- * | 44 REFLTREE len_Nat 11 ASSIGNtree lhs_Ref rhs_Ref
- * | 44 REFLTREE len_Nat 12 TARGETtree sym_Ref body_Ref
- * | 44 REFLTREE len_Nat 13 GOTOtree target_Ref
- * | 44 REFLTREE len_Nat 14 VALDEFtree sym_Ref rhs_Ref
- * | 44 REFLTREE len_Nat 15 CLASSDEFtree sym_Ref tpe_Ref impl_Ref
- * | 44 REFLTREE len_Nat 16 DEFDEFtree sym_Ref ret_Ref rhs_Ref {pl_Nat {param_Ref}}
- * | 44 REFLTREE len_Nat 17 SUPERtree psym_Ref
- * | 44 REFLTREE len_Nat 18 TEMPLATEtree parents_Nat {parent_Ref} body_Ref
- * | 45 REFLTYPE len_Nat 1 NOPREFIXrtpe
- * | 45 REFLTYPE len_Nat 2 NOrtpe
- * | 45 REFLTYPE len_Nat 3 NAMEDrtpe name_Ref
- * | 45 REFLTYPE len_Nat 4 PREFIXEDrtpe pre_Ref sym_Ref
- * | 45 REFLTYPE len_Nat 5 SINGLErtpe pre_Ref sym_Ref
- * | 45 REFLTYPE len_Nat 6 THISrtpe class_Ref
- * | 45 REFLTYPE len_Nat 7 APPLIEDrtpe tpe_Ref {arg_Ref}
- * | 45 REFLTYPE len_Nat 8 TYPEBOUNDSrtpe lo_Ref hi_Ref
- * | 45 REFLTYPE len_Nat 9 METHODrtpe restpe_Ref {paramtpe_Ref}
- * | 45 REFLTYPE len_Nat 10 POLYrtpe restpe_Ref boundslen_Nat {lo_Ref hi_Ref} {typeParam_Ref}
- * | 45 REFLTYPE len_Nat 11 IMPLICITMETHODrtpe restpe_Ref {paramtpe_Ref}
- * | 46 REFLSYM len_Nat 1 CLASSrsym name_Ref
- * | 46 REFLSYM len_Nat 2 METHODrsym fullname_Ref
- * | 46 REFLSYM len_Nat 3 FIELDrsym tpe_Ref fullname_Ref tpe_Ref
- * | 46 REFLSYM len_Nat 4 TYPEFIELDrsym fullname_Ref tpe_Ref
- * | 46 REFLSYM len_Nat 5 LOCALVALUErsym owner_Ref name_Ref tpe_Ref
- * | 46 REFLSYM len_Nat 6 LOCALMETHODrsym owner_Ref name_Ref tpe_Ref
- * | 46 REFLSYM len_Nat 7 NOSYMBOLrsym
- * | 46 REFLSYM len_Nat 8 ROOTSYMBOLrsym
- * | 46 REFLSYM len_Nat 9 LABELSYMBOLrsym name_Ref
+ * | 51 ANNOTATEDWSELFtpe len_Nat tpe_Ref sym_Ref {attribtree_Ref}
+ * | 43 ANNOTINFO attarg_Ref len_Nat attarg_Ref {constant_Ref attarg_Ref}
* | 47 DEBRUIJNINDEXtpe len_Nat level_Nat index_Nat
+ * | 48 EXISTENTIALtpe len_Nat type_Ref {symbol_Ref}
+ * | 49 TREE len_Nat 1 EMPTYtree
+ * | 49 TREE len_Nat 2 PACKAGEtree type_Ref sym_Ref mods_Ref name_Ref {tree_Ref}
+ * | 49 TREE len_Nat 3 CLASStree type_Ref sym_Ref mods_Ref name_Ref tree_Ref {tree_Ref}
+ * | 49 TREE len_Nat 4 MODULEtree type_Ref sym_Ref mods_Ref name_Ref tree_Ref
+ * | 49 TREE len_Nat 5 VALDEFtree type_Ref sym_Ref mods_Ref name_Ref tree_Ref tree_Ref
+ * | 49 TREE len_Nat 6 DEFDEFtree type_Ref sym_Ref mods_Ref name_Ref numtparams_Nat {tree_Ref} numparamss_Nat {numparams_Nat {tree_Ref}} tree_Ref tree_Ref
+ * | 49 TREE len_Nat 7 TYPEDEFtree type_Ref sym_Ref mods_Ref name_Ref tree_Ref {tree_Ref}
+ * | 49 TREE len_Nat 8 LABELtree type_Ref sym_Ref tree_Ref {tree_Ref}
+ * | 49 TREE len_Nat 9 IMPORTtree type_Ref sym_Ref tree_Ref {name_Ref name_Ref}
+ * | 49 TREE len_Nat 10 ANNOTATIONtree type_Ref sym_Ref tree_Ref {tree_Ref}
+ * | 49 TREE len_Nat 11 DOCDEFtree type_Ref sym_Ref string_Ref tree_Ref
+ * | 49 TREE len_Nat 12 TEMPLATEtree type_Ref sym_Ref numparents_Nat {tree_Ref} tree_Ref {tree_Ref}
+ * | 49 TREE len_Nat 13 BLOCKtree type_Ref tree_Ref {tree_Ref}
+ * | 49 TREE len_Nat 14 CASEtree type_Ref tree_Ref tree_Ref tree_Ref
+ * | 49 TREE len_Nat 15 SEQUENCEtree type_Ref {tree_Ref}
+ * | 49 TREE len_Nat 16 ALTERNATIVEtree type_Ref {tree_Ref}
+ * | 49 TREE len_Nat 17 STARtree type_Ref {tree_Ref}
+ * | 49 TREE len_Nat 18 BINDtree type_Ref sym_Ref name_Ref tree_Ref
+ * | 49 TREE len_Nat 19 UNAPPLYtree type_Ref tree_Ref {tree_Ref}
+ * | 49 TREE len_Nat 20 ARRAYVALUEtree type_Ref tree_Ref {tree_Ref}
+ * | 49 TREE len_Nat 21 FUNCTIONtree type_Ref sym_Ref tree_Ref {tree_Ref}
+ * | 49 TREE len_Nat 22 ASSIGNtree type_Ref tree_Ref tree_Ref
+ * | 49 TREE len_Nat 23 IFtree type_Ref tree_Ref tree_Ref tree_Ref
+ * | 49 TREE len_Nat 24 MATCHtree type_Ref tree_Ref {tree_Ref}
+ * | 49 TREE len_Nat 25 RETURNtree type_Ref sym_Ref tree_Ref
+ * | 49 TREE len_Nat 26 TREtree type_Ref tree_Ref tree_Ref {tree_Ref}
+ * | 49 TREE len_Nat 27 THROWtree type_Ref tree_Ref
+ * | 49 TREE len_Nat 28 NEWtree type_Ref tree_Ref
+ * | 49 TREE len_Nat 29 TYPEDtree type_Ref tree_Ref tree_Ref
+ * | 49 TREE len_Nat 30 TYPEAPPLYtree type_Ref tree_Ref {tree_Ref}
+ * | 49 TREE len_Nat 31 APPLYtree type_Ref tree_Ref {tree_Ref}
+ * | 49 TREE len_Nat 32 APPLYDYNAMICtree type_Ref sym_Ref tree_Ref {tree_Ref}
+ * | 49 TREE len_Nat 33 SUPERtree type_Ref sym_Ref tree_Ref name_Ref
+ * | 49 TREE len_Nat 34 THIStree type_Ref sym_Ref name_Ref
+ * | 49 TREE len_Nat 35 SELECTtree type_Ref sym_Ref tree_Ref name_Ref
+ * | 49 TREE len_Nat 36 IDENTtree type_Ref sym_Ref name_Ref
+ * | 49 TREE len_Nat 37 LITERALtree type_Ref constant_Ref
+ * | 49 TREE len_Nat 38 TYPEtree type_Ref
+ * | 49 TREE len_Nat 39 ANNOTATEDtree type_Ref tree_Ref tree_Ref
+ * | 49 TREE len_Nat 40 SINGLETONTYPEtree type_Ref tree_Ref
+ * | 49 TREE len_Nat 41 SELECTFROMTYPEtree type_Ref tree_Ref name_Ref
+ * | 49 TREE len_Nat 42 COMPOUNDTYPEtree type_Ref tree_Ref
+ * | 49 TREE len_Nat 43 APPLIEDTYPEtree type_Ref tree_Ref {tree_Ref}
+ * | 49 TREE len_Nat 44 TYPEBOUNDStree type_Ref tree_Ref tree_Ref
+ * | 49 TREE len_Nat 45 EXISTENTIALTYPEtree type_Ref tree_Ref {tree_Ref}
+ * | 50 MODIFIERS len_Nat flags_Long privateWithin_Ref {Annotation_Ref}
* | 68 PosTYPEsym len_Nat pos_Nat SymbolInfo
* | 69 PosALIASsym len_Nat pos_Nat SymbolInfo
* | 70 PosCLASSsym len_Nat pos_Nat SymbolInfo [thistype_Ref]
@@ -149,55 +162,69 @@ object PickleFormat {
final val CHILDREN = 41
final val ANNOTATEDtpe = 42
- final val ATTRIBTREE = 43 // an annotation with trees
- final val REFLTREE = 44 // prefix saying that a prefix tree is coming
- final val IDENTtree = 1
- final val SELECTtree = 2
- final val LITERALtree = 3
- final val APPLYtree = 4
- final val TYPEAPPLYtree = 5
- final val FUNCTIONtree = 6
- final val THIStree = 7
- final val BLOCKtree = 8
- final val NEWtree = 9
- final val IFtree = 10
- final val ASSIGNtree = 11
- final val TARGETtree = 12
- final val GOTOtree = 13
- final val VALDEFtree = 14
- final val CLASSDEFtree = 15
- final val DEFDEFtree = 16
- final val SUPERtree = 17
- final val TEMPLATEtree = 18
-
+ final val ANNOTINFO = 43 // an annotation with trees
+ final val REFLTREE = 44 // prefix saying that a reflect tree is coming
+ // support dropped in September of 2007
final val REFLTYPE = 45 // prefix code that means a reflect type is coming
- final val NOPREFIXrtpe = 1
- final val NOrtpe = 2
- final val NAMEDrtpe = 3
- final val PREFIXEDrtpe = 4
- final val SINGLErtpe = 5
- final val THISrtpe = 6
- final val APPLIEDrtpe = 7
- final val TYPEBOUNDSrtpe = 8
- final val METHODrtpe = 9
- final val POLYrtpe = 10
- final val IMPLICITMETHODrtpe = 11
+ // support dropped in September of 2007
- final val REFLSYM = 46
- final val CLASSrsym = 1
- final val METHODrsym = 2
- final val FIELDrsym = 3
- final val TYPEFIELDrsym = 4
- final val LOCALVALUErsym = 5
- final val LOCALMETHODrsym = 6
- final val NOSYMBOLrsym = 7
- final val ROOTSYMBOLrsym = 8
- final val LABELSYMBOLrsym = 9
+ final val REFLSYM = 46 // prefix code that means a reflect symbol is coming
+ // support dropped in September of 2007
final val DEBRUIJNINDEXtpe = 47
final val EXISTENTIALtpe = 48
+ final val TREE = 49 // prefix code that means a tree is coming
+ final val EMPTYtree = 1
+ final val PACKAGEtree = 2
+ final val CLASStree = 3
+ final val MODULEtree = 4
+ final val VALDEFtree = 5
+ final val DEFDEFtree = 6
+ final val TYPEDEFtree = 7
+ final val LABELtree = 8
+ final val IMPORTtree = 9
+ final val ANNOTATIONtree = 10
+ final val DOCDEFtree = 11
+ final val TEMPLATEtree = 12
+ final val BLOCKtree = 13
+ final val CASEtree = 14
+ final val SEQUENCEtree = 15
+ final val ALTERNATIVEtree = 16
+ final val STARtree = 17
+ final val BINDtree = 18
+ final val UNAPPLYtree = 19
+ final val ARRAYVALUEtree = 20
+ final val FUNCTIONtree = 21
+ final val ASSIGNtree = 22
+ final val IFtree = 23
+ final val MATCHtree = 24
+ final val RETURNtree = 25
+ final val TREtree = 26
+ final val THROWtree = 27
+ final val NEWtree = 28
+ final val TYPEDtree = 29
+ final val TYPEAPPLYtree = 30
+ final val APPLYtree = 31
+ final val APPLYDYNAMICtree = 32
+ final val SUPERtree = 33
+ final val THIStree = 34
+ final val SELECTtree = 35
+ final val IDENTtree = 36
+ final val LITERALtree = 37
+ final val TYPEtree = 38
+ final val ANNOTATEDtree = 39
+ final val SINGLETONTYPEtree = 40
+ final val SELECTFROMTYPEtree = 41
+ final val COMPOUNDTYPEtree = 42
+ final val APPLIEDTYPEtree = 43
+ final val TYPEBOUNDStree = 44
+ final val EXISTENTIALTYPEtree = 45
+
+ final val MODIFIERS = 50
+ final val ANNOTATEDWSELFtpe = 51 // annotated type with selfsym
+
final val firstSymTag = NONEsym
final val lastSymTag = VALsym
final val lastExtSymTag = EXTMODCLASSref
diff --git a/src/compiler/scala/tools/nsc/symtab/classfile/Pickler.scala b/src/compiler/scala/tools/nsc/symtab/classfile/Pickler.scala
index 4c61981c9d..6bb7ec7369 100644
--- a/src/compiler/scala/tools/nsc/symtab/classfile/Pickler.scala
+++ b/src/compiler/scala/tools/nsc/symtab/classfile/Pickler.scala
@@ -155,7 +155,7 @@ abstract class Pickler extends SubComponent {
case SingleType(pre, sym) =>
putType(pre); putSymbol(sym)
case ConstantType(value) =>
- putConstant(value)
+ putConstant(value)
case TypeRef(pre, sym, args) =>
putType(pre); putSymbol(sym); putTypes(args)
case TypeBounds(lo, hi) =>
@@ -173,109 +173,226 @@ abstract class Pickler extends SubComponent {
putType(restpe); putSymbols(tparams)
case ExistentialType(tparams, restpe) =>
putType(restpe); putSymbols(tparams)
- case AnnotatedType(attribs, tp) =>
+ case AnnotatedType(attribs, tp, selfsym) =>
putType(tp); putAnnotations(attribs)
+ if (settings.selfInAnnots.value) putSymbol(selfsym)
case _ =>
throw new FatalError("bad type: " + tp + "(" + tp.getClass + ")")
}
}
private def putTypes(tps: List[Type]) { tps foreach putType }
- private def putTree(tree: reflect.Tree): Unit = if (putEntry(tree)) {
+ private def putTree(tree: Tree): Unit = if (putEntry(tree)) {
+ if (tree != EmptyTree)
+ putType(tree.tpe)
+ if (tree.hasSymbol)
+ putSymbol(tree.symbol)
+
tree match {
- case reflect.Ident(sym) => putSymbol(sym)
- case reflect.Select(qual, sym) => putTree(qual); putSymbol(sym)
- case reflect.Literal(value) => putConstant(Constant(value))
- case reflect.Apply(fun, args) => putTree(fun); putRefTrees(args)
- case reflect.TypeApply(fun, args) => putTree(fun); putRefTypes(args)
- case reflect.Function(params, body) =>
- putRefSymbols(params); putTree(body)
- case reflect.This(sym) => putSymbol(sym)
- case reflect.Block(stats, expr) => putRefTrees(stats); putTree(expr)
- case reflect.New(clz) => putTree(clz)
- case reflect.If(condition, trueCase, falseCase) =>
- putTree(condition); putTree(trueCase); putTree(falseCase)
- case reflect.Assign(destination, source) =>
- putTree(destination); putTree(source)
- case reflect.Target(sym, body) => putSymbol(sym); putTree(body)
- case reflect.Goto(target) => putSymbol(target)
- case reflect.ValDef(sym, rhs) => putSymbol(sym); putTree(rhs)
- case reflect.ClassDef(sym, tpe, impl) =>
- putSymbol(sym); putType(tpe); putTree(impl)
- case reflect.DefDef(sym, vparamss, ret, rhs) =>
- putSymbol(sym); putRefTreess(vparamss); putType(ret); putTree(rhs)
- case reflect.Super(psym) => putSymbol(psym)
- case reflect.Template(parents, body) =>
- putRefTypes(parents); putRefTrees(body)
- case _ =>
- throw new FatalError("bad tree: " + tree + "(" + tree.getClass + ")")
- }
- }
- private def putRefTrees(trees: List[reflect.Tree]) = trees foreach putTree
- private def putRefTreess(trees: List[List[reflect.Tree]]) =
- trees foreach putRefTrees
-
- private def putType(tpe: reflect.Type): Unit = if (putEntry(tpe)) {
- tpe match {
- case reflect.NoPrefix => ()
- case reflect.NoType => ()
- case reflect.NamedType(fullname) => putConstant(Constant(fullname))
- case reflect.PrefixedType(pre, sym) => putType(pre); putSymbol(sym)
- case reflect.SingleType(pre, sym) => putType(pre); putSymbol(sym)
- case reflect.ThisType(clazz) => putSymbol(clazz)
- case reflect.AppliedType(tpe, args) => putType(tpe); putRefTypes(args)
- case reflect.TypeBounds(lo, hi) => putType(lo); putType(hi)
- case reflect.MethodType(formals, restpe) => //can be implicit
- putRefTypes(formals); putType(restpe)
- case reflect.PolyType(typeParams, typeBounds, resultType) =>
- putRefSymbols(typeParams)
- for ((t1,t2) <- typeBounds) {
- putType(t1)
- putType(t2)
- }
- putType(resultType)
- case _ =>
- throw new FatalError("bad type: " + tpe + "(" + tpe.getClass + ")")
+ case EmptyTree =>
+
+ case tree@PackageDef(name, stats) =>
+ putEntry(name)
+ 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) =>
+ putTree(rhs)
+ putTrees(params)
+
+
+ case Import(expr, selectors) =>
+ putTree(expr)
+ for ((from,to) <- selectors) {
+ putEntry(from)
+ putEntry(to)
+ }
+
+ case Annotation(constr, elements) =>
+ putTree(constr)
+ putTrees(elements)
+
+ case DocDef(comment, definition) =>
+ putConstant(Constant(comment))
+ putTree(definition)
+
+ case Template(parents, self, body) =>
+ writeNat(parents.length)
+ 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 Sequence(trees) =>
+ putTrees(trees)
+
+ 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) =>
+ writeEntry(qual)
+ putTrees(args)
+
+ case Super(qual, mix) =>
+ putEntry(qual:Name)
+ 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 def putRefTypes(tpes: List[reflect.Type]) {
- tpes foreach putType
- }
- private def putSymbol(sym: reflect.Symbol): Unit = if(putEntry(sym)) {
- sym match {
- case reflect.Class(fullname) =>
- putConstant(Constant(fullname))
- case reflect.Method(fullname, tpe) =>
- putConstant(Constant(fullname))
- putType(tpe)
- case reflect.Field(fullname, tpe) =>
- putConstant(Constant(fullname))
- putType(tpe)
- case reflect.TypeField(fullname, tpe) =>
- putConstant(Constant(fullname))
- putType(tpe)
- case reflect.LocalValue(owner, name, tpe) =>
- putSymbol(owner)
- putConstant(Constant(name))
- putType(tpe)
- case reflect.LocalMethod(owner, name, tpe) =>
- putSymbol(owner)
- putConstant(Constant(name))
- putType(tpe)
- case reflect.NoSymbol => ()
- case reflect.RootSymbol => ()
- case reflect.LabelSymbol(name) =>
- putConstant(Constant(name))
- }
+ private def putTrees(trees: List[Tree]) =
+ trees.foreach(putTree _)
+
+ private def putTreess(treess: List[List[Tree]]) =
+ treess.foreach(putTrees _)
+
+ private def putMods(mods: Modifiers) = if (putEntry(mods)) {
+ val Modifiers(flags, privateWithin, annotations) = mods
+ putEntry(privateWithin)
+ putTrees(annotations)
}
- private def putRefSymbols(syms: List[reflect.Symbol]) =
- syms foreach putSymbol
- /** Store constant in map <code>index</code>.
- *
- * @param c ...
+ /** Store a constant in map <code>index</code> along with
+ * anything it references.
*/
private def putConstant(c: Constant) =
if (putEntry(c)) {
@@ -309,7 +426,7 @@ abstract class Pickler extends SubComponent {
if (putEntry(arg)) {
arg.constant match {
case Some(c) => putConstant(c)
- case _ => putTree(arg.tree)
+ case _ => putTree(arg.intTree)
}
}
}
@@ -415,10 +532,17 @@ abstract class Pickler extends SubComponent {
else if (c.tag == StringTag) writeRef(newTermName(c.stringValue))
else if (c.tag == ClassTag) writeRef(c.typeValue)
LITERAL + c.tag
- case AnnotatedType(attribs, tp) =>
- writeRef(tp)
- writeRefs(attribs)
- ANNOTATEDtpe
+ case AnnotatedType(attribs, tp, selfsym) =>
+ if (settings.selfInAnnots.value) {
+ writeRef(tp)
+ writeRef(selfsym)
+ writeRefs(attribs)
+ ANNOTATEDWSELFtpe
+ } else {
+ writeRef(tp)
+ writeRefs(attribs)
+ ANNOTATEDtpe
+ }
case (target: Symbol, attr @ AnnotationInfo(atp, args, assocs)) =>
writeRef(target)
writeRef(atp)
@@ -429,205 +553,376 @@ abstract class Pickler extends SubComponent {
writeRef(target)
for (c <- children) writeRef(c.asInstanceOf[Symbol])
CHILDREN
- case reflect.Ident(sym) =>
- writeNat(IDENTtree)
- writeRef(sym)
- REFLTREE
- case reflect.Select(qual, sym) =>
- writeNat(SELECTtree)
- writeRef(qual)
- writeRef(sym)
- REFLTREE
- case reflect.Literal(value) =>
- writeNat(LITERALtree)
- writeRef(Constant(value))
- REFLTREE
- case reflect.Apply(fun, args) =>
- writeNat(APPLYtree)
- writeRef(fun)
- writeRefs(args)
- REFLTREE
- case reflect.TypeApply(fun, args) =>
- writeNat(TYPEAPPLYtree)
- writeRef(fun)
- writeRefs(args)
- REFLTREE
- case reflect.Function(params, body) =>
- writeNat(FUNCTIONtree)
- writeRef(body)
- writeRefs(params)
- REFLTREE
- case reflect.This(sym) =>
- writeNat(THIStree)
- writeRef(sym)
- REFLTREE
- case reflect.Block(stats, expr) =>
- writeNat(BLOCKtree)
- writeRef(expr)
+
+ case EmptyTree =>
+ writeNat(EMPTYtree)
+ TREE
+
+ case tree@PackageDef(name, stats) =>
+ writeNat(PACKAGEtree)
+ writeRef(tree.tpe)
+ writeRef(tree.symbol)
+ writeRef(tree.mods)
+ writeRef(name)
writeRefs(stats)
- REFLTREE
- case reflect.New(clz) =>
- writeNat(NEWtree)
- writeRef(clz)
- REFLTREE
- case reflect.If(condition, trueCase, falseCase) =>
- writeNat(IFtree)
- writeRef(condition)
- writeRef(trueCase)
- writeRef(falseCase)
- REFLTREE
- case reflect.Assign(destination, source) =>
- writeNat(ASSIGNtree)
- writeRef(destination)
- writeRef(source)
- REFLTREE
- case reflect.Target(sym, body) =>
- writeNat(TARGETtree)
- writeRef(sym)
- writeRef(body)
- REFLTREE
- case reflect.Goto(target) =>
- writeNat(GOTOtree)
- writeRef(target)
- REFLTREE
- case reflect.ValDef(sym, rhs) =>
- writeNat(VALDEFtree)
- writeRef(sym)
- writeRef(rhs)
- REFLTREE
- case reflect.ClassDef(sym, tpe, impl) =>
- writeNat(CLASSDEFtree)
- writeRef(sym)
- writeRef(tpe)
+ TREE
+
+ case tree@ClassDef(mods, name, tparams, impl) =>
+ writeNat(CLASStree)
+ writeRef(tree.tpe)
+ writeRef(tree.symbol)
+ writeRef(mods)
+ writeRef(name)
writeRef(impl)
- REFLTREE
- case reflect.DefDef(sym, vparamss, ret, rhs) =>
+ 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(sym)
- writeRef(ret)
- writeRef(rhs)
- for (vparams <- vparamss) {
- writeNat(vparams.length)
- writeRefs(vparams)
- }
- REFLTREE
- case reflect.Super(psym) =>
- writeNat(SUPERtree)
- writeRef(psym)
- REFLTREE
- case reflect.Template(parents, body) =>
+ writeRef(tree.tpe)
+ writeRef(tree.symbol)
+ writeRef(mods)
+ writeRef(name)
+ writeNat(tparams.length)
+ writeRefs(tparams)
+ writeNat(vparamss.length)
+ for(vparams <- vparamss) {
+ writeNat(vparams.length)
+ writeRefs(vparams)
+ }
+ 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(rhs)
+ writeRefs(params)
+ TREE
+
+
+ case tree@Import(expr, selectors) =>
+ writeNat(IMPORTtree)
+ writeRef(tree.tpe)
+ writeRef(tree.symbol)
+ writeRef(expr)
+ for ((from, to) <- selectors) {
+ writeRef(from)
+ writeRef(to)
+ }
+ TREE
+
+
+ case tree@Annotation(constr, elements) =>
+ writeNat(ANNOTATIONtree)
+ writeRef(tree.tpe)
+ writeRef(constr)
+ writeRefs(elements)
+ 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)
writeNat(parents.length)
- writeRefs(parents)
- writeRefs(body)
- REFLTREE
- case reflect.NoPrefix =>
- writeNat(NOPREFIXrtpe)
- REFLTYPE
- case reflect.NoType =>
- writeNat(NOrtpe)
- REFLTYPE
- case reflect.NamedType(fullname) =>
- writeNat(NAMEDrtpe)
- writeRef(Constant(fullname))
- REFLTYPE
- case reflect.PrefixedType(pre, sym) =>
- writeNat(PREFIXEDrtpe)
- writeRef(pre)
- writeRef(sym)
- REFLTYPE
- case reflect.SingleType(pre, sym) =>
- writeNat(SINGLErtpe)
- writeRef(pre)
- writeRef(sym)
- REFLTYPE
- case reflect.ThisType(clazz) =>
- writeNat(THISrtpe)
- writeRef(clazz)
- REFLTYPE
- case reflect.AppliedType(tpe, args) =>
- writeNat(APPLIEDrtpe)
- writeRef(tpe)
- writeRefs(args)
- REFLTYPE
- case reflect.TypeBounds(lo, hi) =>
- writeNat(TYPEBOUNDSrtpe)
- writeRef(lo)
- writeRef(hi)
- REFLTYPE
- case entry@reflect.MethodType(formals, restpe) => //can be implicit
- if(entry.isInstanceOf[ImplicitMethodType])
- writeNat(IMPLICITMETHODrtpe)
- else
- writeNat(METHODrtpe)
- writeRef(restpe)
- writeRefs(formals)
- REFLTYPE
- case reflect.PolyType(typeParams, typeBounds, resultType) =>
- writeNat(POLYrtpe)
- writeRef(resultType)
- writeNat(typeBounds.length)
- for ((t1,t2) <- typeBounds) {
- writeRef(t1)
- writeRef(t2)
- }
- writeRefs(typeParams)
- REFLTYPE
- case reflect.Class(fullname) =>
- writeNat(CLASSrsym)
- writeRef(Constant(fullname))
- REFLSYM
- case reflect.Method(fullname, tpe) =>
- writeNat(METHODrsym)
- writeRef(Constant(fullname))
- writeRef(tpe)
- REFLSYM
- case reflect.Field(fullname, tpe) =>
- writeNat(FIELDrsym)
- writeRef(Constant(fullname))
- writeRef(tpe)
- REFLSYM
- case reflect.TypeField(fullname, tpe) =>
- writeNat(TYPEFIELDrsym)
- writeRef(Constant(fullname))
- writeRef(tpe)
- REFLSYM
- case reflect.LocalValue(owner, name, tpe) =>
- writeNat(LOCALVALUErsym)
- writeRef(owner)
- writeRef(Constant(name))
- writeRef(tpe)
- REFLSYM
- case reflect.LocalMethod(owner, name, tpe) =>
- writeNat(LOCALMETHODrsym)
- writeRef(owner)
- writeRef(Constant(name))
- writeRef(tpe)
- REFLSYM
- case reflect.NoSymbol =>
- writeNat(NOSYMBOLrsym)
- REFLSYM
- case reflect.RootSymbol =>
- writeNat(ROOTSYMBOLrsym)
- REFLSYM
- case reflect.LabelSymbol(name) =>
- writeNat(LABELSYMBOLrsym)
+ writeRefs(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@Sequence(trees) =>
+ writeNat(SEQUENCEtree)
+ writeRef(tree.tpe)
+ writeRefs(trees)
+ 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)
- REFLSYM
- case AnnotationInfo(target, args, assocs) =>
- writeRef(target)
+ 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)
+ writeRef(tree.tpe)
+ writeRef(ref)
+ TREE
+
+ case tree@SelectFromTypeTree(qualifier, selector) =>
+ writeNat(SELECTFROMTYPEtree)
+ writeRef(tree.tpe)
+ writeRef(qualifier)
+ writeRef(selector)
+ TREE
+
+ case tree@CompoundTypeTree(templ: Template) =>
+ writeNat(COMPOUNDTYPEtree)
+ writeRef(tree.tpe)
+ writeRef(templ)
+ TREE
+
+ case tree@AppliedTypeTree(tpt, args) =>
+ writeNat(APPLIEDTYPEtree)
+ writeRef(tree.tpe)
+ writeRef(tpt)
+ writeRefs(args)
+ TREE
+
+ case tree@TypeBoundsTree(lo, hi) =>
+ writeNat(TYPEBOUNDStree)
+ writeRef(tree.tpe)
+ writeRef(lo)
+ writeRef(hi)
+ TREE
+
+ case tree@ExistentialTypeTree(tpt, whereClauses) =>
+ writeNat(EXISTENTIALTYPEtree)
+ writeRef(tree.tpe)
+ writeRef(tpt)
+ writeRefs(whereClauses)
+ TREE
+
+
+ case Modifiers(flags, privateWithin, annotations) =>
+ writeNat((flags >> 32).toInt)
+ writeNat((flags & 0xFFFFFFFF).toInt)
+ writeRef(privateWithin)
+ writeRefs(annotations)
+ MODIFIERS
+
+ case AnnotationInfo(atp, args, assocs) =>
+ writeRef(atp)
writeNat(args.length)
for (arg <- args) writeRef(arg)
for ((name, arg) <- assocs) {
writeRef(name);
writeRef(arg)
}
- ATTRIBTREE
+ ANNOTINFO
case arg:AnnotationArgument =>
arg.constant match {
case Some(c) => writeBody(c)
- case None => writeBody(arg.tree)
+ case None => writeBody(arg.intTree)
}
case _ =>
diff --git a/src/compiler/scala/tools/nsc/symtab/classfile/UnPickler.scala b/src/compiler/scala/tools/nsc/symtab/classfile/UnPickler.scala
index ce4c99ec25..26dca38361 100644
--- a/src/compiler/scala/tools/nsc/symtab/classfile/UnPickler.scala
+++ b/src/compiler/scala/tools/nsc/symtab/classfile/UnPickler.scala
@@ -273,16 +273,22 @@ abstract class UnPickler {
case EXISTENTIALtpe =>
val restpe = readTypeRef()
ExistentialType(until(end, readSymbolRef), restpe)
- case ANNOTATEDtpe =>
+ case ANNOTATEDtpe | ANNOTATEDWSELFtpe =>
val tp = readTypeRef()
+ val selfsym = if (tag == ANNOTATEDWSELFtpe) readSymbolRef()
+ else NoSymbol
val attribs = until(end, readTreeAttribRef)
- if(global.settings.Xplugtypes.value)
- AnnotatedType(attribs, tp)
- else
- tp // Drop the annotations unless -Xplugtypes.
+ if(settings.Xplugtypes.value) {
+ if (settings.selfInAnnots.value || (selfsym eq NoSymbol))
+ AnnotatedType(attribs, tp, selfsym)
+ else
+ tp // drop annotations with a self symbol unless
+ // -Yself-in-annots is on
+ } else
+ tp // Drop the annotations unless -Xplug-types is on.
// This way, people can distribute classfiles
// including annotated types without them much
- // affecting those who disable -Xplugtypes
+ // affecting those who disable -Xplug-types
case DEBRUIJNINDEXtpe =>
DeBruijnIndex(readNat(), readNat())
case _ =>
@@ -311,20 +317,35 @@ abstract class UnPickler {
}
}
- /** Read an annotation argument. It can be either a Constant or
- * a reflect.Tree.
+ /** Read an annotation argument. It can use either Constant's or
+ * Tree's for its arguments. If a reflect tree is seen, it
+ * prints a warning and returns an empty tree.
*/
private def readAnnotationArg(): AnnotationArgument = {
if (peekByte() == REFLTREE) {
- val tree = readReflTree()
- new AnnotationArgument(tree)
+ reflectAnnotationWarning()
+ new AnnotationArgument(EmptyTree)
+ } else if (peekByte() == TREE) {
+ val tree = readTree()
+ new AnnotationArgument(tree)
} else {
val const = readConstant()
new AnnotationArgument(const)
}
}
- /** Read an attribute and store in referenced symbol */
+ /** Read an annotation abstract syntax tree. */
+ private def readAnnotationTree(): Annotation = {
+ val tag = readByte()
+ val end = readNat() + readIndex
+ val tpe = readTypeRef()
+ val constr = readTreeRef()
+ val elements = until(end, readTreeRef)
+ Annotation(constr, elements).setType(tpe)
+ }
+
+ /** Read an attribute and as a side effect store it into
+ * the symbol it requests. */
private def readAnnotation(): AnyRef = {
val tag = readByte()
val end = readNat() + readIndex
@@ -348,196 +369,14 @@ abstract class UnPickler {
null
}
- /** Read a reflect.Tree */
- private def readReflTree(): reflect.Tree = {
- val outerTag = readByte()
- if(outerTag != REFLTREE)
- errorBadSignature("reflection tree expected (" + outerTag + ")")
- val end = readNat() + readIndex
- val tag = readByte()
- tag match {
- case IDENTtree =>
- val sym = readReflSymbolRef()
- reflect.Ident(sym)
- case SELECTtree =>
- val qual = readReflTreeRef()
- val sym = readReflSymbolRef()
- reflect.Select(qual, sym)
- case LITERALtree =>
- val value = readConstantRef()
- reflect.Literal(value)
- case APPLYtree =>
- val fun = readReflTreeRef()
- val args = until(end, readReflTreeRef)
- reflect.Apply(fun, args)
- case TYPEAPPLYtree =>
- val fun = readReflTreeRef()
- val args = until(end, readReflTypeRef)
- reflect.TypeApply(fun, args)
- case FUNCTIONtree =>
- val body = readReflTreeRef()
- val params = until(end, readReflSymbolRef)
- reflect.Function(params, body)
- case THIStree =>
- val sym = readReflSymbolRef()
- reflect.This(sym)
- case BLOCKtree =>
- val expr = readReflTreeRef()
- val stats = until(end, readReflTreeRef)
- reflect.Block(stats, expr)
- case NEWtree =>
- val clz = readReflTreeRef()
- reflect.New(clz)
- case IFtree =>
- val condition = readReflTreeRef()
- val trueCase = readReflTreeRef()
- val falseCase = readReflTreeRef()
- reflect.If(condition, trueCase, falseCase)
- case ASSIGNtree =>
- val destination = readReflTreeRef()
- val source = readReflTreeRef()
- reflect.Assign(destination, source)
- case TARGETtree =>
- val sym = readReflSymbolRef()
- val body = readReflTreeRef()
- sym match {
- case sym:reflect.LabelSymbol => reflect.Target(sym, body)
- case _ => errorBadSignature("bad label for target: " + sym)
- }
- case GOTOtree =>
- val target = readReflSymbolRef()
- target match {
- case target:reflect.LabelSymbol => reflect.Goto(target)
- case _ => errorBadSignature("bad target for goto: " + target)
- }
- case VALDEFtree =>
- val sym = readReflSymbolRef()
- val rhs = readReflTreeRef()
- reflect.ValDef(sym, rhs)
- case CLASSDEFtree =>
- val sym = readReflSymbolRef()
- val tpe = readReflTypeRef()
- val impl = readReflTreeRef()
- impl match {
- case impl:reflect.Template => reflect.ClassDef(sym, tpe, impl)
- case _ =>
- errorBadSignature("body of class not a template: " + impl)
- }
- case tag =>
- errorBadSignature("unknown reflection tree (" + tag + ")")
- }
- }
-
- /** Read a reflect.Symbol */
- private def readReflSymbol(): reflect.Symbol = {
- val outerTag = readByte()
- if(outerTag != REFLSYM)
- errorBadSignature("reflection symbol expected (" + outerTag + ")")
- val end = readNat() + readIndex
- val tag = readNat()
- tag match {
- case CLASSrsym =>
- val fullname = readConstantRef().stringValue
- reflect.Class(fullname)
- case METHODrsym =>
- val fullname = readConstantRef().stringValue
- val tpe = readReflTypeRef()
- reflect.Method(fullname, tpe)
- case FIELDrsym =>
- val fullname = readConstantRef().stringValue
- val tpe = readReflTypeRef()
- reflect.Field(fullname, tpe)
- case TYPEFIELDrsym =>
- val fullname = readConstantRef().stringValue
- val tpe = readReflTypeRef()
- reflect.TypeField(fullname, tpe)
- case LOCALVALUErsym =>
- val owner = readReflSymbolRef()
- val name = readConstantRef().stringValue
- val tpe = readReflTypeRef()
- reflect.LocalValue(owner, name, tpe)
- case LOCALMETHODrsym =>
- val owner = readReflSymbolRef()
- val name = readConstantRef().stringValue
- val tpe = readReflTypeRef()
- reflect.LocalMethod(owner, name, tpe)
- case NOSYMBOLrsym =>
- reflect.NoSymbol
- case ROOTSYMBOLrsym =>
- reflect.RootSymbol
- case LABELSYMBOLrsym =>
- val name = readConstantRef().stringValue
- reflect.LabelSymbol(name)
- case tag =>
- errorBadSignature("unknown reflection symbol (" + tag + ")")
- }
- }
-
- /** Read a reflect.Type */
- private def readReflType(): reflect.Type = {
- val outerTag = readByte()
- if(outerTag != REFLTYPE)
- errorBadSignature("reflection type expected (" + outerTag + ")")
- val end = readNat() + readIndex
- val tag = readNat()
- tag match {
- case NOPREFIXrtpe =>
- reflect.NoPrefix
- case NOrtpe =>
- reflect.NoType
- case NAMEDrtpe =>
- val fullname = readConstantRef()
- reflect.NamedType(fullname.stringValue)
- case PREFIXEDrtpe =>
- val pre = readReflTypeRef()
- val sym = readReflSymbolRef()
- reflect.PrefixedType(pre, sym)
- case SINGLErtpe =>
- val pre = readReflTypeRef()
- val sym = readReflSymbolRef()
- reflect.SingleType(pre, sym)
- case THISrtpe =>
- val clazz = readReflSymbolRef()
- reflect.ThisType(clazz)
- case APPLIEDrtpe =>
- val tpe = readReflTypeRef()
- val args = until(end, readReflTypeRef)
- reflect.AppliedType(tpe, args)
- case TYPEBOUNDSrtpe =>
- val lo = readReflTypeRef()
- val hi = readReflTypeRef()
- reflect.TypeBounds(lo, hi)
- case IMPLICITMETHODrtpe =>
- val restpe = readReflTypeRef()
- val formals = until(end, readReflTypeRef)
- new reflect.ImplicitMethodType(formals, restpe)
- case METHODrtpe =>
- val restpe = readReflTypeRef()
- val formals = until(end, readReflTypeRef)
- reflect.MethodType(formals, restpe)
- case POLYrtpe =>
- val resultType = readReflTypeRef()
- val numBounds = readNat()
- val typeBounds = times(numBounds, {() =>
- val lo = readReflTypeRef()
- val hi = readReflTypeRef()
- (lo,hi)
- })
- val typeParams = until(end, readReflSymbolRef)
- reflect.PolyType(typeParams, typeBounds, resultType)
- case tag =>
- errorBadSignature("unknown reflection type (" + tag + ")")
- }
- }
-
- /** Read an annotation with reflect.Tree's */
+ /** Read an annotation and return it. */
private def readTreeAttrib(): AnnotationInfo = {
val tag = readByte()
- if(tag != ATTRIBTREE)
+ if(tag != ANNOTINFO)
errorBadSignature("tree-based annotation expected (" + tag + ")")
val end = readNat() + readIndex
- val target = readTypeRef()
+ val atp = readTypeRef()
val numargs = readNat()
val args = times(numargs, readAnnotationArgRef)
val assocs =
@@ -545,7 +384,323 @@ abstract class UnPickler {
val name = readNameRef()
val tree = readAnnotationArgRef()
(name,tree)})
- AnnotationInfo(target, args, assocs)
+ AnnotationInfo(atp, args, assocs)
+ }
+
+ /* Read an abstract syntax tree */
+ private def readTree(): Tree = {
+ val outerTag = readByte()
+ if (outerTag != TREE)
+ errorBadSignature("tree expected (" + outerTag + ")")
+ val end = readNat() + readIndex
+ val tag = readByte()
+ val tpe =
+ if (tag != EMPTYtree)
+ readTypeRef()
+ else
+ NoType
+
+ tag match {
+ case EMPTYtree =>
+ EmptyTree
+
+ case PACKAGEtree =>
+ val symbol = readSymbolRef()
+ val name = readNameRef()
+ val stats = until(end, readTreeRef)
+
+ PackageDef(name, stats) setType tpe
+
+ case CLASStree =>
+ val symbol = readSymbolRef()
+ val mods = readModifiersRef()
+ val name = readNameRef()
+ val impl = readTemplateRef()
+ val tparams = until(end, readTypeDefRef)
+ (ClassDef(mods, name, tparams, impl).
+ setSymbol(symbol).
+ setType(tpe))
+
+ case MODULEtree =>
+ val symbol = readSymbolRef()
+ val mods = readModifiersRef()
+ val name = readNameRef()
+ val impl = readTemplateRef()
+ (ModuleDef(mods, name, impl).
+ setSymbol(symbol).
+ setType(tpe))
+
+ case VALDEFtree =>
+ val symbol = readSymbolRef()
+ val mods = readModifiersRef()
+ val name = readNameRef()
+ val tpt = readTreeRef()
+ val rhs = readTreeRef()
+
+ (ValDef(mods, name, tpt, rhs).
+ setSymbol(symbol).
+ setType(tpe))
+
+ case DEFDEFtree =>
+ val symbol = readSymbolRef()
+ val mods = readModifiersRef()
+ val name = readNameRef()
+ val numTparams = readNat()
+ val tparams = times(numTparams, readTypeDefRef)
+ val numVparamss = readNat
+ val vparamss = times(numVparamss, () => {
+ val len = readNat()
+ times(len, readValDefRef)})
+ val tpt = readTreeRef()
+ val rhs = readTreeRef()
+
+ (DefDef(mods, name, tparams, vparamss, tpt, rhs).
+ setSymbol(symbol).
+ setType(tpe))
+
+ case TYPEDEFtree =>
+ val symbol = readSymbolRef()
+ val mods = readModifiersRef()
+ val name = readNameRef()
+ val rhs = readTreeRef()
+ val tparams = until(end, readTypeDefRef)
+
+ (TypeDef(mods, name, tparams, rhs).
+ setSymbol(symbol).
+ setType(tpe))
+
+
+ case LABELtree =>
+ val symbol = readSymbolRef()
+ val rhs = readTreeRef()
+ val params = until(end, readIdentRef)
+ (LabelDef(name, params, rhs).
+ setSymbol(symbol).
+ setType(tpe))
+
+ case IMPORTtree =>
+ val symbol = readSymbolRef()
+ val expr = readTreeRef()
+ val selectors = until(end, () => {
+ val from = readNameRef()
+ val to = readNameRef()
+ (from, to)
+ })
+ (Import(expr, selectors).
+ setSymbol(symbol).
+ setType(tpe))
+
+ case ANNOTATIONtree =>
+ val constr = readTreeRef()
+ val elements = until(end, readTreeRef)
+ (Annotation(constr, elements).setType(tpe))
+
+ case DOCDEFtree =>
+ val comment = readConstantRef match {
+ case Constant(com: String) => com
+ case other =>
+ errorBadSignature("Document comment not a string (" + other + ")")
+ }
+ val definition = readTreeRef()
+ (DocDef(comment, definition).setType(tpe))
+
+ case TEMPLATEtree =>
+ val symbol = readSymbolRef()
+ val numParents = readNat()
+ val parents = times(numParents, readTreeRef)
+ val self = readValDefRef()
+ val body = until(end, readTreeRef)
+
+ (Template(parents, self, body).
+ setSymbol(symbol).
+ setType(tpe))
+
+ case BLOCKtree =>
+ val expr = readTreeRef()
+ val stats = until(end, readTreeRef)
+ Block(stats, expr).setType(tpe)
+
+ case CASEtree =>
+ val pat = readTreeRef()
+ val guard = readTreeRef()
+ val body = readTreeRef()
+ CaseDef(pat, guard, body).setType(tpe)
+
+ case SEQUENCEtree =>
+ val trees = until(end, readTreeRef)
+ Sequence(trees).setType(tpe)
+
+ case ALTERNATIVEtree =>
+ val trees = until(end, readTreeRef)
+ Alternative(trees).setType(tpe)
+
+ case STARtree =>
+ val elem = readTreeRef()
+ Star(elem).setType(tpe)
+
+ case BINDtree =>
+ val symbol = readSymbolRef()
+ val name = readNameRef()
+ val body = readTreeRef()
+ (Bind(name, body).
+ setSymbol(symbol).
+ setType(tpe))
+
+ case UNAPPLYtree =>
+ val fun = readTreeRef()
+ val args = until(end, readTreeRef)
+ (UnApply(fun: Tree, args).setType(tpe))
+
+ case ARRAYVALUEtree =>
+ val elemtpt = readTreeRef()
+ val trees = until(end, readTreeRef)
+ (ArrayValue(elemtpt, trees).setType(tpe))
+
+ case FUNCTIONtree =>
+ val symbol = readSymbolRef()
+ val body = readTreeRef()
+ val vparams = until(end, readValDefRef)
+ (Function(vparams, body).
+ setSymbol(symbol).
+ setType(tpe))
+
+ case ASSIGNtree =>
+ val lhs = readTreeRef()
+ val rhs = readTreeRef()
+ Assign(lhs, rhs).setType(tpe)
+
+ case IFtree =>
+ val cond = readTreeRef()
+ val thenp = readTreeRef()
+ val elsep = readTreeRef()
+ If(cond, thenp, elsep).setType(tpe)
+
+ case MATCHtree =>
+ val selector = readTreeRef()
+ val cases = until(end, readCaseDefRef)
+ Match(selector, cases).setType(tpe)
+
+ case RETURNtree =>
+ val symbol = readSymbolRef()
+ val expr = readTreeRef()
+ (Return(expr).
+ setSymbol(symbol).
+ setType(tpe))
+
+ case TREtree =>
+ val block = readTreeRef()
+ val finalizer = readTreeRef()
+ val catches = until(end, readCaseDefRef)
+ Try(block, catches, finalizer).setType(tpe)
+
+ case THROWtree =>
+ val expr = readTreeRef()
+ Throw(expr).setType(tpe)
+
+ case NEWtree =>
+ val tpt = readTreeRef()
+ New(tpt).setType(tpe)
+
+ case TYPEDtree =>
+ val expr = readTreeRef()
+ val tpt = readTreeRef()
+ Typed(expr, tpt).setType(tpe)
+
+ case TYPEAPPLYtree =>
+ val fun = readTreeRef()
+ val args = until(end, readTreeRef)
+ TypeApply(fun, args).setType(tpe)
+
+ case APPLYtree =>
+ val fun = readTreeRef()
+ val args = until(end, readTreeRef)
+ Apply(fun, args).setType(tpe)
+
+
+ case APPLYDYNAMICtree =>
+ val symbol = readSymbolRef()
+ val qual = readTreeRef()
+ val args = until(end, readTreeRef)
+ ApplyDynamic(qual, args).setSymbol(symbol).setType(tpe)
+
+ case SUPERtree =>
+ val symbol = readSymbolRef()
+ val qual = readNameRef()
+ val mix = readNameRef()
+ Super(qual, mix).setSymbol(symbol).setType(tpe)
+
+ case THIStree =>
+ val symbol = readSymbolRef()
+ val qual = readNameRef()
+ This(qual).setSymbol(symbol).setType(tpe)
+
+ case SELECTtree =>
+ val symbol = readSymbolRef()
+ val qualifier = readTreeRef()
+ val selector = readNameRef()
+ Select(qualifier, selector).setSymbol(symbol).setType(tpe)
+
+ case IDENTtree =>
+ val symbol = readSymbolRef()
+ val name = readNameRef()
+ Ident(name).setSymbol(symbol).setType(tpe)
+
+ case LITERALtree =>
+ val value = readConstantRef()
+ Literal(value).setType(tpe)
+
+ case TYPEtree =>
+ TypeTree().setType(tpe)
+
+ case ANNOTATEDtree =>
+ val annot = readAnnotationTreeRef()
+ val arg = readTreeRef()
+ Annotated(annot, arg).setType(tpe)
+
+ case SINGLETONTYPEtree =>
+ val ref = readTreeRef()
+ SingletonTypeTree(ref).setType(tpe)
+
+ case SELECTFROMTYPEtree =>
+ val qualifier = readTreeRef()
+ val selector = readNameRef()
+ SelectFromTypeTree(qualifier, selector).setType(tpe)
+
+ case COMPOUNDTYPEtree =>
+ val templ = readTemplateRef()
+ CompoundTypeTree(templ: Template).setType(tpe)
+
+ case APPLIEDTYPEtree =>
+ val tpt = readTreeRef()
+ val args = until(end, readTreeRef)
+ AppliedTypeTree(tpt, args).setType(tpe)
+
+ case TYPEBOUNDStree =>
+ val lo = readTreeRef()
+ val hi = readTreeRef()
+ TypeBoundsTree(lo, hi).setType(tpe)
+
+ case EXISTENTIALTYPEtree =>
+ val tpt = readTreeRef()
+ val whereClauses = until(end, readTreeRef)
+ ExistentialTypeTree(tpt, whereClauses).setType(tpe)
+
+ case _ =>
+ errorBadSignature("unknown tree type (" + tag + ")")
+ }
+ }
+
+ def readModifiers(): Modifiers = {
+ val tag = readNat()
+ if (tag != MODIFIERS)
+ errorBadSignature("expected a modifiers tag (" + tag + ")")
+ val end = readNat() + readIndex
+ val flagsHi = readNat()
+ val flagsLo = readNat()
+ val flags = (flagsHi.toLong << 32) + flagsLo
+ val privateWithin = readNameRef()
+ val annotations = until(end, readAnnotationTreeRef)
+ Modifiers(flags, privateWithin, annotations)
}
/* Read a reference to a pickled item */
@@ -555,19 +710,60 @@ abstract class UnPickler {
private def readConstantRef(): Constant = at(readNat(), readConstant)
private def readAnnotationArgRef(): AnnotationArgument =
at(readNat(), readAnnotationArg)
- private def readReflTreeRef(): reflect.Tree =
- at(readNat(), readReflTree)
- private def readReflSymbolRef(): reflect.Symbol =
- at(readNat(), readReflSymbol)
- private def readReflTypeRef(): reflect.Type =
- at(readNat(), readReflType)
private def readTreeAttribRef(): AnnotationInfo =
at(readNat(), readTreeAttrib)
+ private def readAnnotationTreeRef(): Annotation =
+ at(readNat(), readAnnotationTree)
+ private def readModifiersRef(): Modifiers =
+ at(readNat(), readModifiers)
+ private def readTreeRef(): Tree =
+ at(readNat(), readTree)
+
+ private def readTemplateRef(): Template =
+ readTreeRef() match {
+ case templ:Template => templ
+ case other =>
+ errorBadSignature("expected a template (" + other + ")")
+ }
+ private def readCaseDefRef(): CaseDef =
+ readTreeRef() match {
+ case tree:CaseDef => tree
+ case other =>
+ errorBadSignature("expected a case def (" + other + ")")
+ }
+ private def readValDefRef(): ValDef =
+ readTreeRef() match {
+ case tree:ValDef => tree
+ case other =>
+ errorBadSignature("expected a ValDef (" + other + ")")
+ }
+ private def readIdentRef(): Ident =
+ readTreeRef() match {
+ case tree:Ident => tree
+ case other =>
+ errorBadSignature("expected an Ident (" + other + ")")
+ }
+ private def readTypeDefRef(): TypeDef =
+ readTreeRef() match {
+ case tree:TypeDef => tree
+ case other =>
+ errorBadSignature("expected an TypeDef (" + other + ")")
+ }
+
private def errorBadSignature(msg: String) =
if (inIDE) throw new TypeError(msg)
else throw new RuntimeException("malformed Scala signature of " + classRoot.name + " at " + readIndex + "; " + msg)
+ private var printedReflectAnnotationWarning = false
+ private def reflectAnnotationWarning() {
+ if (!printedReflectAnnotationWarning) {
+ global.warning(
+ "warning: dropping a legacy format annotation in " + classRoot.name)
+ printedReflectAnnotationWarning = true
+ }
+ }
+
private class LazyTypeRef(i: Int) extends LazyType {
private val definedAtRunId = currentRunId
// In IDE, captures class files dependencies so they can be reloaded when their dependencies change.
diff --git a/src/compiler/scala/tools/nsc/transform/Erasure.scala b/src/compiler/scala/tools/nsc/transform/Erasure.scala
index 02ce42a1a6..dfac428303 100644
--- a/src/compiler/scala/tools/nsc/transform/Erasure.scala
+++ b/src/compiler/scala/tools/nsc/transform/Erasure.scala
@@ -95,6 +95,8 @@ abstract class Erasure extends AddInterfaces with typechecker.Analyzer {
case RefinedType(parents, decls) =>
if (parents.isEmpty) erasedTypeRef(ObjectClass)
else apply(parents.head)
+ case AnnotatedType(_, atp, _) =>
+ apply(atp)
case ClassInfoType(parents, decls, clazz) =>
ClassInfoType(
if ((clazz == ObjectClass) || (isValueType(clazz))) List()
diff --git a/src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala b/src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala
index 55c8023ed3..bf5158324b 100644
--- a/src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala
+++ b/src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala
@@ -452,7 +452,7 @@ abstract class ExplicitOuter extends InfoTransform with TransMatcher with Patter
var checkExhaustive = true
def isUncheckedAnnotation(tpe: Type) = tpe match {
- case AnnotatedType(List(AnnotationInfo(atp, _, _)), _) if atp.typeSymbol == UncheckedClass =>
+ case AnnotatedType(List(AnnotationInfo(atp, _, _)), _, _) if atp.typeSymbol == UncheckedClass =>
true
case _ =>
false
diff --git a/src/compiler/scala/tools/nsc/transform/LiftCode.scala b/src/compiler/scala/tools/nsc/transform/LiftCode.scala
index 91caf14b8c..e3e9d70384 100644
--- a/src/compiler/scala/tools/nsc/transform/LiftCode.scala
+++ b/src/compiler/scala/tools/nsc/transform/LiftCode.scala
@@ -19,13 +19,15 @@ import scala.tools.nsc.util.{FreshNameCreator, TreeSet}
* @author Gilles Dubochet
* @version 1.0
*/
-abstract class LiftCode extends Transform {
+abstract class LiftCode extends Transform with Reifiers {
import global._ // the global environment
import definitions._ // standard classes and methods
import typer.{typed, atOwner} // methods to type trees
import posAssigner.atPos // for filling in tree positions
+ val symbols: global.type = global
+
/** the following two members override abstract members in Transform */
val phaseName: String = "liftcode"
@@ -42,147 +44,6 @@ abstract class LiftCode extends Transform {
}
}
- case class FreeValue(tree: Tree) extends reflect.Tree
-
- class ReifyEnvironment extends HashMap[Symbol, reflect.Symbol] {
- var targets = new HashMap[String, Option[reflect.LabelSymbol]]()
- def addTarget(name: String, target: reflect.LabelSymbol): Unit =
- targets.update(name, Some(target))
- def getTarget(name: String): Option[reflect.LabelSymbol] =
- targets.get(name) match {
- case None =>
- targets.update(name, None)
- None
- //case Some(None) => None //bq:redundant
- case Some(tgt) => tgt
- }
- def hasAllTargets: Boolean =
- targets.elements.map(_._2).forall {
- case Some(_) => true
- case None => false
- }
- override def update(sym: Symbol, rsym: reflect.Symbol) =
- super.update(sym,rsym)
- }
-
-
- class Reifier(env: ReifyEnvironment, currentOwner: reflect.Symbol)
- extends SymbolReifier
- {
- val symbols: global.type = global
-
-
- def reify(tree: Tree): reflect.Tree = tree match {
- case Ident(_) =>
- val rsym = reify(tree.symbol);
- //Console.println("LiftCode: seen ident")
- if (rsym == reflect.NoSymbol) {
- //Console.println(" free = "+tree)
- FreeValue(tree)
- } else {
- //Console.println(" rsym = "+rsym)
- reflect.Ident(rsym)
- }
- case Select(qual, _) =>
- val rsym = reify(tree.symbol);
- if (rsym == reflect.NoSymbol) throw new TypeError("cannot reify symbol: " + tree.symbol)
- else reflect.Select(reify(qual), reify(tree.symbol))
-
- case _ : StubTree => reflect.Literal(0)
- case Literal(constant) =>
- reflect.Literal(constant.value)
-
- case Apply(name, args) if name.toString().startsWith("label$") =>
- env.getTarget(name.toString()) match {
- case None => throw new TypeError("cannot reify tree (no forward jumps allowed): " + tree)
- case Some(label) => reflect.Goto(label)
- }
-
- case Apply(fun, args) =>
- reflect.Apply(reify(fun), args map reify)
-
- case TypeApply(fun, args) =>
- reflect.TypeApply(reify(fun), args map (_.tpe) map reify)
-
- case Function(vparams, body) =>
- var env1 = env
- for (vparam <- vparams) {
- val local = reflect.LocalValue(
- currentOwner, vparam.symbol.name.toString(), reify(vparam.symbol.tpe));
- env1.update(vparam.symbol, local);
- }
- reflect.Function(vparams map (_.symbol) map env1,
- new Reifier(env1, currentOwner).reify(body))
- case tree@This(_) if tree.symbol.isModule =>
- // there is no reflect node for a module's this, so
- // represent it as a selection of the module
- reify(typed(
- Select(This(tree.symbol.owner), tree.symbol.name)))
- case This(_) =>
- reflect.This(reify(tree.symbol))
- case Block(stats, expr) =>
- reflect.Block(stats.map(reify), reify(expr))
- case New(clazz) =>
- val reifiedClass = reify(clazz)
- reflect.New(reifiedClass)
- case Typed(t, _) =>
- reify(t)
- case If(cond, thenp, elsep) =>
- reflect.If(reify(cond), reify(thenp), reify(elsep))
- case Assign(lhs, rhs) =>
- reflect.Assign(reify(lhs), reify(rhs))
-
- case LabelDef(name, Nil, body) =>
- val sym = new reflect.LabelSymbol(name.toString())
- env.addTarget(name.toString(), sym)
- val res = reflect.Target(sym, reify(body))
- res
-
- case vd @ ValDef(mods, name, tpt, rhs) =>
- val rtpe = reify(vd.tpe) // will return null, currently?!
- val sym = reflect.LocalValue(currentOwner, name.toString(), rtpe)
- env(vd.symbol) = sym // bq: despite Scala's scoping rules, this should work because references to vd.symbol were type checked.
- val rhs_ = reify(rhs)
- reflect.ValDef(sym, rhs_)
-
- case cd @ ClassDef(mods, name, tparams, impl) =>
- if(!tparams.isEmpty)
- throw new TypeError("cannot handle polymorphic ClassDef ("+name+"): " + tparams)
- val rsym = reify(cd.symbol)
- val rimp = reify(impl)
- val rtpe = reify(impl.self.tpt.tpe) //todo: update
- reflect.ClassDef(rsym, rtpe, rimp.asInstanceOf[reflect.Template])
-
- case tmpl @ Template(parents, self, body) =>
- val rparents = for (p <- parents) yield { reify(p.tpe) }
- //todo: add self to reified templates
- reflect.Template(rparents, body.map(reify))
-
- case dd @ DefDef(mods, name, tparams, vparamss, tpt, rhs) =>
- if(!tparams.isEmpty)
- throw new TypeError("cannot handle polymorphic DefDef ("+name+"): " + tparams)
- val rsym = reify(dd.symbol)
- val rparss = vparamss map { x => x map (reify) }
- val rret = reify(tpt.tpe)
- val rrhs = reify(rhs)
- reflect.DefDef(rsym, rparss, rret, rrhs)
-
- case sp @ Super(qual: Name, mix: Name) =>
- val rsym = reify(sp.symbol)
- reflect.Super(rsym)
-
- case _ =>
- throw new TypeError("cannot reify tree ("+tree.getClass()+"): " + tree)
- }
-
- override def reify(sym: Symbol): reflect.Symbol =
- env.get(sym) match {
- case Some(rsym) =>
- rsym
- case None =>
- super.reify(sym)
- }
- }
type InjectEnvironment = ListMap[reflect.Symbol, Name]
@@ -247,8 +108,6 @@ abstract class LiftCode extends Transform {
}
} // Injector
- def reify(tree: Tree): reflect.Tree =
- new Reifier(new ReifyEnvironment(), reflect.NoSymbol).reify(tree)
def inject(code: reflect.Tree): Tree =
new Injector(ListMap.empty, new FreshNameCreator.Default).inject(code)
diff --git a/src/compiler/scala/tools/nsc/transform/SymbolReifier.scala b/src/compiler/scala/tools/nsc/transform/Reifiers.scala
index 6e26ac8a07..e29621e395 100644
--- a/src/compiler/scala/tools/nsc/transform/SymbolReifier.scala
+++ b/src/compiler/scala/tools/nsc/transform/Reifiers.scala
@@ -1,14 +1,15 @@
package scala.tools.nsc.transform
import scala.tools.nsc.symtab.SymbolTable
import scala.reflect
+import collection.mutable.HashMap
-/** Functions to reify (and un-reify) symbols and types.
+/** Functions to reify (and un-reify) symbols, types, and trees.
* These can be used with only a symbol table; they do not
* need a full compiler.
*
* @author Gilles Dubochet, Lex Spoon
*/
-trait SymbolReifier {
+trait Reifiers {
val symbols: SymbolTable
import symbols._
@@ -85,7 +86,7 @@ trait SymbolReifier {
boundss,
reify(result))
//todo: treat ExistentialType
- case AnnotatedType(attribs, tp) =>
+ case AnnotatedType(attribs, tp, _) =>
reify(tp)
case _ =>
println("could not reify: " + tp)
@@ -171,4 +172,149 @@ trait SymbolReifier {
case _ => NoSymbol
}
+
+ case class FreeValue(tree: Tree) extends reflect.Tree
+
+ class ReifyEnvironment extends HashMap[Symbol, reflect.Symbol] {
+ var targets = new HashMap[String, Option[reflect.LabelSymbol]]()
+ def addTarget(name: String, target: reflect.LabelSymbol): Unit =
+ targets.update(name, Some(target))
+ def getTarget(name: String): Option[reflect.LabelSymbol] =
+ targets.get(name) match {
+ case None =>
+ targets.update(name, None)
+ None
+ //case Some(None) => None //bq:redundant
+ case Some(tgt) => tgt
+ }
+ def hasAllTargets: Boolean =
+ targets.elements.map(_._2).forall {
+ case Some(_) => true
+ case None => false
+ }
+ override def update(sym: Symbol, rsym: reflect.Symbol) =
+ super.update(sym,rsym)
+ }
+
+
+ class Reifier(env: ReifyEnvironment, currentOwner: reflect.Symbol)
+ {
+ def reify(tree: Tree): reflect.Tree = tree match {
+ case Ident(_) =>
+ val rsym = reify(tree.symbol);
+ //Console.println("LiftCode: seen ident")
+ if (rsym == reflect.NoSymbol) {
+ //Console.println(" free = "+tree)
+ FreeValue(tree)
+ } else {
+ //Console.println(" rsym = "+rsym)
+ reflect.Ident(rsym)
+ }
+ case Select(qual, _) =>
+ val rsym = reify(tree.symbol);
+ if (rsym == reflect.NoSymbol) throw new TypeError("cannot reify symbol: " + tree.symbol)
+ else reflect.Select(reify(qual), reify(tree.symbol))
+
+ case _ : StubTree => reflect.Literal(0)
+
+ case Literal(constant) =>
+ reflect.Literal(constant.value)
+
+ case Apply(name, args) if name.toString().startsWith("label$") =>
+ env.getTarget(name.toString()) match {
+ case None => throw new TypeError("cannot reify tree (no forward jumps allowed): " + tree)
+ case Some(label) => reflect.Goto(label)
+ }
+
+ case Apply(fun, args) =>
+ reflect.Apply(reify(fun), args map reify)
+
+ case TypeApply(fun, args) =>
+ reflect.TypeApply(reify(fun), args map (_.tpe) map reify)
+
+ case Function(vparams, body) =>
+ var env1 = env
+ for (vparam <- vparams) {
+ val local = reflect.LocalValue(
+ currentOwner, vparam.symbol.name.toString(), reify(vparam.symbol.tpe));
+ env1.update(vparam.symbol, local);
+ }
+ reflect.Function(vparams map (_.symbol) map env1,
+ new Reifier(env1, currentOwner).reify(body))
+ case tree@This(_) if tree.symbol.isModule =>
+ // there is no reflect node for a module's this, so
+ // represent it as a selection of the module
+ reify(
+ Select(This(tree.symbol.owner), tree.symbol.name))
+ case This(_) =>
+ reflect.This(reify(tree.symbol))
+ case Block(stats, expr) =>
+ reflect.Block(stats.map(reify), reify(expr))
+ case New(clazz) =>
+ val reifiedClass = reify(clazz)
+ reflect.New(reifiedClass)
+ case Typed(t, _) =>
+ reify(t)
+ case If(cond, thenp, elsep) =>
+ reflect.If(reify(cond), reify(thenp), reify(elsep))
+ case Assign(lhs, rhs) =>
+ reflect.Assign(reify(lhs), reify(rhs))
+
+ case LabelDef(name, Nil, body) =>
+ val sym = new reflect.LabelSymbol(name.toString())
+ env.addTarget(name.toString(), sym)
+ val res = reflect.Target(sym, reify(body))
+ res
+
+ case vd @ ValDef(mods, name, tpt, rhs) =>
+ val rtpe = reify(vd.tpe) // will return null, currently?!
+ val sym = reflect.LocalValue(currentOwner, name.toString(), rtpe)
+ env(vd.symbol) = sym // bq: despite Scala's scoping rules, this should work because references to vd.symbol were type checked.
+ val rhs_ = reify(rhs)
+ reflect.ValDef(sym, rhs_)
+
+ case cd @ ClassDef(mods, name, tparams, impl) =>
+ if(!tparams.isEmpty)
+ throw new TypeError("cannot handle polymorphic ClassDef ("+name+"): " + tparams)
+ val rsym = reify(cd.symbol)
+ val rimp = reify(impl)
+ val rtpe = reify(impl.self.tpt.tpe) //todo: update
+ reflect.ClassDef(rsym, rtpe, rimp.asInstanceOf[reflect.Template])
+
+ case tmpl @ Template(parents, self, body) =>
+ val rparents = for (p <- parents) yield { reify(p.tpe) }
+ //todo: add self to reified templates
+ reflect.Template(rparents, body.map(reify))
+
+ case dd @ DefDef(mods, name, tparams, vparamss, tpt, rhs) =>
+ if(!tparams.isEmpty)
+ throw new TypeError("cannot handle polymorphic DefDef ("+name+"): " + tparams)
+ val rsym = reify(dd.symbol)
+ val rparss = vparamss map { x => x map (reify) }
+ val rret = reify(tpt.tpe)
+ val rrhs = reify(rhs)
+ reflect.DefDef(rsym, rparss, rret, rrhs)
+
+ case sp @ Super(qual: Name, mix: Name) =>
+ val rsym = reify(sp.symbol)
+ reflect.Super(rsym)
+
+ case _ =>
+ throw new TypeError("cannot reify tree ("+tree.getClass()+"): " + tree)
+ }
+
+ def reify(sym: Symbol): reflect.Symbol =
+ env.get(sym) match {
+ case Some(rsym) =>
+ rsym
+ case None =>
+ Reifiers.this.reify(sym)
+ }
+
+ def reify(tpe: Type): reflect.Type =
+ Reifiers.this.reify(tpe)
+ }
+
+ def reify(tree: Tree): reflect.Tree =
+ new Reifier(new ReifyEnvironment(), reflect.NoSymbol).reify(tree)
}
diff --git a/src/compiler/scala/tools/nsc/typechecker/Infer.scala b/src/compiler/scala/tools/nsc/typechecker/Infer.scala
index 61de540d03..f3d0208ab5 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Infer.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Infer.scala
@@ -851,7 +851,7 @@ trait Infer {
widen(tp.normalize)
case rtp @ RefinedType(parents, decls) =>
copyRefinedType(rtp, List.mapConserve(parents)(widen), decls)
- case AnnotatedType(_, underlying) =>
+ case AnnotatedType(_, underlying, _) =>
widen(underlying)
case _ =>
tp
diff --git a/src/compiler/scala/tools/nsc/typechecker/Namers.scala b/src/compiler/scala/tools/nsc/typechecker/Namers.scala
index 8c5020c39a..b285113ee6 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Namers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Namers.scala
@@ -543,6 +543,8 @@ trait Namers { self: Analyzer =>
methodArgumentNames(meth) = vparamss.map(_.map(_.symbol));
def convertToDeBruijn(vparams: List[Symbol], level: Int): TypeMap = new TypeMap {
+ def debruijnFor(param: Symbol) =
+ DeBruijnIndex(level, vparams indexOf param)
def apply(tp: Type) = {
tp match {
case SingleType(_, sym) =>
@@ -553,7 +555,7 @@ trait Namers { self: Analyzer =>
ErrorType
} else
*/
- DeBruijnIndex(level, vparams indexOf sym)
+ debruijnFor(sym)
} else tp
case MethodType(formals, restpe) =>
val formals1 = List.mapConserve(formals)(this)
@@ -564,6 +566,24 @@ trait Namers { self: Analyzer =>
mapOver(tp)
}
}
+
+ object treeTrans extends TypeMapTransformer {
+ override def transform(tree: Tree): Tree =
+ tree match {
+ case Ident(name) if (vparams contains tree.symbol) =>
+ val dtpe = debruijnFor(tree.symbol)
+ val dsym =
+ newLocalDummy(context.owner, tree.symbol.pos)
+ .newValue(tree.symbol.pos, name)
+
+ dsym.setFlag(PARAM)
+ dsym.setInfo(dtpe)
+ Ident(name).setSymbol(dsym).copyAttrs(tree).setType(dtpe)
+ case tree => super.transform(tree)
+ }
+ }
+
+ override def mapOver(arg: Tree) = Some(treeTrans.transform(arg))
}
val checkDependencies: TypeTraverser = new TypeTraverser {
diff --git a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala
index 1eae1b9389..5c7841651b 100644
--- a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala
@@ -424,7 +424,7 @@ abstract class RefChecks extends InfoTransform {
validateVariance(result, variance)
case ExistentialType(tparams, result) =>
validateVariance(result, variance)
- case AnnotatedType(attribs, tp) =>
+ case AnnotatedType(attribs, tp, selfsym) =>
validateVariance(tp, variance)
}
diff --git a/src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala b/src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala
index a501c22896..7cfd7ac461 100644
--- a/src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala
@@ -417,7 +417,7 @@ abstract class SuperAccessors extends transform.Transform with transform.TypingT
case SingleType(pref, _) => isThisType(pref)
case RefinedType(parents, defs) =>
parents.exists(isThisType(_))
- case AnnotatedType(attribs, tp) =>
+ case AnnotatedType(_, tp, _) =>
isThisType(tp)
case _ => false
}
diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
index 3f3669569d..2fdf3e561f 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
@@ -513,7 +513,7 @@ trait Typers { self: Analyzer =>
private def isNarrowable(tpe: Type): Boolean = tpe match {
case TypeRef(_, _, _) | RefinedType(_, _) => true
case ExistentialType(_, tpe1) => isNarrowable(tpe1)
- case AnnotatedType(_, tpe1) => isNarrowable(tpe1)
+ case AnnotatedType(_, tpe1, _) => isNarrowable(tpe1)
case PolyType(_, tpe1) => isNarrowable(tpe1)
case _ => !phase.erasedTypes
}
@@ -1776,7 +1776,13 @@ trait Typers { self: Analyzer =>
}
}
- def typedAnnotation(annot: Annotation): AnnotationInfo = {
+ def typedAnnotation(annot: Annotation): AnnotationInfo =
+ typedAnnotation(annot, EXPRmode)
+
+ def typedAnnotation(annot: Annotation, mode: Int): AnnotationInfo =
+ typedAnnotation(annot, NoSymbol, mode)
+
+ def typedAnnotation(annot: Annotation, selfsym: Symbol, mode: Int): AnnotationInfo = {
var attrError: Boolean = false
def error(pos: Position, msg: String): Null = {
context.error(pos, msg)
@@ -1787,9 +1793,34 @@ trait Typers { self: Analyzer =>
error(tr.pos, "attribute argument needs to be a constant; found: "+tr)
}
- typed(annot.constr, EXPRmode, AnnotationClass.tpe) match {
+ val typedConstr =
+ if (selfsym == NoSymbol)
+ typed(annot.constr, mode, AnnotationClass.tpe)
+ else {
+ // Since a selfsym is supplied, the annotation should have
+ // an extra "self" identifier in scope for type checking.
+ // This is implemented by wrapping the rhs
+ // in a function like "self => rhs" during type checking,
+ // and then stripping the "self =>" and substituting
+ // in the supplied selfsym.
+ val funcparm = ValDef(NoMods, nme.self, TypeTree(selfsym.info), EmptyTree)
+ val func = Function(List(funcparm), annot.constr)
+ val fun1clazz = FunctionClass(1)
+ val funcType = typeRef(fun1clazz.tpe.prefix,
+ fun1clazz,
+ List(selfsym.info, AnnotationClass.tpe))
+
+ typed (func, mode, funcType) match {
+ case t @ Function(List(arg), rhs) =>
+ val subs =
+ new TreeSymSubstituter(List(arg.symbol),List(selfsym))
+ subs(rhs)
+ }
+ }
+
+ typedConstr match {
case t @ Apply(Select(New(tpt), nme.CONSTRUCTOR), args) =>
- if (t.isErroneous) {
+ if ((t.tpe==null) || t.tpe.isErroneous) {
AnnotationInfo(ErrorType, List(), List())
}
else {
@@ -1797,10 +1828,10 @@ trait Typers { self: Analyzer =>
val needsConstant =
(!settings.Xplugtypes.value ||
- annType <:< ClassfileAnnotationClass.tpe)
+ (annType.typeSymbol isNonBottomSubClass ClassfileAnnotationClass))
def annotArg(tree: Tree): AnnotationArgument = {
- val arg = new AnnotationArgument(liftcode.reify(tree))
+ val arg = new AnnotationArgument(tree)
if(needsConstant && !arg.isConstant)
needConst(tree)
arg
@@ -1858,20 +1889,24 @@ trait Typers { self: Analyzer =>
* produce a set of fresh type parameters and a type so that it can be
* abstracted to an existential type.
* Every type symbol `T' in `rawSyms' is mapped to a clone.
- * Every term symbol `x' of type `T' in `rawSyms' is mapped to a type parameter
+ * Every term symbol `x' of type `T' in `rawSyms' is given an
+ * associated type symbol of the following form:
*
* type x.type <: T with <singleton>
*
* The name of the type parameter is `x.type', to produce nice diagnostics.
* The <singleton> parent ensures that the type parameter is still seen as a stable type.
- * The new symbols are substituted for the old ones in all type parameter infos
- * and in the returned type itself.
+ * Type symbols in rawSyms are fully replaced by the new symbols.
+ * Term symbols are also replaced, except when they are the term
+ * symbol of an Ident tree, in which case only the type of the
+ * Ident is changed.
*/
protected def existentialTransform(rawSyms: List[Symbol], tp: Type) = {
val typeParams: List[Symbol] = rawSyms map { sym =>
val name = if (sym.isType) sym.name else newTypeName(sym.name+".type")
val bound = existentialBound(sym)
- val quantified: Symbol = recycle(sym.owner.newAbstractType(sym.pos, name))
+ val quantified: Symbol =
+ recycle(sym.owner.newAbstractType(sym.pos, name))
trackSetInfo(quantified setFlag EXISTENTIAL)(bound.cloneInfo(quantified))
}
val typeParamTypes = typeParams map (_.tpe) // don't trackSetInfo here, since type already set!
@@ -1963,17 +1998,33 @@ trait Typers { self: Analyzer =>
}
}
}
- for (t <- tp) {
+ for (t <- tp) {
t match {
case ExistentialType(tparams, _) =>
boundSyms ++= tparams
+ case AnnotatedType(annots, _, _) =>
+ for (annot <- annots; arg <- annot.args; t <- arg.intTree) {
+ t match {
+ case Ident(_) =>
+ // Check the symbol of an Ident, unless the
+ // Ident's type is already over an existential.
+ // (If the type is already over an existential,
+ // then remap the type, not the core symbol.)
+ if (!t.tpe.typeSymbol.hasFlag(EXISTENTIAL))
+ addIfLocal(t.symbol, t.tpe)
+ case _ => ()
+ }
+ }
case _ =>
}
addIfLocal(t.termSymbol, t)
addIfLocal(t.typeSymbol, t)
}
}
- val substLocals = new TypeMap {
+
+ object substLocals extends TypeMap {
+ override val dropNonConstraintAnnotations = true
+
def apply(t: Type): Type = t match {
case TypeRef(_, sym, args) if (sym.isLocal && args.length > 0) =>
localInstances.get(new SymInstance(sym, t)) match {
@@ -1982,9 +2033,28 @@ trait Typers { self: Analyzer =>
}
case _ => mapOver(t)
}
+
+ override def mapOver(arg: Tree, giveup: ()=>Nothing) = {
+ object substLocalTrees extends TypeMapTransformer {
+ override def transform(tr: Tree) = {
+ localInstances.get(new SymInstance(tr.symbol, tr.tpe)) match {
+ case Some(local) =>
+ Ident(local.existentialToString)
+ .setSymbol(tr.symbol).copyAttrs(tr).setType(
+ typeRef(NoPrefix, local, List()))
+
+ case None => super.transform(tr)
+ }
+ }
+ }
+
+ substLocalTrees.transform(arg)
+ }
}
+
val normalizedTpe = normalizeLocals(tree.tpe)
addLocals(normalizedTpe)
+
packSymbols(localSyms.toList ::: localInstances.values.toList, substLocals(normalizedTpe))
}
@@ -2017,14 +2087,51 @@ trait Typers { self: Analyzer =>
}
def typedAnnotated(annot: Annotation, arg1: Tree): Tree = {
- def annotTypeTree(ainfo: AnnotationInfo): Tree =
- TypeTree(arg1.tpe.withAttribute(ainfo)) setOriginal tree
-
if (arg1.isType) {
- val annotInfo = typedAnnotation(annot)
- if (settings.Xplugtypes.value) annotTypeTree(annotInfo) else arg1
+ val selfsym =
+ if (!settings.selfInAnnots.value)
+ NoSymbol
+ else
+ arg1.tpe.selfsym match {
+ case NoSymbol =>
+ /* Implementation limitation: Currently this
+ * can cause cyclical reference errors even
+ * when the self symbol is not referenced at all.
+ * Surely at least some of these cases can be
+ * fixed by proper use of LazyType's. Lex tinkered
+ * on this but did not succeed, so is leaving
+ * it alone for now. Example code with the problem:
+ * class peer extends Annotation
+ * class NPE[T <: NPE[T] @peer]
+ *
+ * (Note: -Yself-in-annots must be on to see the problem)
+ **/
+ val sym =
+ newLocalDummy(context.owner, annot.pos)
+ .newValue(annot.pos, nme.self)
+ sym.setInfo(arg1.tpe.withoutAttributes)
+ sym
+ case sym => sym
+ }
+
+ val ainfo = typedAnnotation(annot, selfsym, mode)
+ val atype0 = arg1.tpe.withAttribute(ainfo)
+ val atype =
+ if ((selfsym != NoSymbol) && (ainfo.refsSymbol(selfsym)))
+ atype0.withSelfsym(selfsym)
+ else
+ atype0 // do not record selfsym if
+ // this annotation did not need it
+
+ if (settings.Xplugtypes.value && !ainfo.isErroneous)
+ TypeTree(atype) setOriginal tree
+ else
+ arg1
} else {
- val annotInfo = typedAnnotation(annot)
+ def annotTypeTree(ainfo: AnnotationInfo): Tree =
+ TypeTree(arg1.tpe.withAttribute(ainfo)) setOriginal tree
+
+ val annotInfo = typedAnnotation(annot, mode)
arg1 match {
case _: DefTree =>
@@ -3297,7 +3404,7 @@ trait Typers { self: Analyzer =>
getParts(tp.widen, s)
case RefinedType(ps, _) =>
for (p <- ps) getParts(p, s)
- case AnnotatedType(_, t) =>
+ case AnnotatedType(_, t, _) =>
getParts(t, s)
case _ =>
}
diff --git a/src/compiler/scala/tools/nsc/typechecker/Variances.scala b/src/compiler/scala/tools/nsc/typechecker/Variances.scala
index 35b63e6644..b5efa7035d 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Variances.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Variances.scala
@@ -83,7 +83,7 @@ trait Variances {
flip(varianceInSyms(tparams)(tparam)) & varianceInType(restpe)(tparam)
case ExistentialType(tparams, restpe) =>
varianceInSyms(tparams)(tparam) & varianceInType(restpe)(tparam)
- case AnnotatedType(attribs, tp) =>
+ case AnnotatedType(attribs, tp, _) =>
varianceInType(tp)(tparam)
}
}
diff --git a/src/compiler/scala/tools/nsc/util/RegexCache.scala b/src/compiler/scala/tools/nsc/util/RegexCache.scala
new file mode 100644
index 0000000000..5626a6e566
--- /dev/null
+++ b/src/compiler/scala/tools/nsc/util/RegexCache.scala
@@ -0,0 +1,40 @@
+/* NSC -- new Scala compiler
+ * Copyright 2005-2007 LAMP/EPFL
+ * @author Lex Spoon
+ */
+// $Id$
+
+package scala.tools.nsc.util
+import java.util.regex.Pattern
+import scala.collection.mutable
+
+object RegexCache {
+ /** Maps patterns to compiled regexes */
+ private val regexMap = mutable.Map.empty[String, Pattern]
+
+ /** Lists the regexes that have been recorded in order */
+ private val regexList = new mutable.Queue[String]
+
+ private val regexesToCache = 1000
+
+ /** Compile a regex and add it to the cache */
+ private def compileAndAdd(regex: String): Pattern = {
+ val pattern = Pattern.compile(regex)
+
+ regexMap += (regex -> pattern)
+ regexList += regex
+
+ if (regexMap.size > regexesToCache)
+ regexMap -= regexList.dequeue()
+
+ pattern
+ }
+
+
+ /** Compile a regex, caching */
+ def apply(regex: String): Pattern =
+ regexMap.get(regex) match {
+ case Some(pattern) => pattern
+ case None => compileAndAdd(regex)
+ }
+}
diff --git a/src/library/scala/TypeConstraint.scala b/src/library/scala/TypeConstraint.scala
new file mode 100644
index 0000000000..96347dc67f
--- /dev/null
+++ b/src/library/scala/TypeConstraint.scala
@@ -0,0 +1,30 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2006-2007, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+
+package scala
+
+/** <p>
+ * A marker for annotations that, when applied to a type,
+ * should be treated as a constraint on the annotated type.
+ * A proper constraint should restrict the type based only
+ * on information mentioned within the type. A Scala compiler
+ * can use this assumption to rewrite the contents of the
+ * constraint as necessary. To contrast, a type annotation
+ * whose meaning depends on the context where it is written
+ * down is not a proper constrained type, and this marker
+ * should not be applied. A Scala compiler will drop such
+ * annotations in cases where it would rewrite a type constraint.
+ * </p>
+ *
+ * @author Lex Spoon
+ * @version 1.1, 2007-11-5
+ */
+trait TypeConstraint extends Annotation
diff --git a/test/files/run/constrained-types.check b/test/files/run/constrained-types.check
new file mode 100644
index 0000000000..c8f0a83ad3
--- /dev/null
+++ b/test/files/run/constrained-types.check
@@ -0,0 +1,136 @@
+class Annot(obj: Any) extends Annotation with TypeConstraint
+defined class Annot
+
+-----
+class A {
+ val x = "hello"
+ val y: Int @Annot(x) = 10
+ override def toString = "an A"
+}
+defined class A
+
+-----
+val a = new A
+a: A = an A
+
+-----
+val y = a.y // should rewrite "this.x" to "a.x"
+y: Int @Annot(a.x) = 10
+
+-----
+var a2 = new A
+a2: A = an A
+
+-----
+val y2 = a2.y // should drop the annotation
+y2: Int = 10
+
+-----
+object Stuff {
+ val x = "hello"
+ val y : Int @Annot(x) = 10
+}
+defined module Stuff
+
+-----
+val y = Stuff.y // should rewrite the annotation
+y: Int @Annot(Stuff.x) = 10
+
+-----
+class B {
+ val y: Int @Annot(Stuff.x) = 10
+ override def toString = "a B"
+}
+defined class B
+
+-----
+val b = new B
+b: B = a B
+
+-----
+val y = b.y // should keep the annotation
+y: Int @Annot(Stuff.x) = 10
+
+-----
+def m(x: String): String @Annot(x) = x // m should be annotated with a debruijn
+m: (x$0:String)String @Annot(x)
+
+-----
+val three = "three"
+three: java.lang.String = three
+
+-----
+val three2 = m(three:three.type) // should change x to three
+three2: String @Annot(three) = three
+
+-----
+var four = "four"
+four: java.lang.String = four
+
+-----
+val four2 = m(four) // should have an existential bound
+four2: String @Annot(x) forSome { val x: java.lang.String } = four
+
+-----
+val four3 = four2 // should have the same type as four2
+four3: String @Annot(x) forSome { val x: java.lang.String } = four
+
+-----
+val stuff = m("stuff") // should not crash
+stuff: String @Annot("stuff") = stuff
+
+-----
+class peer extends Annotation // should not crash
+defined class peer
+
+-----
+class NPE[T <: NPE[T] @peer] // should not crash
+error: illegal cyclic reference involving class NPE
+
+-----
+def m = {
+ val x = "three"
+ val y : String @Annot(x) = x
+ y
+} // x should be existentially bound
+m: String @Annot(x) forSome { val x: java.lang.String }
+
+-----
+def n(y: String) = {
+ def m(x: String) : String @Annot(x) = {
+ (if (x == "")
+ m("default")
+ else
+ x)
+ }
+ m("stuff".stripMargin)
+} // x should be existentially bound
+n: (String)String @Annot(x) forSome { val x: String }
+
+-----
+class rep extends Annotation
+defined class rep
+
+-----
+object A { val x = "hello" : String @ rep }
+defined module A
+
+-----
+val y = a.x // should drop the annotation
+y: java.lang.String = hello
+
+-----
+val x = 3 : Int @Annot(e+f+g+h) //should have a graceful error message
+<console>:5: error: not found: value e
+ val x = 3 : Int @Annot(e+f+g+h) //should have a graceful error message
+ ^
+
+-----
+class Where(condition: Boolean) extends Annotation
+defined class Where
+
+-----
+val x : Int @Where(self > 0 && self < 100) = 3
+x: Int @Where(self.>(0).&&(self.<(100))) = 3
+
+-----
diff --git a/test/files/run/constrained-types.scala b/test/files/run/constrained-types.scala
new file mode 100644
index 0000000000..9a6d31cf6d
--- /dev/null
+++ b/test/files/run/constrained-types.scala
@@ -0,0 +1,103 @@
+/* Check on the processing of annotated types. Initially this tested
+ * asSeenFrom, but now it also tests packedType and the treatment
+ * of DeBruijn's . It runs the test using the interpreter so that
+ * the resulting annotated types can be printed out.
+ */
+import scala.tools.nsc._
+import java.io._
+import scala.Console
+
+object Test {
+
+ val testCode = List(
+ "class Annot(obj: Any) extends Annotation with TypeConstraint",
+
+ """class A {
+ | val x = "hello"
+ | val y: Int @Annot(x) = 10
+ | override def toString = "an A"
+ |} """,
+
+
+
+ "val a = new A",
+
+ """val y = a.y // should rewrite "this.x" to "a.x" """,
+
+
+ "var a2 = new A",
+ "val y2 = a2.y // should drop the annotation",
+
+
+ """object Stuff {
+ | val x = "hello"
+ | val y : Int @Annot(x) = 10
+ |}""",
+
+ "val y = Stuff.y // should rewrite the annotation",
+
+ """class B {
+ | val y: Int @Annot(Stuff.x) = 10
+ | override def toString = "a B"
+ |}""",
+
+ "val b = new B",
+ "val y = b.y // should keep the annotation",
+
+
+ "def m(x: String): String @Annot(x) = x // m should be annotated with a debruijn",
+ "val three = \"three\"",
+ "val three2 = m(three:three.type) // should change x to three",
+ "var four = \"four\"",
+ "val four2 = m(four) // should have an existential bound",
+ "val four3 = four2 // should have the same type as four2",
+
+ """val stuff = m("stuff") // should not crash""",
+
+ """class peer extends Annotation // should not crash""", // reported by Manfred Stock
+ """class NPE[T <: NPE[T] @peer] // should not crash""", // reported by Manfred Stock
+
+ """def m = {
+ | val x = "three"
+ | val y : String @Annot(x) = x
+ | y
+ |} // x should be existentially bound""",
+
+ """def n(y: String) = {
+ | def m(x: String) : String @Annot(x) = {
+ | (if (x == "")
+ | m("default")
+ | else
+ | x)
+ | }
+ | m("stuff".stripMargin)
+ |} // x should be existentially bound""",
+
+ "class rep extends Annotation",
+ """object A { val x = "hello" : String @ rep }""",
+ "val y = a.x // should drop the annotation",
+
+ "val x = 3 : Int @Annot(e+f+g+h) //should have a graceful error message",
+
+ "class Where(condition: Boolean) extends Annotation",
+ "val x : Int @Where(self > 0 && self < 100) = 3"
+ ).map(_.stripMargin)
+
+
+
+ def main(args: Array[String]) {
+ val settings = new Settings
+ settings.Xplugtypes.value = true
+ settings.Xexperimental.value = true
+ settings.selfInAnnots.value = true
+
+ val interp = new Interpreter(settings)
+
+ for (cmd <- testCode) {
+ println(cmd)
+ interp.interpret(cmd)
+ println()
+ println("-----")
+ }
+ }
+}