From 40cc43097a030f95d58a2a414590b8a78d43cf74 Mon Sep 17 00:00:00 2001 From: Guillaume Martres Date: Fri, 1 Jun 2018 18:21:07 +0200 Subject: [PATCH 1/3] Remove unused code meant to support arrays of value classes Efficient arrays of value classes have been abandoned for now, see https://github.com/lampepfl/dotty/issues/1558 --- .../dotc/transform/ExtensionMethods.scala | 19 +- .../src/dotty/runtime/vc/VCPrototype.scala | 486 ------------------ 2 files changed, 2 insertions(+), 503 deletions(-) delete mode 100644 library/src/dotty/runtime/vc/VCPrototype.scala diff --git a/compiler/src/dotty/tools/dotc/transform/ExtensionMethods.scala b/compiler/src/dotty/tools/dotc/transform/ExtensionMethods.scala index b617dbd1e854..9fb6fe36cc29 100644 --- a/compiler/src/dotty/tools/dotc/transform/ExtensionMethods.scala +++ b/compiler/src/dotty/tools/dotc/transform/ExtensionMethods.scala @@ -86,27 +86,12 @@ class ExtensionMethods extends MiniPhase with DenotTransformer with FullParamete 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) } - // 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)) + // Add the extension methods and the cast methods u2evt$ and evt2u$ + 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 - } - -} - From 7aa1ee2a01736e8ffce21ca08ba5041795d8a836 Mon Sep 17 00:00:00 2001 From: Guillaume Martres Date: Fri, 1 Jun 2018 18:04:42 +0200 Subject: [PATCH 2/3] Fix DenotTransformer#validFor This method was unused so far but will be used in the next commit. The validity period of a transformed denotation starts at the phase after the transformer has been run. --- compiler/src/dotty/tools/dotc/core/DenotTransformers.scala | 4 ++-- .../src/dotty/tools/dotc/transform/ExtensionMethods.scala | 2 -- 2 files changed, 2 insertions(+), 4 deletions(-) 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/transform/ExtensionMethods.scala b/compiler/src/dotty/tools/dotc/transform/ExtensionMethods.scala index 9fb6fe36cc29..66269af416b3 100644 --- a/compiler/src/dotty/tools/dotc/transform/ExtensionMethods.scala +++ b/compiler/src/dotty/tools/dotc/transform/ExtensionMethods.scala @@ -62,8 +62,6 @@ 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. From 44a305f2023dd59701f7e4a2beb09d1d94f2c1ca Mon Sep 17 00:00:00 2001 From: Guillaume Martres Date: Fri, 1 Jun 2018 18:42:57 +0200 Subject: [PATCH 3/3] Fix #1895: Use proper validity period for extension methods When we create a symbol in a DenotationTransformer, we cannot safely create it at phase `thisPhase.next` since this can lead to cycles. This is why we created extension methods at phase `thisPhase`, but they're not really valid at that point since they're only entered in their owner once the transformer has been run. This lead to stale symbol errors which were worked around in 51a458efeeebfeed6c357d56cf8afe5b06e86724 but the fix is incomplete and does not work with #4604 because that PR moves the ExtensionMethods phase around. This commit removes all the workarounds and uses a simpler solution: create the symbols at phase `thisPhase` but set their validity period to match the validity of the owner transformed denotation. --- .../tools/dotc/core/SymDenotations.scala | 10 ++-- .../dotc/transform/ExtensionMethods.scala | 54 ++++++++++--------- 2 files changed, 32 insertions(+), 32 deletions(-) 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 66269af416b3..e9dcab37abd4 100644 --- a/compiler/src/dotty/tools/dotc/transform/ExtensionMethods.scala +++ b/compiler/src/dotty/tools/dotc/transform/ExtensionMethods.scala @@ -62,33 +62,37 @@ class ExtensionMethods extends MiniPhase with DenotTransformer with FullParamete val decls1 = cinfo.decls.cloneScope val moduleSym = moduleClassSym.symbol.asClass - 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)) - - 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 and the cast methods u2evt$ and evt2u$ + // 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