aboutsummaryrefslogtreecommitdiff
path: root/src/dotty/tools/dotc/core
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2015-03-04 14:39:13 +0100
committerDmitry Petrashko <dmitry.petrashko@gmail.com>2015-03-18 11:14:14 +0100
commita4b2a67fa5d58f7dbd34b8876e8a87e309524e22 (patch)
tree66c721ac1d151b0c3b640dffb56f647ebf727f4f /src/dotty/tools/dotc/core
parent96fbd7bfe252026f59d1f5e8aa33f2d8fae65769 (diff)
downloaddotty-a4b2a67fa5d58f7dbd34b8876e8a87e309524e22.tar.gz
dotty-a4b2a67fa5d58f7dbd34b8876e8a87e309524e22.tar.bz2
dotty-a4b2a67fa5d58f7dbd34b8876e8a87e309524e22.zip
Changes to Tasty format
Use fewer length fields in type encodings. - create new category of tags that take exactly one argument tree. - avoid using length where a tag fits in one of theopther categories.
Diffstat (limited to 'src/dotty/tools/dotc/core')
-rw-r--r--src/dotty/tools/dotc/core/TypeErasure.scala418
-rw-r--r--src/dotty/tools/dotc/core/pickling/PickleFormat.scala105
-rw-r--r--src/dotty/tools/dotc/core/pickling/TastyPrinter.scala10
-rw-r--r--src/dotty/tools/dotc/core/pickling/TreePickler.scala22
-rw-r--r--src/dotty/tools/dotc/core/pickling/TreeUnpickler.scala17
5 files changed, 492 insertions, 80 deletions
diff --git a/src/dotty/tools/dotc/core/TypeErasure.scala b/src/dotty/tools/dotc/core/TypeErasure.scala
new file mode 100644
index 000000000..a45e29287
--- /dev/null
+++ b/src/dotty/tools/dotc/core/TypeErasure.scala
@@ -0,0 +1,418 @@
+package dotty.tools
+package dotc
+package core
+
+import Symbols._, Types._, Contexts._, Flags._, Names._, StdNames._, Decorators._, Flags.JavaDefined
+import dotc.transform.ExplicitOuter._
+import typer.Mode
+import util.DotClass
+
+/** Erased types are:
+ *
+ * TypeRef(prefix is ignored, denot is ClassDenotation)
+ * TermRef(prefix is ignored, denot is SymDenotation)
+ * JavaArrayType
+ * AnnotatedType
+ * MethodType
+ * ThisType
+ * SuperType
+ * ClassInfo (NoPrefix, ...)
+ * NoType
+ * NoPrefix
+ * WildcardType
+ * ErrorType
+ *
+ * only for isInstanceOf, asInstanceOf: PolyType, PolyParam, TypeBounds
+ *
+ */
+object TypeErasure {
+
+ /** A predicate that tests whether a type is a legal erased type. Only asInstanceOf and
+ * isInstanceOf may have types that do not satisfy the predicate.
+ */
+ def isErasedType(tp: Type)(implicit ctx: Context): Boolean = tp match {
+ case tp: TypeRef =>
+ tp.symbol.isClass && tp.symbol != defn.AnyClass
+ case _: TermRef =>
+ true
+ case JavaArrayType(elem) =>
+ isErasedType(elem)
+ case AnnotatedType(_, tp) =>
+ isErasedType(tp)
+ case ThisType(tref) =>
+ isErasedType(tref)
+ case tp: MethodType =>
+ tp.paramTypes.forall(isErasedType) && isErasedType(tp.resultType)
+ case tp @ ClassInfo(pre, _, parents, decls, _) =>
+ isErasedType(pre) && parents.forall(isErasedType) //&& decls.forall(sym => isErasedType(sym.info)) && isErasedType(tp.selfType)
+ case NoType | NoPrefix | WildcardType | ErrorType | SuperType(_, _) =>
+ true
+ case _ =>
+ false
+ }
+
+ case class ErasedValueType(cls: ClassSymbol, underlying: Type) extends CachedGroundType {
+ override def computeHash = doHash(cls, underlying)
+ }
+
+ private def erasureIdx(isJava: Boolean, isSemi: Boolean, isConstructor: Boolean, wildcardOK: Boolean) =
+ (if (isJava) 1 else 0) +
+ (if (isSemi) 2 else 0) +
+ (if (isConstructor) 4 else 0) +
+ (if (wildcardOK) 8 else 0)
+
+ private val erasures = new Array[TypeErasure](16)
+
+ for {
+ isJava <- List(false, true)
+ isSemi <- List(false, true)
+ isConstructor <- List(false, true)
+ wildcardOK <- List(false, true)
+ } erasures(erasureIdx(isJava, isSemi, isConstructor, wildcardOK)) =
+ new TypeErasure(isJava, isSemi, isConstructor, wildcardOK)
+
+ /** Produces an erasure function.
+ * @param isJava Arguments should be treated the way Java does it
+ * @param isSemi Value classes are mapped in an intermediate step to
+ * ErasedValueClass types, instead of going directly to
+ * the erasure of the underlying type.
+ * @param isConstructor Argument forms part of the type of a constructor
+ * @param wildcardOK Wildcards are acceptable (true when using the erasure
+ * for computing a signature name).
+ */
+ private def erasureFn(isJava: Boolean, isSemi: Boolean, isConstructor: Boolean, wildcardOK: Boolean): TypeErasure =
+ erasures(erasureIdx(isJava, isSemi, isConstructor, wildcardOK))
+
+ private val scalaErasureFn = erasureFn(isJava = false, isSemi = false, isConstructor = false, wildcardOK = false)
+ private val scalaSigFn = erasureFn(isJava = false, isSemi = false, isConstructor = false, wildcardOK = true)
+ private val javaSigFn = erasureFn(isJava = true, isSemi = false, isConstructor = false, wildcardOK = true)
+ private val semiErasureFn = erasureFn(isJava = false, isSemi = true, isConstructor = false, wildcardOK = false)
+
+ /** The current context with a phase no later than erasure */
+ private def erasureCtx(implicit ctx: Context) =
+ if (ctx.erasedTypes) ctx.withPhase(ctx.erasurePhase).addMode(Mode.FutureDefsOK) else ctx
+
+ def erasure(tp: Type)(implicit ctx: Context): Type = scalaErasureFn(tp)(erasureCtx)
+ def semiErasure(tp: Type)(implicit ctx: Context): Type = semiErasureFn(tp)(erasureCtx)
+ def sigName(tp: Type, isJava: Boolean)(implicit ctx: Context): TypeName = {
+ val seqClass = if(isJava) defn.ArrayClass else defn.SeqClass
+ val normTp =
+ if (tp.isRepeatedParam) tp.translateParameterized(defn.RepeatedParamClass, seqClass)
+ else tp
+ (if (isJava) javaSigFn else scalaSigFn).sigName(normTp)(erasureCtx)
+ }
+
+ /** The erasure of a top-level reference. Differs from normal erasure in that
+ * TermRefs are kept instead of being widened away.
+ */
+ def erasedRef(tp: Type)(implicit ctx: Context): Type = tp match {
+ case tp: TermRef =>
+ assert(tp.symbol.exists, tp)
+ val tp1 = ctx.makePackageObjPrefixExplicit(tp)
+ if (tp1 ne tp) erasedRef(tp1)
+ else TermRef(erasedRef(tp.prefix), tp.symbol.asTerm)
+ case tp: ThisType =>
+ tp
+ case tp =>
+ erasure(tp)
+ }
+
+ /** The erasure of a symbol's info. This is different of `erasure` in the way `ExprType`s are
+ * treated. `eraseInfo` maps them them to nullary method types, whereas `erasure` maps them
+ * to `Function0`.
+ */
+ def eraseInfo(tp: Type, sym: Symbol)(implicit ctx: Context): Type =
+ scalaErasureFn.eraseInfo(tp, sym)(erasureCtx)
+
+ /** The erasure of a function result type. Differs from normal erasure in that
+ * Unit is kept instead of being mapped to BoxedUnit.
+ */
+ def eraseResult(tp: Type)(implicit ctx: Context): Type =
+ scalaErasureFn.eraseResult(tp)(erasureCtx)
+
+ /** The symbol's erased info. This is the type's erasure, except for the following symbols:
+ *
+ * - For $asInstanceOf : [T]T
+ * - For $isInstanceOf : [T]Boolean
+ * - For all abstract types : = ?
+ * - For all other symbols : the semi-erasure of their types, with
+ * isJava, isConstructor set according to symbol.
+ */
+ def transformInfo(sym: Symbol, tp: Type)(implicit ctx: Context): Type = {
+ val erase = erasureFn(sym is JavaDefined, isSemi = true, sym.isConstructor, wildcardOK = false)
+
+ def eraseParamBounds(tp: PolyType): Type =
+ tp.derivedPolyType(
+ tp.paramNames, tp.paramNames map (Function.const(TypeBounds.upper(defn.ObjectType))), tp.resultType)
+
+ if (defn.isPolymorphicAfterErasure(sym)) eraseParamBounds(sym.info.asInstanceOf[PolyType])
+ else if (sym.isAbstractType) TypeAlias(WildcardType)
+ else if (sym.isConstructor) outer.addParam(sym.owner.asClass, erase(tp)(erasureCtx))
+ else eraseInfo(tp, sym)(erasureCtx) match {
+ case einfo: MethodType if sym.isGetter && einfo.resultType.isRef(defn.UnitClass) =>
+ defn.BoxedUnitClass.typeRef
+ case einfo =>
+ einfo
+ }
+ }
+
+ /** Is `tp` an abstract type or polymorphic type parameter that has `Any`
+ * as upper bound and that is not Java defined? Arrays of such types are
+ * erased to `Object` instead of `ObjectArray`.
+ */
+ def isUnboundedGeneric(tp: Type)(implicit ctx: Context): Boolean = tp.dealias match {
+ case tp: TypeRef =>
+ !tp.symbol.isClass &&
+ !tp.derivesFrom(defn.ObjectClass) &&
+ !tp.symbol.is(JavaDefined)
+ case tp: PolyParam =>
+ !tp.derivesFrom(defn.ObjectClass) &&
+ !tp.binder.resultType.isInstanceOf[JavaMethodType]
+ case tp: TypeProxy => isUnboundedGeneric(tp.underlying)
+ case tp: AndType => isUnboundedGeneric(tp.tp1) || isUnboundedGeneric(tp.tp2)
+ case tp: OrType => isUnboundedGeneric(tp.tp1) && isUnboundedGeneric(tp.tp2)
+ case _ => false
+ }
+
+
+ /** The erased least upper bound is computed as follows
+ * - if both argument are arrays, an array of the lub of the element types
+ * - if one argument is an array, Object
+ * - otherwise a common superclass or trait S of the argument classes, with the
+ * following two properties:
+ * S is minimal: no other common superclass or trait derives from S]
+ * S is last : in the linearization of the first argument type `tp1`
+ * there are no minimal common superclasses or traits that
+ * come after S.
+ * (the reason to pick last is that we prefer classes over traits that way).
+ */
+ def erasedLub(tp1: Type, tp2: Type)(implicit ctx: Context): Type = tp1 match {
+ case JavaArrayType(elem1) =>
+ tp2 match {
+ case JavaArrayType(elem2) => JavaArrayType(erasedLub(elem1, elem2))
+ case _ => defn.ObjectType
+ }
+ case _ =>
+ tp2 match {
+ case JavaArrayType(_) => defn.ObjectType
+ case _ =>
+ val cls2 = tp2.classSymbol
+ def loop(bcs: List[ClassSymbol], bestSoFar: ClassSymbol): ClassSymbol = bcs match {
+ case bc :: bcs1 =>
+ if (cls2.derivesFrom(bc))
+ if (!bc.is(Trait) && bc != defn.AnyClass) bc
+ else loop(bcs1, if (bestSoFar.derivesFrom(bc)) bestSoFar else bc)
+ else
+ loop(bcs1, bestSoFar)
+ case nil =>
+ bestSoFar
+ }
+ loop(tp1.baseClasses, defn.ObjectClass).typeRef
+ }
+ }
+
+ /** The erased greatest lower bound picks one of the two argument types. It prefers, in this order:
+ * - arrays over non-arrays
+ * - subtypes over supertypes, unless isJava is set
+ * - real classes over traits
+ */
+ def erasedGlb(tp1: Type, tp2: Type, isJava: Boolean)(implicit ctx: Context): Type = tp1 match {
+ case JavaArrayType(elem1) =>
+ tp2 match {
+ case JavaArrayType(elem2) => JavaArrayType(erasedGlb(elem1, elem2, isJava))
+ case _ => tp1
+ }
+ case _ =>
+ tp2 match {
+ case JavaArrayType(_) => tp2
+ case _ =>
+ val tsym1 = tp1.typeSymbol
+ val tsym2 = tp2.typeSymbol
+ if (!tsym2.exists) tp1
+ else if (!tsym1.exists) tp2
+ else if (!isJava && tsym1.derivesFrom(tsym2)) tp1
+ else if (!isJava && tsym2.derivesFrom(tsym1)) tp2
+ else if (tp1.typeSymbol.isRealClass) tp1
+ else if (tp2.typeSymbol.isRealClass) tp2
+ else tp1
+ }
+ }
+}
+import TypeErasure._
+
+/**
+ * This is used as the Scala erasure during the erasure phase itself
+ * It differs from normal erasure in that value classes are erased to ErasedValueTypes which
+ * are then later converted to the underlying parameter type in phase posterasure.
+ *
+ */
+class TypeErasure(isJava: Boolean, isSemi: Boolean, isConstructor: Boolean, wildcardOK: Boolean) extends DotClass {
+
+ /** The erasure |T| of a type T. This is:
+ *
+ * - For a refined type scala.Array+[T]:
+ * - if T is Nothing or Null, []Object
+ * - otherwise, if T <: Object, []|T|
+ * - otherwise, if T is a type paramter coming from Java, []Object
+ * - otherwise, Object
+ * - For a term ref p.x, the type <noprefix> # x.
+ * - For a typeref scala.Any, scala.AnyVal or scala.Singleton: |java.lang.Object|
+ * - For a typeref scala.Unit, |scala.runtime.BoxedUnit|.
+ * - For a typeref P.C where C refers to a class, <noprefix> # C.
+ * - For a typeref P.C where C refers to an alias type, the erasure of C's alias.
+ * - For a typeref P.C where C refers to an abstract type, the erasure of C's upper bound.
+ * - For a this-type C.this, the type itself.
+ * - For all other type proxies: The erasure of the underlying type.
+ * - For T1 & T2, the erased glb of |T1| and |T2| (see erasedGlb)
+ * - For T1 | T2, the first base class in the linearization of T which is also a base class of T2
+ * - For => T, ()T
+ * - For a method type (Fs)scala.Unit, (|Fs|)scala.Unit.
+ * - For any other uncurried method type (Fs)T, (|Fs|)|T|.
+ * - For a curried method type (Fs1)(Fs2)T, (|Fs1|,Es2)ET where (Es2)ET = |(Fs2)T|.
+ * - For a polymorphic type [Ts](Ps)T, |(Ps)T|
+ * _ For a polymorphic type [Ts]T where T is not a method type, ()|T|
+ * - For the class info type of java.lang.Object, the same type without any parents.
+ * - For a class info type of a value class, the same type without any parents.
+ * - For any other class info type with parents Ps, the same type with
+ * parents |Ps|, but with duplicate references of Object removed.
+ * - For NoType or NoPrefix, the type itself.
+ * - For any other type, exception.
+ */
+ private def apply(tp: Type)(implicit ctx: Context): Type = tp match {
+ case tp: TypeRef =>
+ val sym = tp.symbol
+ if (!sym.isClass) this(tp.info)
+ else if (sym.isDerivedValueClass) eraseDerivedValueClassRef(tp)
+ else eraseNormalClassRef(tp)
+ case tp: RefinedType =>
+ val parent = tp.parent
+ if (parent isRef defn.ArrayClass) eraseArray(tp)
+ else this(parent)
+ case tp: TermRef =>
+ this(tp.widen)
+ case tp: ThisType =>
+ this(tp.cls.typeRef)
+ case SuperType(thistpe, supertpe) =>
+ SuperType(this(thistpe), this(supertpe))
+ case ExprType(rt) =>
+ defn.FunctionClass(0).typeRef
+ case tp: TypeProxy =>
+ this(tp.underlying)
+ case AndType(tp1, tp2) =>
+ erasedGlb(this(tp1), this(tp2), isJava)
+ case OrType(tp1, tp2) =>
+ ctx.typeComparer.orType(this(tp1), this(tp2), erased = true)
+ case tp: MethodType =>
+ val paramErasure = erasureFn(tp.isJava, isSemi, isConstructor, wildcardOK)(_)
+ val formals = tp.paramTypes.mapConserve(paramErasure)
+ eraseResult(tp.resultType) match {
+ case rt: MethodType =>
+ tp.derivedMethodType(tp.paramNames ++ rt.paramNames, formals ++ rt.paramTypes, rt.resultType)
+ case rt =>
+ tp.derivedMethodType(tp.paramNames, formals, rt)
+ }
+ case tp: PolyType =>
+ this(tp.resultType) match {
+ case rt: MethodType => rt
+ case rt => MethodType(Nil, Nil, rt)
+ }
+ case tp @ ClassInfo(pre, cls, classParents, decls, _) =>
+ if (cls is Package) tp
+ else {
+ def eraseTypeRef(p: TypeRef) = this(p).asInstanceOf[TypeRef]
+ val parents: List[TypeRef] =
+ if ((cls eq defn.ObjectClass) || cls.isPrimitiveValueClass) Nil
+ else classParents.mapConserve(eraseTypeRef) match {
+ case tr :: trs1 =>
+ assert(!tr.classSymbol.is(Trait), cls)
+ val tr1 = if (cls is Trait) defn.ObjectClass.typeRef else tr
+ tr1 :: trs1.filterNot(_ isRef defn.ObjectClass)
+ case nil => nil
+ }
+ val erasedDecls = decls.filteredScope(d => !d.isType || d.isClass)
+ tp.derivedClassInfo(NoPrefix, parents, erasedDecls, erasedRef(tp.selfType))
+ // can't replace selftype by NoType because this would lose the sourceModule link
+ }
+ case NoType | NoPrefix | ErrorType | JavaArrayType(_) =>
+ tp
+ case tp: WildcardType if wildcardOK =>
+ tp
+ }
+
+ private def eraseArray(tp: RefinedType)(implicit ctx: Context) = {
+ val defn.ArrayType(elemtp) = tp
+ if (elemtp derivesFrom defn.NullClass) JavaArrayType(defn.ObjectType)
+ else if (isUnboundedGeneric(elemtp)) defn.ObjectType
+ else JavaArrayType(this(elemtp))
+ }
+
+ def eraseInfo(tp: Type, sym: Symbol)(implicit ctx: Context) = tp match {
+ case ExprType(rt) =>
+ if (sym is Param) apply(tp)
+ // Note that params with ExprTypes are eliminated by ElimByName,
+ // but potentially re-introduced by ResolveSuper, when we add
+ // forwarders to mixin methods.
+ // See doc comment for ElimByName for speculation how we could improve this.
+ else MethodType(Nil, Nil, eraseResult(rt))
+ case tp => erasure(tp)
+ }
+
+ private def eraseDerivedValueClassRef(tref: TypeRef)(implicit ctx: Context): Type =
+ unsupported("eraseDerivedValueClass")
+
+ private def eraseNormalClassRef(tref: TypeRef)(implicit ctx: Context): Type = {
+ val cls = tref.symbol.asClass
+ (if (cls.owner is Package) normalizeClass(cls) else cls).typeRef
+ }
+
+ private def eraseResult(tp: Type)(implicit ctx: Context): Type = tp match {
+ case tp: TypeRef =>
+ val sym = tp.typeSymbol
+ if (sym eq defn.UnitClass) sym.typeRef
+ else if (sym.isDerivedValueClass) eraseNormalClassRef(tp)
+ else this(tp)
+ case RefinedType(parent, _) if !(parent isRef defn.ArrayClass) =>
+ eraseResult(parent)
+ case _ =>
+ this(tp)
+ }
+
+ private def normalizeClass(cls: ClassSymbol)(implicit ctx: Context): ClassSymbol = {
+ if (cls.owner == defn.ScalaPackageClass) {
+ if (cls == defn.AnyClass || cls == defn.AnyValClass || cls == defn.SingletonClass)
+ return defn.ObjectClass
+ if (cls == defn.UnitClass)
+ return defn.BoxedUnitClass
+ }
+ cls
+ }
+
+ /** The name of the type as it is used in `Signature`s.
+ * Need to ensure correspondence with erasure!
+ */
+ private def sigName(tp: Type)(implicit ctx: Context): TypeName = tp match {
+ case tp: TypeRef =>
+ val sym = tp.symbol
+ if (!sym.isClass) sigName(tp.info)
+ else if (sym.isDerivedValueClass) sigName(eraseDerivedValueClassRef(tp))
+ else normalizeClass(sym.asClass).fullName.asTypeName
+ case defn.ArrayType(elem) =>
+ sigName(this(tp))
+ case JavaArrayType(elem) =>
+ sigName(elem) ++ "[]"
+ case tp: TermRef =>
+ sigName(tp.widen)
+ case ExprType(rt) =>
+ sigName(defn.FunctionType(Nil, rt))
+ case tp: TypeProxy =>
+ sigName(tp.underlying)
+ case ErrorType | WildcardType =>
+ tpnme.WILDCARD
+ case tp: WildcardType =>
+ sigName(tp.optBounds)
+ case _ =>
+ val erased = this(tp)
+ assert(erased ne tp, tp)
+ sigName(erased)
+ }
+}
diff --git a/src/dotty/tools/dotc/core/pickling/PickleFormat.scala b/src/dotty/tools/dotc/core/pickling/PickleFormat.scala
index 1a79ad08e..3338c355e 100644
--- a/src/dotty/tools/dotc/core/pickling/PickleFormat.scala
+++ b/src/dotty/tools/dotc/core/pickling/PickleFormat.scala
@@ -55,7 +55,7 @@ Standard-Section: "ASTs" TopLevelStat*
Modifier*
TYPEDEF Length NameRef (Type | Template) Modifier*
IMPORT Length qual_Term Selector*
- Selector = IMPORTED Length name_NameRef
+ Selector = IMPORTED name_NameRef
RENAMED Length from_NameRef to_NameRef
// Imports are for scala.meta, they are not used in the backend
@@ -65,14 +65,14 @@ Standard-Section: "ASTs" TopLevelStat*
Template = TEMPLATE Length TypeParam* Param* Parent* Self? Stat* // Stat* always starts with the primary constructor.
Parent = Application
Type
- Self = SELFDEF Length selfName_NameRef selfType_Type
+ Self = SELFDEF selfName_NameRef selfType_Type
Term = Path
Application
IDENT NameRef Type // used when ident’s type is not a TermRef
SELECT possiblySigned_NameRef qual_Term
+ NEW cls_Type
SUPER Length this_Term mixinTrait_Type?
- NEW Length cls_Type
PAIR Length left_Term right_Term
TYPED Length expr_Term ascription_Type
NAMEDARG Length paramName_NameRef arg_Term
@@ -94,7 +94,7 @@ Standard-Section: "ASTs" TopLevelStat*
TYPEAPPLY Length fn_Term arg_Type*
CaseDef = CASEDEF Length pat_Term rhs_Tree guard_Tree?
- ImplicitArg = IMPLICITARG Length arg_Term
+ ImplicitArg = IMPLICITARG arg_Term
ASTRef = Nat // byte position in AST payload
Path = Constant
@@ -102,7 +102,7 @@ Standard-Section: "ASTs" TopLevelStat*
TERMREFsymbol sym_ASTRef qual_Type
TERMREFpkg fullyQualified_NameRef
TERMREF possiblySigned_NameRef qual_Type
- THIS Length clsRef_Type
+ THIS clsRef_Type
SKOLEMtype refinedType_ASTRef
SHARED path_ASTRef
@@ -119,8 +119,8 @@ Standard-Section: "ASTs" TopLevelStat*
DOUBLEconst LongInt
STRINGconst NameRef
NULLconst
- CLASSconst Length Type
- ENUMconst Length Path
+ CLASSconst Type
+ ENUMconst Path
Type = Path
TYPEREFdirect sym_ASTRef
@@ -147,10 +147,10 @@ Standard-Section: "ASTs" TopLevelStat*
NameType = paramName_NameRef typeOrBounds_ASTRef
Modifier = PRIVATE
- INTERNAL // package private
+ INTERNAL // package private
PROTECTED
- PRIVATEqualified Length qualifier_Type // will be dropped
- PROTECTEDqualified Length qualifier_Type // will be dropped
+ PRIVATEqualified qualifier_Type // will be dropped
+ PROTECTEDqualified qualifier_Type // will be dropped
ABSTRACT
FINAL
SEALED
@@ -158,33 +158,34 @@ Standard-Section: "ASTs" TopLevelStat*
IMPLICIT
LAZY
OVERRIDE
- INLINE // macro
- ABSOVERRIDE // abstract override
- STATIC // mapped to static Java member
- MODULE // an object or its class
- TRAIT // a trait
- LOCAL // private[this] or protected[this]
- SYNTHETIC // generated by Scala compiler
- ARTIFACT // to be tagged Java Synthetic
- MUTABLE // a var
- LABEL // method generated as a label
- FIELDaccessor // getter or setter
- CASEaccessor // getter for case class param
- COVARIANT // type param marked “+”
- CONTRAVARIANT // type param marked “-”
- SCALA2X // Imported from Scala2.x
- DEFAULTparameterized // Method with default params
- DEFAULTinit // variable with “_” initializer
- INSUPERCALL // defined in the argument of a constructor supercall
+ INLINE // macro
+ ABSOVERRIDE // abstract override
+ STATIC // mapped to static Java member
+ MODULE // an object or its class
+ TRAIT // a trait
+ LOCAL // private[this] or protected[this]
+ SYNTHETIC // generated by Scala compiler
+ ARTIFACT // to be tagged Java Synthetic
+ MUTABLE // a var
+ LABEL // method generated as a label
+ FIELDaccessor // getter or setter
+ CASEaccessor // getter for case class param
+ COVARIANT // type param marked “+”
+ CONTRAVARIANT // type param marked “-”
+ SCALA2X // Imported from Scala2.x
+ DEFAULTparameterized // Method with default params
+ DEFAULTinit // variable with “_” initializer
+ INSUPERCALL // defined in the argument of a constructor supercall
Annotation
- Annotation = ANNOTATION Length tycon_Symbol fullAnnotation_Term
+ Annotation = ANNOTATION Length tycon_Type fullAnnotation_Term
-Note: Tree tags are grouped into 4 categories that determine what follows, and thus allow to compute the size of the tagged tree in a generic way.
+Note: Tree tags are grouped into 5 categories that determine what follows, and thus allow to compute the size of the tagged tree in a generic way.
- Category 1 (tags 0-63) : tag
- Category 2 (tags 64-99) : tag Nat
- Category 3 (tags 100-127): tag Nat AST
- Category 4 (tags 128-255): tag Length <payload>
+ Category 1 (tags 0-63) : tag
+ Category 2 (tags 64-95) : tag Nat
+ Category 3 (tags 96-111) : tag AST
+ Category 4 (tags 112-127): tag Nat AST
+ Category 5 (tags 128-255): tag Length <payload>
Standard Section: "Positions" sourceLength_Nat Assoc*
@@ -271,13 +272,23 @@ object PickleFormat {
final val FLOATconst = 75
final val DOUBLEconst = 76
final val STRINGconst = 77
-
- final val IDENT = 100
- final val SELECT = 101
- final val TERMREFsymbol = 102
- final val TERMREF = 103
- final val TYPEREFsymbol = 104
- final val TYPEREF = 105
+ final val IMPORTED = 78
+
+ final val THIS = 96
+ final val CLASSconst = 97
+ final val ENUMconst = 98
+ final val NEW = 99
+ final val IMPLICITarg = 100
+ final val PRIVATEqualified = 101
+ final val PROTECTEDqualified = 102
+
+ final val IDENT = 112
+ final val SELECT = 113
+ final val TERMREFsymbol = 114
+ final val TERMREF = 115
+ final val TYPEREFsymbol = 116
+ final val TYPEREF = 117
+ final val SELFDEF = 118
final val PACKAGE = 128
final val VALDEF = 129
@@ -287,11 +298,9 @@ object PickleFormat {
final val TYPEPARAM = 133
final val PARAMS = 134
final val PARAM = 136
- final val IMPORTED = 137
final val RENAMED = 138
final val APPLY = 139
final val TYPEAPPLY = 140
- final val NEW = 141
final val PAIR = 142
final val TYPED = 143
final val NAMEDARG = 144
@@ -309,13 +318,8 @@ object PickleFormat {
final val UNAPPLY = 156
final val ANNOTATED = 157
final val CASEDEF = 158
- final val IMPLICITarg = 159
final val TEMPLATE = 160
- final val SELFDEF = 161
- final val THIS = 162
final val SUPER = 163
- final val CLASSconst = 164
- final val ENUMconst = 165
final val SUPERtype = 166
final val REFINEDtype = 167
final val APPLIEDtype = 168
@@ -327,13 +331,11 @@ object PickleFormat {
final val METHODtype = 174
final val POLYtype = 175
final val PARAMtype = 176
- final val IMPLICITARG = 177
final val ANNOTATION = 178
- final val PRIVATEqualified = 179
- final val PROTECTEDqualified = 180
final val firstSimpleTreeTag = EMPTYTREE
final val firstNatTreeTag = SHARED
+ final val firstASTTreeTag = THIS
final val firstNatASTTreeTag = IDENT
final val firstLengthTreeTag = PACKAGE
@@ -490,7 +492,6 @@ object PickleFormat {
case POLYtype => "POLYtype"
case METHODtype => "METHODtype"
case PARAMtype => "PARAMtype"
- case IMPLICITARG => "IMPLICITARG"
case ANNOTATION => "ANNOTATION"
case PRIVATEqualified => "PRIVATEqualified"
case PROTECTEDqualified => "PROTECTEDqualified"
diff --git a/src/dotty/tools/dotc/core/pickling/TastyPrinter.scala b/src/dotty/tools/dotc/core/pickling/TastyPrinter.scala
index 38dac2c32..3311fc683 100644
--- a/src/dotty/tools/dotc/core/pickling/TastyPrinter.scala
+++ b/src/dotty/tools/dotc/core/pickling/TastyPrinter.scala
@@ -62,11 +62,9 @@ class TastyPrinter(bytes: Array[Byte])(implicit ctx: Context) {
val end = currentAddr + len
def printTrees() = until(end)(printTree())
tag match {
- case IMPORTED =>
- printName()
case RENAMED =>
printName(); printName()
- case VALDEF | DEFDEF | TYPEDEF | TYPEPARAM | PARAM | NAMEDARG | SELFDEF | BIND =>
+ case VALDEF | DEFDEF | TYPEDEF | TYPEPARAM | PARAM | NAMEDARG | BIND =>
printName(); printTrees()
case REFINEDtype =>
printTree(); printName(); printTrees()
@@ -87,14 +85,16 @@ class TastyPrinter(bytes: Array[Byte])(implicit ctx: Context) {
}
else if (tag >= firstNatASTTreeTag) {
tag match {
- case IDENT | SELECT | TERMREF | TYPEREF => printName()
+ case IDENT | SELECT | TERMREF | TYPEREF | SELFDEF => printName()
case _ => printNat()
}
printTree()
}
+ else if (tag >= firstASTTreeTag)
+ printTree()
else if (tag >= firstNatTreeTag)
tag match {
- case TERMREFpkg | TYPEREFpkg | STRINGconst => printName()
+ case TERMREFpkg | TYPEREFpkg | STRINGconst | IMPORTED => printName()
case _ => printNat()
}
indent -= 2
diff --git a/src/dotty/tools/dotc/core/pickling/TreePickler.scala b/src/dotty/tools/dotc/core/pickling/TreePickler.scala
index 750c7bda6..b8f031ec5 100644
--- a/src/dotty/tools/dotc/core/pickling/TreePickler.scala
+++ b/src/dotty/tools/dotc/core/pickling/TreePickler.scala
@@ -103,10 +103,10 @@ class TreePickler(pickler: TastyPickler) {
writeByte(NULLconst)
case ClazzTag =>
writeByte(CLASSconst)
- withLength { pickleType(c.typeValue) }
+ pickleType(c.typeValue)
case EnumTag =>
writeByte(ENUMconst)
- withLength { pickleType(c.symbolValue.termRef) }
+ pickleType(c.symbolValue.termRef)
}
def pickleType(tpe0: Type, richTypes: Boolean = false): Unit = try {
@@ -165,7 +165,7 @@ class TreePickler(pickler: TastyPickler) {
pickleName(tpe.name); pickleType(tpe.prefix)
case tpe: ThisType =>
writeByte(THIS)
- withLength { pickleType(tpe.tref) }
+ pickleType(tpe.tref)
case tpe: SuperType =>
writeByte(SUPERtype)
withLength { pickleType(tpe.thistpe); pickleType(tpe.supertpe)}
@@ -302,7 +302,7 @@ class TreePickler(pickler: TastyPickler) {
}
case New(tpt) =>
writeByte(NEW)
- withLength { pickleTpt(tpt) }
+ pickleTpt(tpt)
case Pair(left, right) =>
writeByte(PAIR)
withLength { pickleTree(left); pickleTree(right) }
@@ -357,8 +357,8 @@ class TreePickler(pickler: TastyPickler) {
withLength {
pickleTree(fun)
for (implicitArg <- implicits) {
- writeByte(IMPLICITARG)
- withLength { pickleTree(implicitArg) }
+ writeByte(IMPLICITarg)
+ pickleTree(implicitArg)
}
pickleType(tree.tpe)
patterns.foreach(pickleTree)
@@ -390,10 +390,8 @@ class TreePickler(pickler: TastyPickler) {
val cinfo @ ClassInfo(_, _, _, _, selfInfo) = tree.symbol.owner.info
if ((selfInfo ne NoType) || !tree.self.isEmpty) {
writeByte(SELFDEF)
- withLength {
- pickleName(tree.self.name)
- pickleType(cinfo.selfType)
- }
+ pickleName(tree.self.name)
+ pickleType(cinfo.selfType)
}
pickleStats(tree.constr :: rest)
}
@@ -407,7 +405,7 @@ class TreePickler(pickler: TastyPickler) {
withLength { pickleName(from); pickleName(to) }
case Ident(name) =>
writeByte(IMPORTED)
- withLength { pickleName(name) }
+ pickleName(name)
}
}
case PackageDef(pid, stats) =>
@@ -460,7 +458,7 @@ class TreePickler(pickler: TastyPickler) {
val privateWithin = sym.privateWithin
if (privateWithin.exists) {
writeByte(if (flags is Protected) PROTECTEDqualified else PRIVATEqualified)
- withLength { pickleType(privateWithin.typeRef) }
+ pickleType(privateWithin.typeRef)
}
if (flags is Private) writeByte(PRIVATE)
if (flags is Protected) if (!privateWithin.exists) writeByte(PROTECTED)
diff --git a/src/dotty/tools/dotc/core/pickling/TreeUnpickler.scala b/src/dotty/tools/dotc/core/pickling/TreeUnpickler.scala
index edd951a9d..4890e14ef 100644
--- a/src/dotty/tools/dotc/core/pickling/TreeUnpickler.scala
+++ b/src/dotty/tools/dotc/core/pickling/TreeUnpickler.scala
@@ -72,6 +72,7 @@ class TreeUnpickler(reader: TastyReader, tastyName: TastyName.Table, roots: Set[
def skipTree(tag: Int): Unit =
if (tag >= firstLengthTreeTag) goto(readEnd())
else if (tag >= firstNatASTTreeTag) { readNat(); skipTree() }
+ else if (tag >= firstASTTreeTag) skipTree()
else if (tag >= firstNatTreeTag) readNat()
def skipTree(): Unit = skipTree(readByte())
@@ -130,8 +131,6 @@ class TreeUnpickler(reader: TastyReader, tastyName: TastyName.Table, roots: Set[
val result =
(tag: @switch) match {
- case THIS =>
- ThisType.raw(readType().asInstanceOf[TypeRef])
case SUPERtype =>
SuperType(readType(), readType())
case REFINEDtype =>
@@ -190,10 +189,8 @@ class TreeUnpickler(reader: TastyReader, tastyName: TastyName.Table, roots: Set[
case binder: MethodType => MethodParam(binder, readNat())
}
case CLASSconst =>
- readEnd()
ConstantType(Constant(readType()))
case ENUMconst =>
- readEnd()
ConstantType(Constant(readTermRef().termSymbol))
}
assert(currentAddr == end, s"$start $currentAddr $end ${astTagToString(tag)}")
@@ -228,6 +225,8 @@ class TreeUnpickler(reader: TastyReader, tastyName: TastyName.Table, roots: Set[
case name: TermName => TermRef.all(readType(), name)
case (name: TermName, sig: Signature) => TermRef.withSig(readType(), name, sig)
}
+ case THIS =>
+ ThisType.raw(readType().asInstanceOf[TypeRef])
case SKOLEMtype =>
SkolemType(readTypeRef())
case NOTYPE =>
@@ -391,11 +390,9 @@ class TreeUnpickler(reader: TastyReader, tastyName: TastyName.Table, roots: Set[
case INSUPERCALL => addFlag(InSuperCall)
case PRIVATEqualified =>
readByte()
- readEnd()
privateWithin = readType().typeSymbol
case PROTECTEDqualified =>
addFlag(Protected)
- readEnd()
privateWithin = readType().typeSymbol
case ANNOTATION =>
readByte()
@@ -549,7 +546,6 @@ class TreeUnpickler(reader: TastyReader, tastyName: TastyName.Table, roots: Set[
val self =
if (nextByte == SELFDEF) {
readByte()
- readEnd()
untpd.ValDef(readName(), readTpt(), EmptyTree).withType(NoType)
}
else EmptyValDef
@@ -622,6 +618,8 @@ class TreeUnpickler(reader: TastyReader, tastyName: TastyName.Table, roots: Set[
case name: Name => readQual(name).select(name)
case (name: Name, sig: Signature) => readQual(name).selectWithSig(name, sig)
}
+ case NEW =>
+ New(readTpt())
case EMPTYTREE =>
EmptyTree
case _ =>
@@ -648,8 +646,6 @@ class TreeUnpickler(reader: TastyReader, tastyName: TastyName.Table, roots: Set[
tpd.Apply(fn, until(end)(readArg()))
case TYPEAPPLY =>
tpd.TypeApply(readTerm(), until(end)(readTpt()))
- case NEW =>
- New(readTpt())
case PAIR =>
Pair(readTerm(), readTerm())
case TYPED =>
@@ -694,9 +690,8 @@ class TreeUnpickler(reader: TastyReader, tastyName: TastyName.Table, roots: Set[
case UNAPPLY =>
val fn = readTerm()
val implicitArgs =
- collectWhile(nextByte == IMPLICITARG) {
+ collectWhile(nextByte == IMPLICITarg) {
readByte()
- readEnd()
readTerm()
}
val patType = readType()