Skip to content

Commit 0b7aa2f

Browse files
committed
Squash with GP commit: Address review comments.
1 parent 8c6e6e3 commit 0b7aa2f

File tree

5 files changed

+55
-57
lines changed

5 files changed

+55
-57
lines changed

linker/shared/src/main/scala/org/scalajs/linker/backend/wasmemitter/FunctionEmitter.scala

Lines changed: 3 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1377,6 +1377,8 @@ private class FunctionEmitter private (
13771377
return NothingType
13781378
}
13791379

1380+
// scalastyle:on return
1381+
13801382
genTree(lhs, op match {
13811383
case IdentityHashCode => AnyNotNullType
13821384
case WrapAsThrowable | Throw => AnyType
@@ -1507,6 +1509,7 @@ private class FunctionEmitter private (
15071509
}
15081510

15091511
case IdentityHashCode =>
1512+
// TODO Avoid dispatch when we know a more precise type than any
15101513
fb += wa.Call(genFunctionID.identityHashCode)
15111514

15121515
case WrapAsThrowable =>
@@ -1561,8 +1564,6 @@ private class FunctionEmitter private (
15611564
}
15621565

15631566
tree.tpe
1564-
1565-
// scalastyle:on return
15661567
}
15671568

15681569
private def genBinaryOp(tree: BinaryOp): Type = {
@@ -2658,43 +2659,6 @@ private class FunctionEmitter private (
26582659
ClassType(boxClassName, nullable = false)
26592660
}
26602661

2661-
private def genWrapAsThrowable(tree: UnaryOp): Type = {
2662-
val UnaryOp(op, expr) = tree
2663-
assert(op == UnaryOp.WrapAsThrowable)
2664-
2665-
val nonNullThrowableType = watpe.RefType(genTypeID.ThrowableStruct)
2666-
val jsExceptionType = watpe.RefType(genTypeID.JSExceptionStruct)
2667-
2668-
fb.block(nonNullThrowableType) { doneLabel =>
2669-
genTree(expr, AnyType)
2670-
2671-
markPosition(tree)
2672-
2673-
// if expr.isInstanceOf[Throwable], then br $done
2674-
fb += wa.BrOnCast(doneLabel, watpe.RefType.anyref, nonNullThrowableType)
2675-
2676-
// otherwise, wrap in a new JavaScriptException
2677-
2678-
val exprLocal = addSyntheticLocal(watpe.RefType.anyref)
2679-
val instanceLocal = addSyntheticLocal(jsExceptionType)
2680-
2681-
fb += wa.LocalSet(exprLocal)
2682-
fb += wa.Call(genFunctionID.newDefault(SpecialNames.JSExceptionClass))
2683-
fb += wa.LocalTee(instanceLocal)
2684-
fb += wa.LocalGet(exprLocal)
2685-
fb += wa.Call(
2686-
genFunctionID.forMethod(
2687-
MemberNamespace.Constructor,
2688-
SpecialNames.JSExceptionClass,
2689-
SpecialNames.AnyArgConstructorName
2690-
)
2691-
)
2692-
fb += wa.LocalGet(instanceLocal)
2693-
}
2694-
2695-
tree.tpe
2696-
}
2697-
26982662
private def genLinkTimeProperty(tree: LinkTimeProperty): Type = {
26992663
val lit = ctx.coreSpec.linkTimeProperties.transformLinkTimeProperty(tree)
27002664
genLiteral(lit, lit.tpe)

linker/shared/src/main/scala/org/scalajs/linker/checker/ClassDefChecker.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -798,7 +798,7 @@ private final class ClassDefChecker(classDef: ClassDef,
798798

799799
checkApplyGeneric(method, args)
800800

801-
case UnaryOp(op, lhs) =>
801+
case UnaryOp(_, lhs) =>
802802
checkTree(lhs, env)
803803

804804
case BinaryOp(_, lhs, rhs) =>

linker/shared/src/main/scala/org/scalajs/linker/frontend/optimizer/IncOptimizer.scala

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -882,7 +882,8 @@ final class IncOptimizer private[optimizer] (config: CommonPhaseConfig, collOps:
882882
case UnaryOp(UnaryOp.CheckNotNull, expr) =>
883883
config.coreSpec.semantics.nullPointers == CheckedBehavior.Unchecked &&
884884
isTriviallySideEffectFree(expr)
885-
case UnaryOp(UnaryOp.GetClass, expr) => // Before 1.17, we used GetClass as CheckNotNull
885+
case UnaryOp(op, expr) => // Before 1.17, we used GetClass as CheckNotNull
886+
UnaryOp.isSideEffectFreeOp(op) &&
886887
isTriviallySideEffectFree(expr)
887888

888889
case New(className, _, args) =>

linker/shared/src/main/scala/org/scalajs/linker/frontend/optimizer/OptimizerCore.scala

Lines changed: 15 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -3472,34 +3472,35 @@ private[optimizer] abstract class OptimizerCore(
34723472
val UnaryOp(op, arg) = tree
34733473

34743474
pretransformExpr(arg) { tlhs =>
3475-
val folded = foldUnaryOp(op, tlhs)
3475+
def folded: PreTransform =
3476+
foldUnaryOp(op, tlhs)
34763477

3477-
folded match {
3478-
case PreTransUnaryOp(UnaryOp.WrapAsThrowable, texpr) =>
3479-
if (isSubtype(texpr.tpe.base, ThrowableClassType.toNonNullable)) {
3480-
cont(texpr)
3478+
op match {
3479+
case UnaryOp.WrapAsThrowable =>
3480+
if (isSubtype(tlhs.tpe.base, ThrowableClassType.toNonNullable)) {
3481+
cont(tlhs)
34813482
} else {
3482-
if (texpr.tpe.isExact) {
3483+
if (tlhs.tpe.isExact) {
34833484
pretransformNew(AllocationSite.Tree(tree), JavaScriptExceptionClass,
3484-
MethodIdent(AnyArgConstructorName), texpr :: Nil)(cont)
3485+
MethodIdent(AnyArgConstructorName), tlhs :: Nil)(cont)
34853486
} else {
34863487
cont(folded)
34873488
}
34883489
}
34893490

3490-
case PreTransUnaryOp(UnaryOp.UnwrapFromThrowable, texpr) =>
3491-
val baseTpe = texpr.tpe.base
3491+
case UnaryOp.UnwrapFromThrowable =>
3492+
val baseTpe = tlhs.tpe.base
34923493

34933494
if (baseTpe == NothingType) {
3494-
cont(texpr)
3495+
cont(tlhs)
34953496
} else if (baseTpe == NullType) {
3496-
cont(checkNotNull(texpr))
3497+
cont(checkNotNull(tlhs))
34973498
} else if (isSubtype(baseTpe, JavaScriptExceptionClassType)) {
3498-
pretransformSelectCommon(AnyType, texpr, optQualDeclaredType = None,
3499+
pretransformSelectCommon(AnyType, tlhs, optQualDeclaredType = None,
34993500
FieldIdent(exceptionFieldName), isLhsOfAssign = false)(cont)
35003501
} else {
3501-
if (texpr.tpe.isExact || !isSubtype(JavaScriptExceptionClassType.toNonNullable, baseTpe))
3502-
cont(checkNotNull(texpr))
3502+
if (tlhs.tpe.isExact || !isSubtype(JavaScriptExceptionClassType.toNonNullable, baseTpe))
3503+
cont(checkNotNull(tlhs))
35033504
else
35043505
cont(folded)
35053506
}

linker/shared/src/test/scala/org/scalajs/linker/IRCheckerTest.scala

Lines changed: 34 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ import org.scalajs.linker.interface._
3131
import org.scalajs.linker.interface.unstable.IRFileImpl
3232
import org.scalajs.linker.standard._
3333
import org.scalajs.linker.frontend.Refiner
34+
import org.scalajs.linker.backend.emitter.PrivateLibHolder
3435

3536
import org.scalajs.linker.testutils._
3637
import org.scalajs.linker.testutils.TestIRBuilder._
@@ -255,13 +256,43 @@ class IRCheckerTest {
255256
}
256257
}
257258

259+
@Test
260+
def unaryOpNonNullableArguments(): AsyncResult = await {
261+
import UnaryOp._
262+
263+
// List of ops that take non-nullable reference types as argument
264+
val ops = List(
265+
Class_name,
266+
Class_isPrimitive,
267+
Class_isInterface,
268+
Class_isArray,
269+
Class_componentType,
270+
Class_superClass,
271+
Array_length,
272+
GetClass,
273+
Clone,
274+
UnwrapFromThrowable
275+
)
276+
277+
val results = for (op <- ops) yield {
278+
val classDefs = Seq(
279+
mainTestClassDef(UnaryOp(op, Null()))
280+
)
281+
282+
for (log <- testLinkIRErrors(classDefs, MainTestModuleInitializers)) yield {
283+
log.assertContainsError("expected but null found")
284+
}
285+
}
286+
287+
Future.sequence(results)
288+
}
289+
258290
@Test
259291
def arrayOpsNullOrNothing(): AsyncResult = await {
260292
val classDefs = Seq(
261293
mainTestClassDef(
262294
Block(
263295
ArraySelect(Null(), int(1))(NothingType),
264-
UnaryOp(UnaryOp.Array_length, UnaryOp(UnaryOp.CheckNotNull, Null())),
265296
ArraySelect(UnaryOp(UnaryOp.Throw, Null()), int(1))(NothingType),
266297
UnaryOp(UnaryOp.Array_length, UnaryOp(UnaryOp.Throw, Null()))
267298
)
@@ -453,7 +484,8 @@ object IRCheckerTest {
453484
val linkerFrontend = StandardLinkerFrontend(config)
454485
val irFiles = (
455486
stdLibFiles ++
456-
classDefs.map(MemClassDefIRFile(_))
487+
classDefs.map(MemClassDefIRFile(_)) ++
488+
PrivateLibHolder.files
457489
)
458490
linkerFrontend.link(irFiles, moduleInitializers, noSymbolRequirements, logger)
459491
}

0 commit comments

Comments
 (0)