@@ -28,42 +28,35 @@ import dotty.tools.dotc.core.Denotations.SingleDenotation
2828import dotty .tools .dotc .core .SymDenotations .SymDenotation
2929import StdNames ._
3030
31- // @DarkDimius The getClass scheme changed. We no longer can have
32- // two different methods in Any and Object. The tests pass but I
33- // am not sure Intercepted methods treats getClass right now.
34- // Please check and delete comment when done.
3531/** Replace member references as follows:
3632 *
37- * - `x == y` for == in class Any becomes `x equals y ` with equals in class Object .
38- * - `x != y ` for != in class Any becomes `!(x equals y)` with equals in class Object.
39- * - `x.##` for ## in other classes becomes calls to ScalaRunTime.hash,
33+ * - `x != y` for != in class Any becomes `!(x == y) ` with == in class Any .
34+ * - `x.## ` for ## in NullClass becomes `0`
35+ * - `x.##` for ## in Any becomes calls to ScalaRunTime.hash,
4036 * using the most precise overload available
4137 * - `x.getClass` for getClass in primitives becomes `x.getClass` with getClass in class Object.
4238 */
43- class InterceptedMethods extends MiniPhaseTransform { thisTransform =>
39+ class InterceptedMethods extends MiniPhaseTransform {
40+ thisTransform =>
4441
4542 import tpd ._
4643
4744 override def phaseName : String = " intercepted"
4845
49- private var getClassMethods : Set [Symbol ] = _
50- private var poundPoundMethods : Set [Symbol ] = _
51- private var Any_comparisons : Set [Symbol ] = _
52- private var interceptedMethods : Set [Symbol ] = _
5346 private var primitiveGetClassMethods : Set [Symbol ] = _
5447
48+ var Any_## : Symbol = _ // cached for performance reason
49+
5550 /** perform context-dependant initialization */
5651 override def prepareForUnit (tree : Tree )(implicit ctx : Context ) = {
57- poundPoundMethods = Set (defn.Any_## )
58- Any_comparisons = Set (defn.Any_== , defn.Any_!= )
59- interceptedMethods = poundPoundMethods ++ Any_comparisons
52+ this .Any_## = defn.Any_##
6053 primitiveGetClassMethods = Set [Symbol ]() ++ defn.ScalaValueClasses .map(x => x.requiredMethod(nme.getClass_))
6154 this
6255 }
6356
6457 // this should be removed if we have guarantee that ## will get Apply node
6558 override def transformSelect (tree : tpd.Select )(implicit ctx : Context , info : TransformerInfo ): Tree = {
66- if (tree.symbol.isTerm && poundPoundMethods.contains( tree.symbol.asTerm)) {
59+ if (tree.symbol.isTerm && ( Any_## eq tree.symbol.asTerm)) {
6760 val rewrite = poundPoundValue(tree.qualifier)
6861 ctx.log(s " $phaseName rewrote $tree to $rewrite" )
6962 rewrite
@@ -103,43 +96,36 @@ class InterceptedMethods extends MiniPhaseTransform { thisTransform =>
10396 s " that means the intercepted methods set doesn't match the code " )
10497 tree
10598 }
106- if (tree.fun.symbol.isTerm &&
107- (interceptedMethods contains tree.fun.symbol.asTerm)) {
108- val rewrite : Tree = tree.fun match {
109- case Select (qual, name) =>
110- if (poundPoundMethods contains tree.fun.symbol.asTerm) {
111- poundPoundValue(qual)
112- } else if (Any_comparisons contains tree.fun.symbol.asTerm) {
113- if (tree.fun.symbol eq defn.Any_== ) {
114- qual.selectWithSig(defn.Any_equals ).appliedToArgs(tree.args)
115- } else if (tree.fun.symbol eq defn.Any_!= ) {
116- qual.selectWithSig(defn.Any_equals ).appliedToArgs(tree.args).select(defn.Boolean_! )
117- } else unknown
118- } /* else if (isPrimitiveValueClass(qual.tpe.typeSymbol)) {
99+ lazy val Select (qual, _) = tree.fun
100+ val Any_## = this .Any_##
101+ val Any_!= = defn.Any_!=
102+ val rewrite : Tree = tree.fun.symbol match {
103+ case Any_## =>
104+ poundPoundValue(qual)
105+ case Any_!= =>
106+ qual.select(defn.Any_== ).appliedToArgs(tree.args).select(defn.Boolean_! )
107+ /*
108+ /* else if (isPrimitiveValueClass(qual.tpe.typeSymbol)) {
119109 // todo: this is needed to support value classes
120110 // Rewrite 5.getClass to ScalaRunTime.anyValClass(5)
121111 global.typer.typed(gen.mkRuntimeCall(nme.anyValClass,
122112 List(qual, typer.resolveClassTag(tree.pos, qual.tpe.widen))))
123113 }*/
124- else if (primitiveGetClassMethods.contains(tree.fun.symbol)) {
125- // if we got here then we're trying to send a primitive getClass method to either
126- // a) an Any, in which cage Object_getClass works because Any erases to object. Or
127- //
128- // b) a non-primitive, e.g. because the qualifier's type is a refinement type where one parent
129- // of the refinement is a primitive and another is AnyRef. In that case
130- // we get a primitive form of _getClass trying to target a boxed value
131- // so we need replace that method name with Object_getClass to get correct behavior.
132- // See SI-5568.
133- qual.selectWithSig(defn.Any_getClass ).appliedToNone
134- } else {
135- unknown
136- }
137- case _ =>
138- unknown
139- }
140- ctx.log(s " $phaseName rewrote $tree to $rewrite" )
141- rewrite
114+ */
115+ case t if primitiveGetClassMethods.contains(t) =>
116+ // if we got here then we're trying to send a primitive getClass method to either
117+ // a) an Any, in which cage Object_getClass works because Any erases to object. Or
118+ //
119+ // b) a non-primitive, e.g. because the qualifier's type is a refinement type where one parent
120+ // of the refinement is a primitive and another is AnyRef. In that case
121+ // we get a primitive form of _getClass trying to target a boxed value
122+ // so we need replace that method name with Object_getClass to get correct behavior.
123+ // See SI-5568.
124+ qual.selectWithSig(defn.Any_getClass ).appliedToNone
125+ case _ =>
126+ tree
142127 }
143- else tree
128+ ctx.log(s " $phaseName rewrote $tree to $rewrite" )
129+ rewrite
144130 }
145131}
0 commit comments