@@ -28,42 +28,35 @@ import dotty.tools.dotc.core.Denotations.SingleDenotation
28
28
import dotty .tools .dotc .core .SymDenotations .SymDenotation
29
29
import StdNames ._
30
30
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.
35
31
/** Replace member references as follows:
36
32
*
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,
40
36
* using the most precise overload available
41
37
* - `x.getClass` for getClass in primitives becomes `x.getClass` with getClass in class Object.
42
38
*/
43
- class InterceptedMethods extends MiniPhaseTransform { thisTransform =>
39
+ class InterceptedMethods extends MiniPhaseTransform {
40
+ thisTransform =>
44
41
45
42
import tpd ._
46
43
47
44
override def phaseName : String = " intercepted"
48
45
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 ] = _
53
46
private var primitiveGetClassMethods : Set [Symbol ] = _
54
47
48
+ var Any_## : Symbol = _ // cached for performance reason
49
+
55
50
/** perform context-dependant initialization */
56
51
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_##
60
53
primitiveGetClassMethods = Set [Symbol ]() ++ defn.ScalaValueClasses .map(x => x.requiredMethod(nme.getClass_))
61
54
this
62
55
}
63
56
64
57
// this should be removed if we have guarantee that ## will get Apply node
65
58
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)) {
67
60
val rewrite = poundPoundValue(tree.qualifier)
68
61
ctx.log(s " $phaseName rewrote $tree to $rewrite" )
69
62
rewrite
@@ -103,43 +96,36 @@ class InterceptedMethods extends MiniPhaseTransform { thisTransform =>
103
96
s " that means the intercepted methods set doesn't match the code " )
104
97
tree
105
98
}
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)) {
119
109
// todo: this is needed to support value classes
120
110
// Rewrite 5.getClass to ScalaRunTime.anyValClass(5)
121
111
global.typer.typed(gen.mkRuntimeCall(nme.anyValClass,
122
112
List(qual, typer.resolveClassTag(tree.pos, qual.tpe.widen))))
123
113
}*/
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
142
127
}
143
- else tree
128
+ ctx.log(s " $phaseName rewrote $tree to $rewrite" )
129
+ rewrite
144
130
}
145
131
}
0 commit comments