-
Notifications
You must be signed in to change notification settings - Fork 397
Removes spurious js.AsInstanceOf around the js.LinkTimeIf #5210
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
case Apply(fun, List(cond, thenp, elsep)) | ||
if fun.symbol == jsDefinitions.LinkingInfo_linkTimeIf && | ||
thenp.tpe <:< targetTpe && elsep.tpe <:< targetTpe => | ||
val genObj = genExpr(obj).asInstanceOf[js.LinkTimeIf] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The original change already looks good to me, but maybe we can match against genExpr(obj)
and abort if it's not typed js.LinkTimeIf
? That would display informative error when the compiler generates an unexpected IR by accident.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Indeed, that would provide more context (especially with a message that includes the current position) in case something fails in the future.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
IMO we should also have a test in the compiler tests' OptimizationTest
. I think the "impl pattern" should be tested there, with a hasNot
assertion that makes sure there is no js.AsInstanceOf
in the produced code.
case Apply(fun, List(cond, thenp, elsep)) | ||
if fun.symbol == jsDefinitions.LinkingInfo_linkTimeIf && | ||
thenp.tpe <:< targetTpe && elsep.tpe <:< targetTpe => | ||
val genObj = genExpr(obj).asInstanceOf[js.LinkTimeIf] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Indeed, that would provide more context (especially with a message that includes the current position) in case something fails in the future.
/* This is an optimization for `linkTimeIf(cond)(thenp)(elsep).asInstanceOf[T]`. | ||
* If both `thenp` and `elsep` are subtypes of `T`, the `asInstanceOf` | ||
* is redundant and can be removed. | ||
*/ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's elaborate a bit more on why this is useful:
/* This is an optimization for `linkTimeIf(cond)(thenp)(elsep).asInstanceOf[T]`. | |
* If both `thenp` and `elsep` are subtypes of `T`, the `asInstanceOf` | |
* is redundant and can be removed. | |
*/ | |
/* This is an optimization for `linkTimeIf(cond)(thenp)(elsep).asInstanceOf[T]`. | |
* If both `thenp` and `elsep` are subtypes of `T`, the `asInstanceOf` | |
* is redundant and can be removed. The optimizer already routinely performs | |
* this optimization. However, that comes too late for the module instance | |
* field alias analysis performed by `IncOptimizer`. In that case, while the | |
* desugarer removes the `LinkTimeIf`, the extra `AsInstanceOf` prevents | |
* aliasing the field. Removing the cast ahead of time in the compiler allows | |
* field aliases to be recognized in the presence of `LinkTimeIf`s. | |
*/ |
} | ||
|
||
@Test def implPattern(): Unit = { | ||
sealed abstract class ArrayImpl { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This abstract class and its two object
s should static for the pattern to be the one we are interested in. You can put them in the companion object of LinkTimeIfTest
. We often do that.
When B<:A and C<:A, `linkTimeIf[A](cond){ B }{ C }` would generate an `.asInstanceOf[A]` that casts the resulting value to a supertype. However, this cast is redundant, as the linker will prune one branch at linktime, and the remaining expression is already known to be a compatible type. This commit eliminates the surrounding `.asInstanceOf` around the `linkTimeIf[T]` when both `thenp` and `elsep` are surely subtypes of `T`. The optimizer already routinely performs this optimization. However, that comes too late for the module instance field alias analysis performed by `IncOptimizer`. In that case, while the desugarer removes the `LinkTimeIf`, the extra `AsInstanceOf` prevents aliasing the field. Removing the cast ahead of time in the compiler allows field aliases to be recognized in the presence of `LinkTimeIf`s. context: scala-js#5168 Co-authored-by: Sébastien Doeraene <sjrdoeraene@gmail.com>
a3a0b43
to
9bb267c
Compare
Cherry-picking a change from #5168 (comment) :)
When B<:A and C<:A,
linkTimeIf[A](cond){ B }{ C }
would generate an.asInstanceOf[A]
that casts the resulting value to a supertype.However, this cast is redundant,
as the linker will prune one branch at linktime,
and the remaining expression is already known to be a compatible type.
This commit eliminates the surrounding
.asInstanceOf
around thelinkTimeIf[T]
when boththenp
andelsep
are surely subtypes ofT
.context: #5168