Skip to content

Commit 266ddbf

Browse files
committed
Scala.js: Remove spurious js.AsInstanceOf around js.LinkTimeIf.
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 link time, 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 known to be 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. This commit is a forward port of the Scala.js commit scala-js/scala-js@9bb267c
1 parent 82e305d commit 266ddbf

File tree

1 file changed

+23
-1
lines changed

1 file changed

+23
-1
lines changed

compiler/src/dotty/tools/backend/sjs/JSCodeGen.scala

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3321,7 +3321,29 @@ class JSCodeGen()(using genCtx: Context) {
33213321
val genReceiver = genExpr(receiver)
33223322

33233323
if (sym == defn.Any_asInstanceOf) {
3324-
genAsInstanceOf(genReceiver, to)
3324+
receiver match {
3325+
/* This is an optimization for `linkTimeIf(cond)(thenp)(elsep).asInstanceOf[T]`.
3326+
* If both `thenp` and `elsep` are subtypes of `T`, the `asInstanceOf`
3327+
* is redundant and can be removed. The optimizer already routinely performs
3328+
* this optimization. However, that comes too late for the module instance
3329+
* field alias analysis performed by `IncOptimizer`. In that case, while the
3330+
* desugarer removes the `LinkTimeIf`, the extra `AsInstanceOf` prevents
3331+
* aliasing the field. Removing the cast ahead of time in the compiler allows
3332+
* field aliases to be recognized in the presence of `LinkTimeIf`s.
3333+
*/
3334+
case Apply(innerFun, List(cond, thenp, elsep))
3335+
if innerFun.symbol == jsdefn.LinkingInfo_linkTimeIf &&
3336+
thenp.tpe <:< to && elsep.tpe <:< to =>
3337+
val genReceiver1 = genReceiver match {
3338+
case genReceiver: js.LinkTimeIf =>
3339+
genReceiver
3340+
case _ =>
3341+
throw FatalError(s"Unexpected tree $genReceiver is generated for $innerFun at: ${tree.sourcePos}")
3342+
}
3343+
js.LinkTimeIf(genReceiver1.cond, genReceiver1.thenp, genReceiver1.elsep)(toIRType(to))(using genReceiver1.pos)
3344+
case _ =>
3345+
genAsInstanceOf(genReceiver, to)
3346+
}
33253347
} else if (sym == defn.Any_isInstanceOf) {
33263348
genIsInstanceOf(genReceiver, to)
33273349
} else {

0 commit comments

Comments
 (0)