Skip to content

Commit

Permalink
Merge pull request #14352 from Xavientois/eq-ne-always-valid-init-check
Browse files Browse the repository at this point in the history
Add special case to init checker to always allow certain methods
  • Loading branch information
olhotak authored Feb 2, 2022
2 parents e5c8238 + ec794f3 commit 8bb2453
Show file tree
Hide file tree
Showing 4 changed files with 49 additions and 0 deletions.
7 changes: 7 additions & 0 deletions compiler/src/dotty/tools/dotc/transform/init/Semantic.scala
Original file line number Diff line number Diff line change
Expand Up @@ -596,8 +596,15 @@ object Semantic {
&& meth.owner.is(Flags.Module)
&& meth.owner.companionClass.is(Flags.Case)

def isAlwaysSafe(meth: Symbol) =
(meth eq defn.Object_eq)
|| (meth eq defn.Object_ne)
|| (meth eq defn.Any_isInstanceOf)

// fast track if the current object is already initialized
if promoted.isCurrentObjectPromoted then Result(Hot, Nil)
else if isAlwaysSafe(meth) then Result(Hot, Nil)
else if meth eq defn.Any_asInstanceOf then Result(value, Nil)
else value match {
case Hot =>
if isSyntheticApply(meth) then
Expand Down
7 changes: 7 additions & 0 deletions tests/init/neg/as-instance-of-cold-field-access.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
final class MyAsInstanceOfClass(o: MyAsInstanceOfClass) {
val other: MyAsInstanceOfClass = {
if (o.asInstanceOf[MyAsInstanceOfClass].oRef ne null) o // error
else new MyAsInstanceOfClass(this)
}
val oRef = o
}
13 changes: 13 additions & 0 deletions tests/init/pos/eq-ne-always-valid.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
final class MyNeClass(o: MyNeClass) {
val other: MyNeClass = {
if (o ne null) o // o is cold, but ne is always valid
else new MyNeClass(this)
}
}

final class MyEqClass(o: MyEqClass) {
val other: MyEqClass = {
if (o eq null) new MyEqClass(this) // o is cold, but eq is always valid
else o
}
}
22 changes: 22 additions & 0 deletions tests/init/pos/instance-of-always-valid.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
final class MyIsInstanceOfClass(o: MyIsInstanceOfClass) {
val other: MyIsInstanceOfClass = {
if (!o.isInstanceOf[Object]) new MyIsInstanceOfClass(this) // o is cold, but isInstanceOf is always valid
else o
}
}

final class MyAsInstanceOfClass(o: MyAsInstanceOfClass) {
val other: MyAsInstanceOfClass = {
if (o.asInstanceOf[Object] ne null) o // o is cold, but ne and AsInstanceOf is always valid
else new MyAsInstanceOfClass(this)
}
}

final class MyAsInstanceOfFieldClass(o: MyAsInstanceOfFieldClass) {
val oRef = o
val other: MyAsInstanceOfFieldClass = {
if (this.asInstanceOf[MyAsInstanceOfFieldClass].oRef ne null) oRef // o is cold, but ne and AsInstanceOf is always valid
else new MyAsInstanceOfFieldClass(this)
}
}

0 comments on commit 8bb2453

Please sign in to comment.