Skip to content

Commit ad5b08c

Browse files
committed
Merge pull request #485 from dotty-staging/interceptedM
Simplify InterceptedMethods. Fix #439
2 parents b6c3ab9 + afaec82 commit ad5b08c

File tree

1 file changed

+34
-48
lines changed

1 file changed

+34
-48
lines changed

src/dotty/tools/dotc/transform/InterceptedMethods.scala

Lines changed: 34 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -28,42 +28,35 @@ import dotty.tools.dotc.core.Denotations.SingleDenotation
2828
import dotty.tools.dotc.core.SymDenotations.SymDenotation
2929
import 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

Comments
 (0)