diff --git a/compiler/src/dotty/tools/dotc/core/DenotTransformers.scala b/compiler/src/dotty/tools/dotc/core/DenotTransformers.scala index c62008e6eada..192e2547a57d 100644 --- a/compiler/src/dotty/tools/dotc/core/DenotTransformers.scala +++ b/compiler/src/dotty/tools/dotc/core/DenotTransformers.scala @@ -24,9 +24,9 @@ object DenotTransformers { /** The last phase during which the transformed denotations are valid */ def lastPhaseId(implicit ctx: Context) = ctx.nextDenotTransformerId(id + 1) - /** The validity period of the transformer in the given context */ + /** The validity period of the transformed denotations in the given context */ def validFor(implicit ctx: Context): Period = - Period(ctx.runId, id, lastPhaseId) + Period(ctx.runId, id + 1, lastPhaseId) /** The transformation method */ def transform(ref: SingleDenotation)(implicit ctx: Context): SingleDenotation diff --git a/compiler/src/dotty/tools/dotc/core/SymDenotations.scala b/compiler/src/dotty/tools/dotc/core/SymDenotations.scala index 32c6b4038d82..7d2ecdf21436 100644 --- a/compiler/src/dotty/tools/dotc/core/SymDenotations.scala +++ b/compiler/src/dotty/tools/dotc/core/SymDenotations.scala @@ -51,13 +51,9 @@ trait SymDenotations { this: Context => else { val initial = denot.initial val firstPhaseId = initial.validFor.firstPhaseId.max(ctx.typerPhase.id) - if ((initial ne denot) || ctx.phaseId != firstPhaseId) { - ctx.withPhase(firstPhaseId).stillValidInOwner(initial) || - // Workaround #1895: A symbol might not be entered into an owner - // until the second phase where it exists - (denot.validFor.containsPhaseId(firstPhaseId + 1)) && - ctx.withPhase(firstPhaseId + 1).stillValidInOwner(initial) - } else + if ((initial ne denot) || ctx.phaseId != firstPhaseId) + ctx.withPhase(firstPhaseId).stillValidInOwner(initial) + else stillValidInOwner(denot) } diff --git a/compiler/src/dotty/tools/dotc/transform/ExtensionMethods.scala b/compiler/src/dotty/tools/dotc/transform/ExtensionMethods.scala index b617dbd1e854..e9dcab37abd4 100644 --- a/compiler/src/dotty/tools/dotc/transform/ExtensionMethods.scala +++ b/compiler/src/dotty/tools/dotc/transform/ExtensionMethods.scala @@ -62,51 +62,38 @@ class ExtensionMethods extends MiniPhase with DenotTransformer with FullParamete val decls1 = cinfo.decls.cloneScope val moduleSym = moduleClassSym.symbol.asClass - var newSuperClass: Type = null - - ctx.atPhase(thisPhase.next) { implicit ctx => - // In Scala 2, extension methods are added before pickling so we should - // not generate them again. - if (!(valueClass is Scala2x)) ctx.atPhase(thisPhase) { implicit ctx => - for (decl <- valueClass.classInfo.decls) { - if (isMethodWithExtension(decl)) { - val meth = createExtensionMethod(decl, moduleClassSym.symbol) - decls1.enter(meth) - // Workaround #1895: force denotation of `meth` to be - // at phase where `meth` is entered into the decls of a class - meth.denot(ctx.withPhase(thisPhase.next)) - } - } - } - - val underlying = valueErasure(underlyingOfValueClass(valueClass)) - val evt = ErasedValueType(valueClass.typeRef, underlying) - val u2evtSym = ctx.newSymbol(moduleSym, nme.U2EVT, Synthetic | Method, - MethodType(List(nme.x_0), List(underlying), evt)) - val evt2uSym = ctx.newSymbol(moduleSym, nme.EVT2U, Synthetic | Method, - MethodType(List(nme.x_0), List(evt), underlying)) - - val defn = ctx.definitions - - val underlyingCls = underlying.classSymbol - val underlyingClsName = - if (underlyingCls.isNumericValueClass || underlyingCls == defn.BooleanClass) underlyingCls.name - else nme.Object - - val syp = ctx.requiredClass(s"dotty.runtime.vc.VC${underlyingClsName}Companion").asClass - - newSuperClass = tpd.ref(syp).select(nme.CONSTRUCTOR).appliedToType(valueClass.typeRef).tpe.resultType - - decls1.enter(u2evtSym) - decls1.enter(evt2uSym) + def enterInModuleClass(sym: Symbol): Unit = { + decls1.enter(sym) + // This is tricky: in this denotation transformer, we transform + // companion modules of value classes by adding methods to them. + // Running the transformer will create these methods, but they're + // only valid once it has finished running. This means we cannot use + // `ctx.withPhase(thisPhase.next)` here without potentially running + // into cycles. Instead, we manually set their validity after having + // created them to match the validity of the owner transformed + // denotation. + sym.validFor = thisPhase.validFor } - // Add the extension methods, the cast methods u2evt$ and evt2u$, and a VC*Companion superclass - moduleClassSym.copySymDenotation(info = - cinfo.derivedClassInfo( - // FIXME: use of VC*Companion superclasses is disabled until the conflicts with SyntheticMethods are solved. - //classParents = List(newSuperClass) - decls = decls1)) + // Create extension methods, except if the class comes from Scala 2 + // because it adds extension methods before pickling. + if (!(valueClass.is(Scala2x))) + for (decl <- valueClass.classInfo.decls) + if (isMethodWithExtension(decl)) + enterInModuleClass(createExtensionMethod(decl, moduleClassSym.symbol)) + + // Create synthetic methods to cast values between the underlying type + // and the ErasedValueType. These methods are removed in ElimErasedValueType. + val underlying = valueErasure(underlyingOfValueClass(valueClass)) + val evt = ErasedValueType(valueClass.typeRef, underlying) + val u2evtSym = ctx.newSymbol(moduleSym, nme.U2EVT, Synthetic | Method, + MethodType(List(nme.x_0), List(underlying), evt)) + val evt2uSym = ctx.newSymbol(moduleSym, nme.EVT2U, Synthetic | Method, + MethodType(List(nme.x_0), List(evt), underlying)) + enterInModuleClass(u2evtSym) + enterInModuleClass(evt2uSym) + + moduleClassSym.copySymDenotation(info = cinfo.derivedClassInfo(decls = decls1)) case _ => moduleClassSym } diff --git a/library/src/dotty/runtime/vc/VCPrototype.scala b/library/src/dotty/runtime/vc/VCPrototype.scala deleted file mode 100644 index 212046ef8922..000000000000 --- a/library/src/dotty/runtime/vc/VCPrototype.scala +++ /dev/null @@ -1,486 +0,0 @@ -package dotty.runtime.vc - -import scala.reflect.ClassTag - -abstract class VCPrototype { -} - - -abstract class VCArrayPrototype[T <: VCPrototype] extends Object with Cloneable { - def apply(idx: Int): Object - def update(idx: Int, el: T): Unit - def length: Int - override def clone(): Object = super.clone() -} - - -abstract class VCFloatPrototype(val underlying: Float) extends VCPrototype {} - -abstract class VCFloatCasePrototype(underlying: Float) extends VCFloatPrototype(underlying) with Product1[Float] { - - final def _1: Float = underlying - - override final def hashCode(): Int = { - underlying.hashCode() - } - - override final def toString: String = { - s"$productPrefix($underlying)" - } -} - -abstract class VCFloatCompanion[T <: VCFloatPrototype] extends ClassTag[T] { - def box(underlying: Float): T - final def unbox(boxed: T) = boxed.underlying - - implicit def classTag: this.type = this - override def newArray(len: Int): Array[T] = - new VCFloatArray(this, len).asInstanceOf[Array[T]] - - - final def _1$extension(underlying: Float) = underlying - final def hashCode$extension(underlying: Float) = underlying.hashCode() - final def toString$extension(underlying: Float) = s"${productPrefix$extension(underlying)}($underlying)" - def productPrefix$extension(underlying: Float): String -} - -final class VCFloatArray[T <: VCFloatPrototype] private (val arr: Array[Float], val ct: VCFloatCompanion[T]) - extends VCArrayPrototype[T] { - def this(ct: VCFloatCompanion[T], sz: Int) = - this(new Array[Float](sz), ct) - - def apply(idx: Int) = - ct.box(arr(idx)) - def update(idx: Int, elem: T) = - arr(idx) = ct.unbox(elem) - def length: Int = arr.length - - override def clone(): VCFloatArray[T] = { - new VCFloatArray[T](arr.clone(), ct) - } - - override def toString: String = { - "[" + ct.runtimeClass - } -} - - -abstract class VCObjectPrototype(val underlying: Object) extends VCPrototype {} - -abstract class VCObjectCasePrototype(underlying: Object) extends VCObjectPrototype(underlying) with Product1[Object] { - - final def _1: Object = underlying - - override final def hashCode(): Int = { - underlying.hashCode() - } - - override final def toString: String = { - s"$productPrefix($underlying)" - } -} - -abstract class VCObjectCompanion[T <: VCObjectPrototype] extends ClassTag[T] { - def box(underlying: Object): T - final def unbox(boxed: T) = boxed.underlying - - implicit def classTag: this.type = this - override def newArray(len: Int): Array[T] = - new VCObjectArray(this, len).asInstanceOf[Array[T]] - - - final def _1$extension(underlying: Object) = underlying - final def hashCode$extension(underlying: Object) = underlying.hashCode() - final def toString$extension(underlying: Object) = s"${productPrefix$extension(underlying)}($underlying)" - def productPrefix$extension(underlying: Object): String -} - -final class VCObjectArray[T <: VCObjectPrototype] private (val arr: Array[Object], val ct: VCObjectCompanion[T]) - extends VCArrayPrototype[T] { - def this(ct: VCObjectCompanion[T], sz: Int) = - this(new Array[Object](sz), ct) - - def apply(idx: Int) = - ct.box(arr(idx)) - - def update(idx: Int, elem: T) = - arr(idx) = ct.unbox(elem) - - def length: Int = arr.length - - override def clone(): VCObjectArray[T] = { - new VCObjectArray[T](arr.clone(), ct) - } - - override def toString: String = { - "[" + ct.runtimeClass - } -} - - -abstract class VCShortPrototype(val underlying: Short) extends VCPrototype {} - -abstract class VCShortCasePrototype(underlying: Short) extends VCShortPrototype(underlying) with Product1[Short] { - - final def _1: Short = underlying - - override final def hashCode(): Int = { - underlying.hashCode() - } - - override final def toString: String = { - s"$productPrefix($underlying)" - } -} - -abstract class VCShortCompanion[T <: VCShortPrototype] extends ClassTag[T] { - def box(underlying: Short): T - final def unbox(boxed: T) = boxed.underlying - - implicit def classTag: this.type = this - override def newArray(len: Int): Array[T] = - new VCShortArray(this, len).asInstanceOf[Array[T]] - - - final def _1$extension(underlying: Short) = underlying - final def hashCode$extension(underlying: Short) = underlying.hashCode() - final def toString$extension(underlying: Short) = s"${productPrefix$extension(underlying)}($underlying)" - def productPrefix$extension(underlying: Short): String -} - -final class VCShortArray[T <: VCShortPrototype] private (val arr: Array[Short], val ct: VCShortCompanion[T]) - extends VCArrayPrototype[T] { - def this(ct: VCShortCompanion[T], sz: Int) = - this(new Array[Short](sz), ct) - - def apply(idx: Int) = - ct.box(arr(idx)) - - def update(idx: Int, elem: T) = - arr(idx) = ct.unbox(elem) - - def length: Int = arr.length - - override def clone(): VCShortArray[T] = { - new VCShortArray[T](arr.clone(), ct) - } - - override def toString: String = { - "[" + ct.runtimeClass - } - -} - - -abstract class VCLongPrototype(val underlying: Long) extends VCPrototype {} - -abstract class VCLongCasePrototype(underlying: Long) extends VCLongPrototype(underlying) with Product1[Long] { - - final def _1: Long = underlying - - override final def hashCode(): Int = { - underlying.hashCode() - } - - override final def toString: String = { - s"$productPrefix($underlying)" - } -} - -abstract class VCLongCompanion[T <: VCLongPrototype] extends ClassTag[T] { - def box(underlying: Long): T - final def unbox(boxed: T) = boxed.underlying - - implicit def classTag: this.type = this - override def newArray(len: Int): Array[T] = - new VCLongArray(this, len).asInstanceOf[Array[T]] - - - final def _1$extension(underlying: Long) = underlying - final def hashCode$extension(underlying: Long) = underlying.hashCode() - final def toString$extension(underlying: Long) = s"${productPrefix$extension(underlying)}($underlying)" - def productPrefix$extension(underlying: Long): String -} - -final class VCLongArray[T <: VCLongPrototype] private (val arr: Array[Long], val ct: VCLongCompanion[T]) - extends VCArrayPrototype[T] { - def this(ct: VCLongCompanion[T], sz: Int) = - this(new Array[Long](sz), ct) - - def apply(idx: Int) = - ct.box(arr(idx)) - - def update(idx: Int, elem: T) = - arr(idx) = ct.unbox(elem) - - def length: Int = arr.length - - override def clone(): VCLongArray[T] = { - new VCLongArray[T](arr.clone(), ct) - } - - override def toString: String = { - "[" + ct.runtimeClass - } -} - - -abstract class VCIntPrototype(val underlying: Int) extends VCPrototype {} - -abstract class VCIntCasePrototype(underlying: Int) extends VCIntPrototype(underlying) with Product1[Int] { - - final def _1: Int = underlying - - override final def hashCode(): Int = { - underlying.hashCode() - } - - override final def toString: String = { - s"$productPrefix($underlying)" - } -} - -abstract class VCIntCompanion[T <: VCIntPrototype] extends ClassTag[T] { - def box(underlying: Int): T - final def unbox(boxed: T) = boxed.underlying - - implicit def classTag: this.type = this - override def newArray(len: Int): Array[T] = - new VCIntArray(this, len).asInstanceOf[Array[T]] - - - final def _1$extension(underlying: Int) = underlying - final def hashCode$extension(underlying: Int) = underlying.hashCode() - final def toString$extension(underlying: Int) = s"${productPrefix$extension(underlying)}($underlying)" - def productPrefix$extension(underlying: Int): String -} - -final class VCIntArray[T <: VCIntPrototype] private (val arr: Array[Int], val ct: VCIntCompanion[T]) - extends VCArrayPrototype[T] { - def this(ct: VCIntCompanion[T], sz: Int) = - this(new Array[Int](sz), ct) - - def apply(idx: Int) = - ct.box(arr(idx)) - def update(idx: Int, elem: T) = - arr(idx) = ct.unbox(elem) - def length: Int = arr.length - - override def clone(): VCIntArray[T] = { - new VCIntArray[T](arr.clone(), ct) - } - - override def toString: String = { - "[" + ct.runtimeClass - } -} - - -abstract class VCDoublePrototype(val underlying: Double) extends VCPrototype {} - -abstract class VCDoubleCasePrototype(underlying: Double) extends VCDoublePrototype(underlying) with Product1[Double] { - - final def _1: Double = underlying - - override final def hashCode(): Int = { - underlying.hashCode() - } - - override final def toString: String = { - s"$productPrefix($underlying)" - } -} - -abstract class VCDoubleCompanion[T <: VCDoublePrototype] extends ClassTag[T] { - def box(underlying: Double): T - final def unbox(boxed: T) = boxed.underlying - - implicit def classTag: this.type = this - override def newArray(len: Int): Array[T] = - new VCDoubleArray(this, len).asInstanceOf[Array[T]] - - - final def _1$extension(underlying: Double) = underlying - final def hashCode$extension(underlying: Double) = underlying.hashCode() - final def toString$extension(underlying: Double) = s"${productPrefix$extension(underlying)}($underlying)" - def productPrefix$extension(underlying: Double): String -} - -final class VCDoubleArray[T <: VCDoublePrototype] private (val arr: Array[Double], val ct: VCDoubleCompanion[T]) - extends VCArrayPrototype[T] { - def this(ct: VCDoubleCompanion[T], sz: Int) = - this(new Array[Double](sz), ct) - - def apply(idx: Int) = - ct.box(arr(idx)) - def update(idx: Int, elem: T) = - arr(idx) = ct.unbox(elem) - def length: Int = arr.length - - override def clone(): VCDoubleArray[T] = { - new VCDoubleArray[T](arr.clone(), ct) - } - - override def toString: String = { - "[" + ct.runtimeClass - } -} - - -abstract class VCBooleanPrototype(val underlying: Boolean) extends VCPrototype {} - -abstract class VCBooleanCasePrototype(underlying: Boolean) extends VCBooleanPrototype(underlying) with Product1[Boolean] { - - final def _1: Boolean = underlying - - override final def hashCode(): Int = { - underlying.hashCode() - } - - override final def toString: String = { - s"$productPrefix($underlying)" - } -} - -abstract class VCBooleanCompanion[T <: VCBooleanPrototype] extends ClassTag[T] { - def box(underlying: Boolean): T - final def unbox(boxed: T) = boxed.underlying - - implicit def classTag: this.type = this - override def newArray(len: Int): Array[T] = - new VCBooleanArray(this, len).asInstanceOf[Array[T]] - - - final def _1$extension(underlying: Boolean) = underlying - final def hashCode$extension(underlying: Boolean) = underlying.hashCode() - final def toString$extension(underlying: Boolean) = s"${productPrefix$extension(underlying)}($underlying)" - def productPrefix$extension(underlying: Boolean): String -} - -final class VCBooleanArray[T <: VCBooleanPrototype] private (val arr: Array[Boolean], val ct: VCBooleanCompanion[T]) - extends VCArrayPrototype[T] { - def this(ct: VCBooleanCompanion[T], sz: Int) = - this(new Array[Boolean](sz), ct) - - def apply(idx: Int) = - ct.box(arr(idx)) - - def update(idx: Int, elem: T) = - arr(idx) = ct.unbox(elem) - - def length: Int = arr.length - - override def clone(): VCBooleanArray[T] = { - new VCBooleanArray[T](arr.clone(), ct) - } - - override def toString: String = { - "[" + ct.runtimeClass - } -} - - -abstract class VCCharPrototype(val underlying: Char) extends VCPrototype {} - -abstract class VCCharCasePrototype(underlying: Char) extends VCCharPrototype(underlying) with Product1[Char] { - - final def _1: Char = underlying - - override final def hashCode(): Int = { - underlying.hashCode() - } - - override final def toString: String = { - s"$productPrefix($underlying)" - } - - // subclasses are expected to implement equals, productPrefix, and canEqual -} - -abstract class VCCharCompanion[T <: VCCharPrototype] extends ClassTag[T] { - def box(underlying: Char): T - final def unbox(boxed: T) = boxed.underlying - - implicit def classTag: this.type = this - override def newArray(len: Int): Array[T] = - new VCCharArray(this, len).asInstanceOf[Array[T]] - - - final def _1$extension(underlying: Char) = underlying - final def hashCode$extension(underlying: Char) = underlying.hashCode() - final def toString$extension(underlying: Char) = s"${productPrefix$extension(underlying)}($underlying)" - def productPrefix$extension(underlying: Char): String -} - -final class VCCharArray[T <: VCCharPrototype] private (val arr: Array[Char], val ct: VCCharCompanion[T]) - extends VCArrayPrototype[T] { - def this(ct: VCCharCompanion[T], sz: Int) = - this(new Array[Char](sz), ct) - - def apply(idx: Int) = - ct.box(arr(idx)) - def update(idx: Int, elem: T) = - arr(idx) = ct.unbox(elem) - def length: Int = arr.length - - override def clone(): VCCharArray[T] = { - new VCCharArray[T](arr.clone(), ct) - } - - override def toString: String = { - "[" + ct.runtimeClass - } -} - - -abstract class VCBytePrototype(val underlying: Byte) extends VCPrototype {} - -abstract class VCByteCasePrototype(underlying: Byte) extends VCBytePrototype(underlying) with Product1[Byte] { - - final def _1: Byte = underlying - - override final def hashCode(): Int = { - underlying.hashCode() - } - - override final def toString: String = { - s"$productPrefix($underlying)" - } -} - -abstract class VCByteCompanion[T <: VCBytePrototype] extends ClassTag[T] { - def box(underlying: Byte): T - final def unbox(boxed: T) = boxed.underlying - - implicit def classTag: this.type = this - override def newArray(len: Int): Array[T] = - new VCByteArray(this, len).asInstanceOf[Array[T]] - - - final def _1$extension(underlying: Byte) = underlying - final def hashCode$extension(underlying: Byte) = underlying.hashCode() - final def toString$extension(underlying: Byte) = s"${productPrefix$extension(underlying)}($underlying)" - def productPrefix$extension(underlying: Byte): String -} - -final class VCByteArray[T <: VCBytePrototype] private (val arr: Array[Byte], val ct: VCByteCompanion[T]) - extends VCArrayPrototype[T] { - def this(ct: VCByteCompanion[T], sz: Int) = - this(new Array[Byte](sz), ct) - - def apply(idx: Int) = - ct.box(arr(idx)) - def update(idx: Int, elem: T) = - arr(idx) = ct.unbox(elem) - def length: Int = arr.length - - override def clone(): VCByteArray[T] = { - new VCByteArray[T](arr.clone(), ct) - } - - override def toString: String = { - "[" + ct.runtimeClass - } - -} -