From 3bf0245b79dfaed2b011f7e85979278c896265d7 Mon Sep 17 00:00:00 2001 From: Lex Spoon Date: Sun, 1 Apr 2007 17:29:40 +0000 Subject: - annotations on types use lifted reflect trees... - annotations on types use lifted reflect trees instead of internal compiler trees - type annotations are pickled and unpickled in the class-file symbol tables - lifted code uses NoType in places it used to use null - type attributes propagate just a little bit further in the compiler than they used to (see changes to Type.scala) --- src/compiler/scala/tools/nsc/symtab/Types.scala | 8 +- .../tools/nsc/symtab/classfile/PickleBuffer.scala | 6 + .../tools/nsc/symtab/classfile/PickleFormat.scala | 64 ++++- .../scala/tools/nsc/symtab/classfile/Pickler.scala | 317 ++++++++++++++++++++- .../tools/nsc/symtab/classfile/UnPickler.scala | 220 +++++++++++++- .../scala/tools/nsc/transform/LiftCode.scala | 28 +- .../scala/tools/nsc/typechecker/Typers.scala | 2 +- 7 files changed, 616 insertions(+), 29 deletions(-) (limited to 'src') diff --git a/src/compiler/scala/tools/nsc/symtab/Types.scala b/src/compiler/scala/tools/nsc/symtab/Types.scala index 024d71b7e8..69853c37bc 100644 --- a/src/compiler/scala/tools/nsc/symtab/Types.scala +++ b/src/compiler/scala/tools/nsc/symtab/Types.scala @@ -1254,7 +1254,7 @@ trait Types requires SymbolTable { if(attributes.isEmpty) "" else - attributes.mkString("[", "] [", "] ") + attributes.mkString("", " ", "") attString + tp } @@ -1278,9 +1278,9 @@ trait Types requires SymbolTable { // ---------------- methods forwarded to tp ------------------ \\ override def symbol: Symbol = tp.symbol - override def singleDeref: Type = tp.singleDeref - override def widen: Type = tp.widen - override def deconst: Type = tp.deconst + override def singleDeref: Type = maybeRewrap(tp.singleDeref) + override def widen: Type = maybeRewrap(tp.widen) + override def deconst: Type = maybeRewrap(tp.deconst) override def bounds: TypeBounds = { val oftp = tp.bounds oftp match { diff --git a/src/compiler/scala/tools/nsc/symtab/classfile/PickleBuffer.scala b/src/compiler/scala/tools/nsc/symtab/classfile/PickleBuffer.scala index fb8a3a5ed8..6e85d606d4 100644 --- a/src/compiler/scala/tools/nsc/symtab/classfile/PickleBuffer.scala +++ b/src/compiler/scala/tools/nsc/symtab/classfile/PickleBuffer.scala @@ -123,6 +123,12 @@ class PickleBuffer(data: Array[byte], from: int, to: int) { def until[T](end: int, op: () => T): List[T] = if (readIndex == end) List() else op() :: until(end, op); + /** Perform operation op the number of + * times specified. Concatenate the results into a list. + */ + def times[T](n: int, op: ()=>T): List[T] = + if (n == 0) List() else op() :: times(n-1, op) + /** Create an index. * * @return ... diff --git a/src/compiler/scala/tools/nsc/symtab/classfile/PickleFormat.scala b/src/compiler/scala/tools/nsc/symtab/classfile/PickleFormat.scala index 5b26443932..86077f5852 100644 --- a/src/compiler/scala/tools/nsc/symtab/classfile/PickleFormat.scala +++ b/src/compiler/scala/tools/nsc/symtab/classfile/PickleFormat.scala @@ -102,15 +102,71 @@ object PickleFormat { final val LITERALstring = 33 final val LITERALnull = 34 final val LITERALclass = 35 - final val ATTRIBUTE = 40 + final val ATTRIBUTE = 40 // an attribute with constants 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 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 + + 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 firstSymTag = NONEsym final val lastSymTag = VALsym final val lastExtSymTag = EXTMODCLASSref - final val firstTypeTag = NOtpe - final val lastTypeTag = POLYtpe - final val PosOffset = 64 + + //The following two are no longer accurate, because ATTRIBUTEDtpe + //is not in the same range as the other types + //final val firstTypeTag = NOtpe + //final val lastTypeTag = POLYtpe + + final val PosOffset = 64 final val PosTYPEsym = PosOffset + TYPEsym final val PosALIASsym = PosOffset + ALIASsym final val PosCLASSsym = PosOffset + CLASSsym diff --git a/src/compiler/scala/tools/nsc/symtab/classfile/Pickler.scala b/src/compiler/scala/tools/nsc/symtab/classfile/Pickler.scala index c40cbba935..be95558b6b 100644 --- a/src/compiler/scala/tools/nsc/symtab/classfile/Pickler.scala +++ b/src/compiler/scala/tools/nsc/symtab/classfile/Pickler.scala @@ -123,6 +123,7 @@ abstract class Pickler extends SubComponent { private def putSymbols(syms: List[Symbol]) = syms foreach putSymbol + /** Store type and everythig it refers to in map index. * * @param tp ... @@ -150,14 +151,104 @@ abstract class Pickler extends SubComponent { case PolyType(tparams, restpe) => putType(restpe); putSymbols(tparams) case AnnotatedType(attribs, tp) => - putType(tp) // the attributes should be stored, but it is not yet - // decided how to handle that. + putType(tp); putAnnotations(attribs) case _ => - throw new FatalError("bad type: " + tp + "(" + tp.getClass() + ")") + throw new FatalError("bad type: " + tp + "(" + tp.getClass + ")") } } private def putTypes(tps: List[Type]): unit = tps foreach putType + private def putTree(tree: reflect.Tree): unit = if(putEntry(tree)) { + 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(val (t1,t2) <- typeBounds) { + putType(t1) + putType(t2) + } + putType(resultType) + case _ => + throw new FatalError("bad type: " + tpe + "(" + tpe.getClass + ")") + + } + } + 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 putRefSymbols(syms: List[reflect.Symbol]) = + syms foreach putSymbol + /** Store constant in map index. * * @param c ... @@ -180,6 +271,26 @@ abstract class Pickler extends SubComponent { for (val (name, c) <- attr.assocs) { putEntry(name); putConstant(c) } } + private def putAnnotation(annot: AnnotationInfo[Any]): unit = + if(putEntry(annot)) { + val AnnotationInfo(tpe, args, assocs) = annot + putType(tpe) + args foreach putTreeOrConstant + for (val (name, rhs) <- assocs) { putEntry(name); putTreeOrConstant(rhs) } + } + + private def putTreeOrConstant(x: Any) { + x match { + case c:Constant => putConstant(c) + case tree:reflect.Tree => putTree(tree) + case _ => + throw new FatalError("attribute neither tree nor constant: " + x) + } + } + + private def putAnnotations(annots: List[AnnotationInfo[Any]]): unit = + annots foreach putAnnotation + // Phase 2 methods: Write all entries to byte array ------------------------------ private val buf = new PickleBuffer(new Array[byte](4096), -1, 0) @@ -278,7 +389,9 @@ abstract class Pickler extends SubComponent { else if (c.tag == ClassTag) writeRef(c.typeValue) LITERAL + c.tag case AnnotatedType(attribs, tp) => - writeBody(tp) // obviously, this should be improved + writeRef(tp) + writeRefs(attribs) + ANNOTATEDtpe case (target: Symbol, attr @ AnnotationInfo(atp, args, assocs)) => writeRef(target) writeRef(atp) @@ -289,8 +402,202 @@ abstract class Pickler extends SubComponent { writeRef(target) for (val 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) + writeRef(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) + 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) + writeRef(impl) + REFLTREE + case reflect.DefDef(sym, vparamss, ret, rhs) => + writeNat(DEFDEFtree) + writeRef(sym) + writeRef(ret) + writeRef(rhs) + for(val vparams <- vparamss) { + writeNat(vparams.length) + writeRefs(vparams) + } + REFLTREE + case reflect.Super(psym) => + writeNat(SUPERtree) + writeRef(psym) + REFLTREE + case reflect.Template(parents, body) => + writeNat(TEMPLATEtree) + 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) + writeRef(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(val (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) + REFLSYM + case AnnotationInfo(target, args, assocs) => + writeRef(target) + writeNat(args.length) + for (val tree <- args) writeRef(tree.asInstanceOf[reflect.Tree]) + for (val (name, tree) <- assocs) { + writeRef(name); + writeRef(tree.asInstanceOf[reflect.Tree]) + } + ATTRIBTREE + case _ => - throw new FatalError("bad entry: " + entry + " " + entry.getClass())//debug + throw new FatalError("bad entry: " + entry + " " + entry.getClass) } val startpos = writeIndex writeByte(0); writeByte(0) diff --git a/src/compiler/scala/tools/nsc/symtab/classfile/UnPickler.scala b/src/compiler/scala/tools/nsc/symtab/classfile/UnPickler.scala index 70fcc5e7d7..136a69f126 100644 --- a/src/compiler/scala/tools/nsc/symtab/classfile/UnPickler.scala +++ b/src/compiler/scala/tools/nsc/symtab/classfile/UnPickler.scala @@ -254,6 +254,16 @@ abstract class UnPickler { case POLYtpe => val restpe = readTypeRef() PolyType(until(end, readSymbolRef), restpe) + case ANNOTATEDtpe => + val tp = readTypeRef() + val attribs = until(end, readTreeAttribRef) + if(global.settings.Xplugtypes.value) + AnnotatedType(attribs, tp) + else + tp // Drop the annotations unless -Xplugtypes. + // This way, people can distribute classfiles + // including annotated types without them much + // affecting those who disable -Xplugtypes case _ => errorBadSignature("bad type tag: " + tag) } @@ -302,11 +312,219 @@ abstract class UnPickler { null } - /** Read a reference to a name, symbol, type or constant */ + /** 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 */ + private def readTreeAttrib(): AnnotationInfo[reflect.Tree] = { + val tag = readByte() + if(tag != ATTRIBTREE) + errorBadSignature("tree-based annotation expected (" + tag + ")") + val end = readNat() + readIndex + + val target = readTypeRef() + val numargs = readNat() + val args = times(numargs, readReflTreeRef) + val assocs = + until(end, {() => + val name = readNameRef() + val tree = readReflTreeRef() + (name,tree)}) + AnnotationInfo(target, args, assocs) + } + + /* Read a reference to a pickled item */ private def readNameRef(): Name = at(readNat(), readName) private def readSymbolRef(): Symbol = at(readNat(), readSymbol) private def readTypeRef(): Type = at(readNat(), readType) private def readConstantRef(): Constant = at(readNat(), readConstant) + 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[reflect.Tree] = + at(readNat(), readTreeAttrib) private def errorBadSignature(msg: String) = throw new RuntimeException("malformed Scala signature of " + classRoot.name + " at " + readIndex + "; " + msg) diff --git a/src/compiler/scala/tools/nsc/transform/LiftCode.scala b/src/compiler/scala/tools/nsc/transform/LiftCode.scala index f5426083dd..df301eb159 100644 --- a/src/compiler/scala/tools/nsc/transform/LiftCode.scala +++ b/src/compiler/scala/tools/nsc/transform/LiftCode.scala @@ -183,40 +183,40 @@ abstract class LiftCode extends Transform { def reify(tp: Type): reflect.Type = tp match { case ErrorType => - if (_log_reify_type_) Console.println("cannot handle ErrorType"); null + if (_log_reify_type_) Console.println("cannot handle ErrorType"); reflect.NoType case WildcardType => - if (_log_reify_type_) Console.println("cannot handle WildcardType"); null + if (_log_reify_type_) Console.println("cannot handle WildcardType"); reflect.NoType case NoType => - if (_log_reify_type_) Console.println("cannot handle NoType"); null + if (_log_reify_type_) Console.println("cannot handle NoType"); reflect.NoType case NoPrefix => - if (_log_reify_type_) Console.println("cannot handle NoPrefix"); null + if (_log_reify_type_) Console.println("cannot handle NoPrefix"); reflect.NoType case ThisType(sym) => if (_log_reify_type_) Console.println("ThisType ("+sym+")") val rsym = reify(sym) - if (_log_reify_type_) Console.println("reified is "+rsym+" cannot handle ThisType "+tp); null + if (_log_reify_type_) Console.println("reified is "+rsym+" cannot handle ThisType "+tp); reflect.NoType case SingleType(pre, sym) => - if (_log_reify_type_) Console.println("cannot handle SingleType "+tp); null + if (_log_reify_type_) Console.println("cannot handle SingleType "+tp); reflect.NoType case ConstantType(value) => - if (_log_reify_type_) Console.println("cannot handle ConstantType("+value+") "+tp); null + if (_log_reify_type_) Console.println("cannot handle ConstantType("+value+") "+tp); reflect.NoType case TypeRef(pre, sym, args) => if (_log_reify_type_) Console.println("TypeRef! try to handle prefix") val rpre = reify(pre) - if (_log_reify_type_) Console.println("cannot handle TypeRef("+pre+","+sym+","+args+") == "+tp+")"); null + if (_log_reify_type_) Console.println("cannot handle TypeRef("+pre+","+sym+","+args+") == "+tp+")"); reflect.NoType case TypeBounds(lo, hi) => - if (_log_reify_type_) Console.println("cannot handle TypeBounds "+tp); null + if (_log_reify_type_) Console.println("cannot handle TypeBounds "+tp); reflect.NoType case RefinedType(parents, defs) => - if (_log_reify_type_) Console.println("cannot handle RefinedType "+tp); null + if (_log_reify_type_) Console.println("cannot handle RefinedType "+tp); reflect.NoType case ClassInfoType(parents, defs, clazz) => - if (_log_reify_type_) Console.println("cannot handle ClassInfoType "+tp); null + if (_log_reify_type_) Console.println("cannot handle ClassInfoType "+tp); reflect.NoType case MethodType(paramtypes, result) => - if (_log_reify_type_) Console.println("cannot handle MethodType "+tp); null + if (_log_reify_type_) Console.println("cannot handle MethodType "+tp); reflect.NoType case PolyType(tparams, result) => - if (_log_reify_type_) Console.println("cannot handle PolyType "+tp); null; + if (_log_reify_type_) Console.println("cannot handle PolyType "+tp); reflect.NoType case AnnotatedType(attribs, tp) => reify(tp) case _ => - null + reflect.NoType } } diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala index 630a5253ef..084ed5df2e 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala @@ -2023,7 +2023,7 @@ trait Typers requires Analyzer { def annotTypeTree(ainfo: AnnotationInfo[Any]): Tree = TypeTree(arg1.tpe.withAttribute(ainfo)) setOriginal tree if (arg1.isType) { - val annotInfo = typedAnnotation(annot, identity[Tree]) + val annotInfo = typedAnnotation(annot, liftcode.reify) if (settings.Xplugtypes.value) annotTypeTree(annotInfo) else arg1 } else { val annotInfo = typedAnnotation(annot, getConstant) -- cgit v1.2.3