diff options
Diffstat (limited to 'src/dotty/tools/dotc/core')
-rw-r--r-- | src/dotty/tools/dotc/core/Denotations.scala | 38 | ||||
-rw-r--r-- | src/dotty/tools/dotc/core/Phases.scala | 2 | ||||
-rw-r--r-- | src/dotty/tools/dotc/core/StdNames.scala | 2 | ||||
-rw-r--r-- | src/dotty/tools/dotc/core/SymDenotations.scala | 16 | ||||
-rw-r--r-- | src/dotty/tools/dotc/core/Symbols.scala | 8 | ||||
-rw-r--r-- | src/dotty/tools/dotc/core/TypeApplications.scala | 15 | ||||
-rw-r--r-- | src/dotty/tools/dotc/core/TypeComparer.scala | 8 | ||||
-rw-r--r-- | src/dotty/tools/dotc/core/TypeErasure.scala | 143 | ||||
-rw-r--r-- | src/dotty/tools/dotc/core/Types.scala | 6 | ||||
-rw-r--r-- | src/dotty/tools/dotc/core/pickling/NameBuffer.scala | 2 | ||||
-rw-r--r-- | src/dotty/tools/dotc/core/pickling/PositionPickler.scala | 2 | ||||
-rw-r--r-- | src/dotty/tools/dotc/core/pickling/TastyBuffer.scala | 5 | ||||
-rw-r--r-- | src/dotty/tools/dotc/core/pickling/TreeBuffer.scala | 3 |
13 files changed, 166 insertions, 84 deletions
diff --git a/src/dotty/tools/dotc/core/Denotations.scala b/src/dotty/tools/dotc/core/Denotations.scala index a30cff714..6502c4a40 100644 --- a/src/dotty/tools/dotc/core/Denotations.scala +++ b/src/dotty/tools/dotc/core/Denotations.scala @@ -620,14 +620,9 @@ object Denotations { // println(s"installing $this after $phase/${phase.id}, valid = ${current.validFor}") // printPeriods(current) this.validFor = Period(ctx.runId, targetId, current.validFor.lastPhaseId) - if (current.validFor.firstPhaseId == targetId) { - // replace current with this denotation - var prev = current - while (prev.nextInRun ne current) prev = prev.nextInRun - prev.nextInRun = this - this.nextInRun = current.nextInRun - current.validFor = Nowhere - } else { + if (current.validFor.firstPhaseId == targetId) + replaceDenotation(current) + else { // insert this denotation after current current.validFor = Period(ctx.runId, current.validFor.firstPhaseId, targetId - 1) this.nextInRun = current.nextInRun @@ -637,6 +632,33 @@ object Denotations { } } + /** Apply a transformation `f` to all denotations in this group that start at or after + * given phase. Denotations are replaced while keeping the same validity periods. + */ + protected def transformAfter(phase: DenotTransformer, f: SymDenotation => SymDenotation)(implicit ctx: Context): Unit = { + var current = symbol.current + while (current.validFor.firstPhaseId < phase.id && (current.nextInRun.validFor.code > current.validFor.code)) + current = current.nextInRun + var hasNext = true + while ((current.validFor.firstPhaseId >= phase.id) && hasNext) { + val current1: SingleDenotation = f(current.asSymDenotation) + if (current1 ne current) { + current1.validFor = current.validFor + current1.replaceDenotation(current) + } + hasNext = current1.nextInRun.validFor.code > current1.validFor.code + current = current1.nextInRun + } + } + + private def replaceDenotation(current: SingleDenotation): Unit = { + var prev = current + while (prev.nextInRun ne current) prev = prev.nextInRun + prev.nextInRun = this + this.nextInRun = current.nextInRun + current.validFor = Nowhere + } + def staleSymbolError(implicit ctx: Context) = { def ownerMsg = this match { case denot: SymDenotation => s"in ${denot.owner}" diff --git a/src/dotty/tools/dotc/core/Phases.scala b/src/dotty/tools/dotc/core/Phases.scala index 96066db5e..406a3457a 100644 --- a/src/dotty/tools/dotc/core/Phases.scala +++ b/src/dotty/tools/dotc/core/Phases.scala @@ -232,6 +232,7 @@ object Phases { private val typerCache = new PhaseCache(classOf[FrontEnd]) private val refChecksCache = new PhaseCache(classOf[RefChecks]) + private val extensionMethodsCache = new PhaseCache(classOf[ExtensionMethods]) private val erasureCache = new PhaseCache(classOf[Erasure]) private val patmatCache = new PhaseCache(classOf[PatternMatcher]) private val flattenCache = new PhaseCache(classOf[Flatten]) @@ -241,6 +242,7 @@ object Phases { def typerPhase = typerCache.phase def refchecksPhase = refChecksCache.phase + def extensionMethodsPhase = extensionMethodsCache.phase def erasurePhase = erasureCache.phase def patmatPhase = patmatCache.phase def flattenPhase = flattenCache.phase diff --git a/src/dotty/tools/dotc/core/StdNames.scala b/src/dotty/tools/dotc/core/StdNames.scala index 829ff8b8f..74a121b47 100644 --- a/src/dotty/tools/dotc/core/StdNames.scala +++ b/src/dotty/tools/dotc/core/StdNames.scala @@ -226,6 +226,7 @@ object StdNames { val ANYname: N = "<anyname>" val CONSTRUCTOR: N = Names.CONSTRUCTOR.toString val DEFAULT_CASE: N = "defaultCase$" + val EVT2U: N = "evt2u$" val EQEQ_LOCAL_VAR: N = "eqEqTemp$" val FAKE_LOCAL_THIS: N = "this$" val IMPLCLASS_CONSTRUCTOR: N = "$init$" @@ -257,6 +258,7 @@ object StdNames { val SKOLEM: N = "<skolem>" val SPECIALIZED_INSTANCE: N = "specInstance$" val THIS: N = "_$this" + val U2EVT: N = "u2evt$" final val Nil: N = "Nil" final val Predef: N = "Predef" diff --git a/src/dotty/tools/dotc/core/SymDenotations.scala b/src/dotty/tools/dotc/core/SymDenotations.scala index 83499ca7b..14be606a1 100644 --- a/src/dotty/tools/dotc/core/SymDenotations.scala +++ b/src/dotty/tools/dotc/core/SymDenotations.scala @@ -1043,6 +1043,12 @@ object SymDenotations { /** Install this denotation as the result of the given denotation transformer. */ override def installAfter(phase: DenotTransformer)(implicit ctx: Context): Unit = super.installAfter(phase) + + /** Apply a transformation `f` to all denotations in this group that start at or after + * given phase. Denotations are replaced while keeping the same validity periods. + */ + override def transformAfter(phase: DenotTransformer, f: SymDenotation => SymDenotation)(implicit ctx: Context): Unit = + super.transformAfter(phase, f) } /** The contents of a class definition during a period @@ -1441,10 +1447,16 @@ object SymDenotations { def inCache(tp: Type) = baseTypeRefCache.containsKey(tp) - /** Can't cache types containing type variables which are uninstantiated - * or whose instances can change, depending on typerstate. + /** We cannot cache: + * - type variables which are uninstantiated or whose instances can + * change, depending on typerstate. + * - types where the underlying type is an ErasedValueType, because + * this underlying type will change after ElimErasedValueType, + * and this changes subtyping relations. As a shortcut, we do not + * cache ErasedValueType at all. */ def isCachable(tp: Type): Boolean = tp match { + case _: TypeErasure.ErasedValueType => false case tp: TypeVar => tp.inst.exists && inCache(tp.inst) case tp: TypeProxy => inCache(tp.underlying) case tp: AndOrType => inCache(tp.tp1) && inCache(tp.tp2) diff --git a/src/dotty/tools/dotc/core/Symbols.scala b/src/dotty/tools/dotc/core/Symbols.scala index 9f18e723c..2b91efbcd 100644 --- a/src/dotty/tools/dotc/core/Symbols.scala +++ b/src/dotty/tools/dotc/core/Symbols.scala @@ -434,14 +434,6 @@ object Symbols { /** If this symbol satisfies predicate `p` this symbol, otherwise `NoSymbol` */ def filter(p: Symbol => Boolean): Symbol = if (p(this)) this else NoSymbol - /** Is this symbol a user-defined value class? */ - final def isDerivedValueClass(implicit ctx: Context): Boolean = { - this.derivesFrom(defn.AnyValClass)(ctx.withPhase(denot.validFor.firstPhaseId)) - // Simulate ValueClasses.isDerivedValueClass - false // will migrate to ValueClasses.isDerivedValueClass; - // unsupported value class code will continue to use this stub while it exists - } - /** The current name of this symbol */ final def name(implicit ctx: Context): ThisName = denot.name.asInstanceOf[ThisName] diff --git a/src/dotty/tools/dotc/core/TypeApplications.scala b/src/dotty/tools/dotc/core/TypeApplications.scala index 5325189e1..a5e24c5ff 100644 --- a/src/dotty/tools/dotc/core/TypeApplications.scala +++ b/src/dotty/tools/dotc/core/TypeApplications.scala @@ -282,12 +282,17 @@ class TypeApplications(val self: Type) extends AnyVal { /** Translate a type of the form From[T] to To[T], keep other types as they are. * `from` and `to` must be static classes, both with one type parameter, and the same variance. + * Do the same for by name types => From[T] and => To[T] */ - def translateParameterized(from: ClassSymbol, to: ClassSymbol)(implicit ctx: Context): Type = - if (self.derivesFrom(from)) - if (ctx.erasedTypes) to.typeRef - else RefinedType(to.typeRef, to.typeParams.head.name, self.member(from.typeParams.head.name).info) - else self + def translateParameterized(from: ClassSymbol, to: ClassSymbol)(implicit ctx: Context): Type = self match { + case self @ ExprType(tp) => + self.derivedExprType(tp.translateParameterized(from, to)) + case _ => + if (self.derivesFrom(from)) + if (ctx.erasedTypes) to.typeRef + else RefinedType(to.typeRef, to.typeParams.head.name, self.member(from.typeParams.head.name).info) + else self + } /** If this is repeated parameter type, its underlying Seq type, * or, if isJava is true, Array type, else the type itself. diff --git a/src/dotty/tools/dotc/core/TypeComparer.scala b/src/dotty/tools/dotc/core/TypeComparer.scala index a59a64a91..18f9f08bb 100644 --- a/src/dotty/tools/dotc/core/TypeComparer.scala +++ b/src/dotty/tools/dotc/core/TypeComparer.scala @@ -229,6 +229,14 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling wi compareSuper case AndType(tp21, tp22) => isSubType(tp1, tp21) && isSubType(tp1, tp22) + case TypeErasure.ErasedValueType(cls2, underlying2) => + def compareErasedValueType = tp1 match { + case TypeErasure.ErasedValueType(cls1, underlying1) => + (cls1 eq cls2) && isSameType(underlying1, underlying2) + case _ => + secondTry(tp1, tp2) + } + compareErasedValueType case ErrorType => true case _ => diff --git a/src/dotty/tools/dotc/core/TypeErasure.scala b/src/dotty/tools/dotc/core/TypeErasure.scala index 20cf816c2..e695e6721 100644 --- a/src/dotty/tools/dotc/core/TypeErasure.scala +++ b/src/dotty/tools/dotc/core/TypeErasure.scala @@ -3,12 +3,15 @@ package dotc package core import Symbols._, Types._, Contexts._, Flags._, Names._, StdNames._, Decorators._, Flags.JavaDefined +import Uniques.unique import dotc.transform.ExplicitOuter._ +import dotc.transform.ValueClasses._ import typer.Mode import util.DotClass /** Erased types are: * + * ErasedValueType * TypeRef(prefix is ignored, denot is ClassDenotation) * TermRef(prefix is ignored, denot is SymDenotation) * JavaArrayType @@ -29,8 +32,12 @@ 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. + * ErasedValueType is considered an erased type because it is valid after Erasure (it is + * eliminated by ElimErasedValueType). */ def isErasedType(tp: Type)(implicit ctx: Context): Boolean = tp match { + case _: ErasedValueType => + true case tp: TypeRef => tp.symbol.isClass && tp.symbol != defn.AnyClass case _: TermRef => @@ -51,13 +58,35 @@ object TypeErasure { false } - case class ErasedValueType(cls: ClassSymbol, underlying: Type) extends CachedGroundType { - override def computeHash = doHash(cls, underlying) + /** A type representing the semi-erasure of a derived value class, see SIP-15 + * where it's called "C$unboxed" for a class C. + * Derived value classes are erased to this type during Erasure (when + * semiEraseVCs = true) and subsequently erased to their underlying type + * during ElimErasedValueType. This type is outside the normal Scala class + * hierarchy: it is a subtype of no other type and is a supertype only of + * Nothing. This is because this type is only useful for type adaptation (see + * [[Erasure.Boxing#adaptToType]]). + * + * @param cls The value class symbol + * @param erasedUnderlying The erased type of the single field of the value class + */ + abstract case class ErasedValueType(cls: ClassSymbol, erasedUnderlying: Type) + extends CachedGroundType with ValueType { + override def computeHash = doHash(cls, erasedUnderlying) } - private def erasureIdx(isJava: Boolean, isSemi: Boolean, isConstructor: Boolean, wildcardOK: Boolean) = + final class CachedErasedValueType(cls: ClassSymbol, erasedUnderlying: Type) + extends ErasedValueType(cls, erasedUnderlying) + + object ErasedValueType { + def apply(cls: ClassSymbol, erasedUnderlying: Type)(implicit ctx: Context) = { + unique(new CachedErasedValueType(cls, erasedUnderlying)) + } + } + + private def erasureIdx(isJava: Boolean, semiEraseVCs: Boolean, isConstructor: Boolean, wildcardOK: Boolean) = (if (isJava) 1 else 0) + - (if (isSemi) 2 else 0) + + (if (semiEraseVCs) 2 else 0) + (if (isConstructor) 4 else 0) + (if (wildcardOK) 8 else 0) @@ -65,41 +94,32 @@ object TypeErasure { for { isJava <- List(false, true) - isSemi <- List(false, true) + semiEraseVCs <- List(false, true) isConstructor <- List(false, true) wildcardOK <- List(false, true) - } erasures(erasureIdx(isJava, isSemi, isConstructor, wildcardOK)) = - new TypeErasure(isJava, isSemi, isConstructor, wildcardOK) + } erasures(erasureIdx(isJava, semiEraseVCs, isConstructor, wildcardOK)) = + new TypeErasure(isJava, semiEraseVCs, 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). + /** Produces an erasure function. See the documentation of the class [[TypeErasure]] + * for a description of each parameter. */ - 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) + private def erasureFn(isJava: Boolean, semiEraseVCs: Boolean, isConstructor: Boolean, wildcardOK: Boolean): TypeErasure = + erasures(erasureIdx(isJava, semiEraseVCs, isConstructor, wildcardOK)) /** 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 erasure(tp: Type, semiEraseVCs: Boolean = true)(implicit ctx: Context): Type = + erasureFn(isJava = false, semiEraseVCs, isConstructor = false, wildcardOK = false)(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) + val erase = erasureFn(isJava, semiEraseVCs = false, isConstructor = false, wildcardOK = true) + erase.sigName(normTp)(erasureCtx) } /** The erasure of a top-level reference. Differs from normal erasure in that @@ -117,29 +137,20 @@ object TypeErasure { 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 COMPANION_CLASS_METHOD : the erasure of their type with semiEraseVCs = false, + * this is needed to keep [[SymDenotation#companionClass]] + * working after erasure for value classes. * - 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) + val semiEraseVCs = sym.name ne nme.COMPANION_CLASS_METHOD + val erase = erasureFn(sym is JavaDefined, semiEraseVCs, sym.isConstructor, wildcardOK = false) def eraseParamBounds(tp: PolyType): Type = tp.derivedPolyType( @@ -148,7 +159,7 @@ object TypeErasure { 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 { + else erase.eraseInfo(tp, sym)(erasureCtx) match { case einfo: MethodType if sym.isGetter && einfo.resultType.isRef(defn.UnitClass) => defn.BoxedUnitClass.typeRef case einfo => @@ -241,12 +252,15 @@ object TypeErasure { 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. - * + * @param isJava Arguments should be treated the way Java does it + * @param semiEraseVCs If true, value classes are semi-erased to ErasedValueType + * (they will be fully erased in [[ElimErasedValueType]]). + * If false, they are erased like normal classes. + * @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). */ -class TypeErasure(isJava: Boolean, isSemi: Boolean, isConstructor: Boolean, wildcardOK: Boolean) extends DotClass { +class TypeErasure(isJava: Boolean, semiEraseVCs: Boolean, isConstructor: Boolean, wildcardOK: Boolean) extends DotClass { /** The erasure |T| of a type T. This is: * @@ -279,10 +293,12 @@ class TypeErasure(isJava: Boolean, isSemi: Boolean, isConstructor: Boolean, wild * - For any other type, exception. */ private def apply(tp: Type)(implicit ctx: Context): Type = tp match { + case _: ErasedValueType => + tp case tp: TypeRef => val sym = tp.symbol if (!sym.isClass) this(tp.info) - else if (sym.isDerivedValueClass) eraseDerivedValueClassRef(tp) + else if (semiEraseVCs && isDerivedValueClass(sym)) eraseDerivedValueClassRef(tp) else eraseNormalClassRef(tp) case tp: RefinedType => val parent = tp.parent @@ -291,7 +307,9 @@ class TypeErasure(isJava: Boolean, isSemi: Boolean, isConstructor: Boolean, wild case tp: TermRef => this(tp.widen) case tp: ThisType => - this(tp.cls.typeRef) + def thisTypeErasure(tpToErase: Type) = + erasureFn(isJava, semiEraseVCs = false, isConstructor, wildcardOK)(tpToErase) + thisTypeErasure(tp.cls.typeRef) case SuperType(thistpe, supertpe) => SuperType(this(thistpe), this(supertpe)) case ExprType(rt) => @@ -303,7 +321,8 @@ class TypeErasure(isJava: Boolean, isSemi: Boolean, isConstructor: Boolean, wild case OrType(tp1, tp2) => ctx.typeComparer.orType(this(tp1), this(tp2), erased = true) case tp: MethodType => - val paramErasure = erasureFn(tp.isJava, isSemi, isConstructor, wildcardOK)(_) + def paramErasure(tpToErase: Type) = + erasureFn(tp.isJava, semiEraseVCs, isConstructor, wildcardOK)(tpToErase) val formals = tp.paramTypes.mapConserve(paramErasure) eraseResult(tp.resultType) match { case rt: MethodType => @@ -341,11 +360,17 @@ class TypeErasure(isJava: Boolean, isSemi: Boolean, isConstructor: Boolean, wild private def eraseArray(tp: RefinedType)(implicit ctx: Context) = { val defn.ArrayType(elemtp) = tp + def arrayErasure(tpToErase: Type) = + erasureFn(isJava, semiEraseVCs = false, isConstructor, wildcardOK)(tpToErase) if (elemtp derivesFrom defn.NullClass) JavaArrayType(defn.ObjectType) else if (isUnboundedGeneric(elemtp)) defn.ObjectType - else JavaArrayType(this(elemtp)) + else JavaArrayType(arrayErasure(elemtp)) } + /** The erasure of a symbol's info. This is different from `apply` in the way `ExprType`s are + * treated. `eraseInfo` maps them them to nullary method types, whereas `apply` maps them + * to `Function0`. + */ def eraseInfo(tp: Type, sym: Symbol)(implicit ctx: Context) = tp match { case ExprType(rt) => if (sym is Param) apply(tp) @@ -354,22 +379,30 @@ class TypeErasure(isJava: Boolean, isSemi: Boolean, isConstructor: Boolean, wild // 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) + case tp => this(tp) + } + + private def eraseDerivedValueClassRef(tref: TypeRef)(implicit ctx: Context): Type = { + val cls = tref.symbol.asClass + val underlying = underlyingOfValueClass(cls) + ErasedValueType(cls, erasure(underlying)) } - 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 } + /** The erasure of a function result type. */ 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) + // For a value class V, "new V(x)" should have type V for type adaptation to work + // correctly (see SIP-15 and [[Erasure.Boxing.adaptToType]]), so the return type of a + // constructor method should not be semi-erased. + else if (isConstructor && isDerivedValueClass(sym)) eraseNormalClassRef(tp) else this(tp) case RefinedType(parent, _) if !(parent isRef defn.ArrayClass) => eraseResult(parent) @@ -391,10 +424,12 @@ class TypeErasure(isJava: Boolean, isSemi: Boolean, isConstructor: Boolean, wild * Need to ensure correspondence with erasure! */ private def sigName(tp: Type)(implicit ctx: Context): TypeName = tp match { + case ErasedValueType(_, underlying) => + sigName(underlying) case tp: TypeRef => val sym = tp.symbol if (!sym.isClass) sigName(tp.info) - else if (sym.isDerivedValueClass) sigName(eraseDerivedValueClassRef(tp)) + else if (isDerivedValueClass(sym)) sigName(eraseDerivedValueClassRef(tp)) else normalizeClass(sym.asClass).fullName.asTypeName case defn.ArrayType(elem) => sigName(this(tp)) diff --git a/src/dotty/tools/dotc/core/Types.scala b/src/dotty/tools/dotc/core/Types.scala index e290e8868..595732b37 100644 --- a/src/dotty/tools/dotc/core/Types.scala +++ b/src/dotty/tools/dotc/core/Types.scala @@ -2066,14 +2066,16 @@ object Types { def apply(paramTypes: List[Type], resultType: Type)(implicit ctx: Context): MethodType = apply(nme.syntheticParamNames(paramTypes.length), paramTypes, resultType) def fromSymbols(params: List[Symbol], resultType: Type)(implicit ctx: Context) = { - def paramInfo(param: Symbol): Type = param.info match { + def translateRepeated(tp: Type): Type = tp match { + case tp @ ExprType(tp1) => tp.derivedExprType(translateRepeated(tp1)) case AnnotatedType(annot, tp) if annot matches defn.RepeatedAnnot => - val typeSym = param.info.typeSymbol.asClass + val typeSym = tp.typeSymbol.asClass assert(typeSym == defn.SeqClass || typeSym == defn.ArrayClass) tp.translateParameterized(typeSym, defn.RepeatedParamClass) case tp => tp } + def paramInfo(param: Symbol): Type = translateRepeated(param.info) def transformResult(mt: MethodType) = resultType.subst(params, (0 until params.length).toList map (MethodParam(mt, _))) apply(params map (_.name.asTermName), params map paramInfo)(transformResult _) diff --git a/src/dotty/tools/dotc/core/pickling/NameBuffer.scala b/src/dotty/tools/dotc/core/pickling/NameBuffer.scala index 2a6239c5a..7ea94089f 100644 --- a/src/dotty/tools/dotc/core/pickling/NameBuffer.scala +++ b/src/dotty/tools/dotc/core/pickling/NameBuffer.scala @@ -11,7 +11,7 @@ import scala.io.Codec import TastyName._ import PickleFormat._ -class NameBuffer extends TastyBuffer(100000) { +class NameBuffer extends TastyBuffer(10000) { private val nameRefs = new mutable.LinkedHashMap[TastyName, NameRef] diff --git a/src/dotty/tools/dotc/core/pickling/PositionPickler.scala b/src/dotty/tools/dotc/core/pickling/PositionPickler.scala index e8a0b3d01..1e36105cb 100644 --- a/src/dotty/tools/dotc/core/pickling/PositionPickler.scala +++ b/src/dotty/tools/dotc/core/pickling/PositionPickler.scala @@ -38,7 +38,7 @@ object PositionPickler { import PositionPickler._ class PositionPickler(pickler: TastyPickler, addrOfTree: Tree => Option[Addr]) { - val buf = new TastyBuffer(100000) + val buf = new TastyBuffer(5000) pickler.newSection("Positions", buf) import buf._ diff --git a/src/dotty/tools/dotc/core/pickling/TastyBuffer.scala b/src/dotty/tools/dotc/core/pickling/TastyBuffer.scala index a67722227..f57c15a3d 100644 --- a/src/dotty/tools/dotc/core/pickling/TastyBuffer.scala +++ b/src/dotty/tools/dotc/core/pickling/TastyBuffer.scala @@ -44,7 +44,8 @@ class TastyBuffer(initialSize: Int) { /** Write a byte of data. */ def writeByte(b: Int): Unit = { - if (length == bytes.length) bytes = dble(bytes) + if (length >= bytes.length) + bytes = dble(bytes) bytes(length) = b.toByte length += 1 } @@ -116,6 +117,8 @@ class TastyBuffer(initialSize: Int) { def putNat(at: Addr, x: Int, width: Int): Unit = { var y = x var w = width + if(at.index + w >= bytes.length) + bytes = dble(bytes) var digit = y & 0x7f | 0x80 while (w > 0) { w -= 1 diff --git a/src/dotty/tools/dotc/core/pickling/TreeBuffer.scala b/src/dotty/tools/dotc/core/pickling/TreeBuffer.scala index c224fc30b..393ffd278 100644 --- a/src/dotty/tools/dotc/core/pickling/TreeBuffer.scala +++ b/src/dotty/tools/dotc/core/pickling/TreeBuffer.scala @@ -8,10 +8,9 @@ import TastyBuffer.{Addr, AddrWidth} import config.Printers.pickling import ast.tpd.Tree -class TreeBuffer extends TastyBuffer(1000000) { +class TreeBuffer extends TastyBuffer(50000) { private final val ItemsOverOffsets = 2 - private val initialOffsetSize = bytes.length / (AddrWidth * ItemsOverOffsets) private var offsets = new Array[Int](initialOffsetSize) private var isRelative = new Array[Boolean](initialOffsetSize) |