Skip to content

Commit ec794f3

Browse files
committed
Add special case to init checker to always allow certain methods
Closes #14275 - Treats mehtods `ne`, `eq`, `isInstanceOf`, and `asInstanceOf` as safe to call, regardless of initialization Signed the CLA - @Xavientois Review by @liufengyun
1 parent 1130c52 commit ec794f3

File tree

4 files changed

+49
-0
lines changed

4 files changed

+49
-0
lines changed

compiler/src/dotty/tools/dotc/transform/init/Semantic.scala

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -596,8 +596,15 @@ object Semantic {
596596
&& meth.owner.is(Flags.Module)
597597
&& meth.owner.companionClass.is(Flags.Case)
598598

599+
def isAlwaysSafe(meth: Symbol) =
600+
(meth eq defn.Object_eq)
601+
|| (meth eq defn.Object_ne)
602+
|| (meth eq defn.Any_isInstanceOf)
603+
599604
// fast track if the current object is already initialized
600605
if promoted.isCurrentObjectPromoted then Result(Hot, Nil)
606+
else if isAlwaysSafe(meth) then Result(Hot, Nil)
607+
else if meth eq defn.Any_asInstanceOf then Result(value, Nil)
601608
else value match {
602609
case Hot =>
603610
if isSyntheticApply(meth) then
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
final class MyAsInstanceOfClass(o: MyAsInstanceOfClass) {
2+
val other: MyAsInstanceOfClass = {
3+
if (o.asInstanceOf[MyAsInstanceOfClass].oRef ne null) o // error
4+
else new MyAsInstanceOfClass(this)
5+
}
6+
val oRef = o
7+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
final class MyNeClass(o: MyNeClass) {
2+
val other: MyNeClass = {
3+
if (o ne null) o // o is cold, but ne is always valid
4+
else new MyNeClass(this)
5+
}
6+
}
7+
8+
final class MyEqClass(o: MyEqClass) {
9+
val other: MyEqClass = {
10+
if (o eq null) new MyEqClass(this) // o is cold, but eq is always valid
11+
else o
12+
}
13+
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
final class MyIsInstanceOfClass(o: MyIsInstanceOfClass) {
2+
val other: MyIsInstanceOfClass = {
3+
if (!o.isInstanceOf[Object]) new MyIsInstanceOfClass(this) // o is cold, but isInstanceOf is always valid
4+
else o
5+
}
6+
}
7+
8+
final class MyAsInstanceOfClass(o: MyAsInstanceOfClass) {
9+
val other: MyAsInstanceOfClass = {
10+
if (o.asInstanceOf[Object] ne null) o // o is cold, but ne and AsInstanceOf is always valid
11+
else new MyAsInstanceOfClass(this)
12+
}
13+
}
14+
15+
final class MyAsInstanceOfFieldClass(o: MyAsInstanceOfFieldClass) {
16+
val oRef = o
17+
val other: MyAsInstanceOfFieldClass = {
18+
if (this.asInstanceOf[MyAsInstanceOfFieldClass].oRef ne null) oRef // o is cold, but ne and AsInstanceOf is always valid
19+
else new MyAsInstanceOfFieldClass(this)
20+
}
21+
}
22+

0 commit comments

Comments
 (0)