@@ -62,51 +62,38 @@ class ExtensionMethods extends MiniPhase with DenotTransformer with FullParamete
6262 val decls1 = cinfo.decls.cloneScope
6363 val moduleSym = moduleClassSym.symbol.asClass
6464
65- var newSuperClass : Type = null
66-
67- ctx.atPhase(thisPhase.next) { implicit ctx =>
68- // In Scala 2, extension methods are added before pickling so we should
69- // not generate them again.
70- if (! (valueClass is Scala2x )) ctx.atPhase(thisPhase) { implicit ctx =>
71- for (decl <- valueClass.classInfo.decls) {
72- if (isMethodWithExtension(decl)) {
73- val meth = createExtensionMethod(decl, moduleClassSym.symbol)
74- decls1.enter(meth)
75- // Workaround #1895: force denotation of `meth` to be
76- // at phase where `meth` is entered into the decls of a class
77- meth.denot(ctx.withPhase(thisPhase.next))
78- }
79- }
80- }
81-
82- val underlying = valueErasure(underlyingOfValueClass(valueClass))
83- val evt = ErasedValueType (valueClass.typeRef, underlying)
84- val u2evtSym = ctx.newSymbol(moduleSym, nme.U2EVT , Synthetic | Method ,
85- MethodType (List (nme.x_0), List (underlying), evt))
86- val evt2uSym = ctx.newSymbol(moduleSym, nme.EVT2U , Synthetic | Method ,
87- MethodType (List (nme.x_0), List (evt), underlying))
88-
89- val defn = ctx.definitions
90-
91- val underlyingCls = underlying.classSymbol
92- val underlyingClsName =
93- if (underlyingCls.isNumericValueClass || underlyingCls == defn.BooleanClass ) underlyingCls.name
94- else nme.Object
95-
96- val syp = ctx.requiredClass(s " dotty.runtime.vc.VC ${underlyingClsName}Companion " ).asClass
97-
98- newSuperClass = tpd.ref(syp).select(nme.CONSTRUCTOR ).appliedToType(valueClass.typeRef).tpe.resultType
99-
100- decls1.enter(u2evtSym)
101- decls1.enter(evt2uSym)
65+ def enterInModuleClass (sym : Symbol ): Unit = {
66+ decls1.enter(sym)
67+ // This is tricky: in this denotation transformer, we transform
68+ // companion modules of value classes by adding methods to them.
69+ // Running the transformer will create these methods, but they're
70+ // only valid once it has finished running. This means we cannot use
71+ // `ctx.withPhase(thisPhase.next)` here without potentially running
72+ // into cycles. Instead, we manually set their validity after having
73+ // created them to match the validity of the owner transformed
74+ // denotation.
75+ sym.validFor = thisPhase.validFor
10276 }
10377
104- // Add the extension methods, the cast methods u2evt$ and evt2u$, and a VC*Companion superclass
105- moduleClassSym.copySymDenotation(info =
106- cinfo.derivedClassInfo(
107- // FIXME: use of VC*Companion superclasses is disabled until the conflicts with SyntheticMethods are solved.
108- // classParents = List(newSuperClass)
109- decls = decls1))
78+ // Create extension methods, except if the class comes from Scala 2
79+ // because it adds extension methods before pickling.
80+ if (! (valueClass.is(Scala2x )))
81+ for (decl <- valueClass.classInfo.decls)
82+ if (isMethodWithExtension(decl))
83+ enterInModuleClass(createExtensionMethod(decl, moduleClassSym.symbol))
84+
85+ // Create synthetic methods to cast values between the underlying type
86+ // and the ErasedValueType. These methods are removed in ElimErasedValueType.
87+ val underlying = valueErasure(underlyingOfValueClass(valueClass))
88+ val evt = ErasedValueType (valueClass.typeRef, underlying)
89+ val u2evtSym = ctx.newSymbol(moduleSym, nme.U2EVT , Synthetic | Method ,
90+ MethodType (List (nme.x_0), List (underlying), evt))
91+ val evt2uSym = ctx.newSymbol(moduleSym, nme.EVT2U , Synthetic | Method ,
92+ MethodType (List (nme.x_0), List (evt), underlying))
93+ enterInModuleClass(u2evtSym)
94+ enterInModuleClass(evt2uSym)
95+
96+ moduleClassSym.copySymDenotation(info = cinfo.derivedClassInfo(decls = decls1))
11097 case _ =>
11198 moduleClassSym
11299 }
0 commit comments