@@ -62,51 +62,38 @@ class ExtensionMethods extends MiniPhase with DenotTransformer with FullParamete
62
62
val decls1 = cinfo.decls.cloneScope
63
63
val moduleSym = moduleClassSym.symbol.asClass
64
64
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
102
76
}
103
77
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))
110
97
case _ =>
111
98
moduleClassSym
112
99
}
0 commit comments