diff options
author | Lex Spoon <lex@lexspoon.org> | 2007-11-28 05:17:14 +0000 |
---|---|---|
committer | Lex Spoon <lex@lexspoon.org> | 2007-11-28 05:17:14 +0000 |
commit | dfda38550a2d48662fde917d26dfb8e2d6c64eee (patch) | |
tree | 0a444d414e55ef39cbb184de63ef8505a070bce5 /src | |
parent | 8c9e9f7b7d1de79b104d954035613e51e0acaaf2 (diff) | |
download | scala-dfda38550a2d48662fde917d26dfb8e2d6c64eee.tar.gz scala-dfda38550a2d48662fde917d26dfb8e2d6c64eee.tar.bz2 scala-dfda38550a2d48662fde917d26dfb8e2d6c64eee.zip |
Merge from the annots-normtrees branch.
now use compiler trees instead of reflect trees.
In many cases, annotations on types can be rewritten
instead of discarded as the types undergo various
operations. Also, -Yself-in-annots has been added.
Diffstat (limited to 'src')
30 files changed, 1935 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 |