From b114bc5ea699a5cbee63ef55eb8989952201d70f Mon Sep 17 00:00:00 2001 From: Googler Date: Fri, 24 Jan 2025 06:50:35 -0800 Subject: [PATCH] [J2KT] Remove redundant casts which were added implicitly by various passes, which are not needed in Kotlin. PiperOrigin-RevId: 719284651 --- .../j2cl/transpiler/backend/Backend.java | 2 + .../passes/RemoveUnneededCastsJ2kt.java | 54 +++++++++++++++++++ .../java/cast/output_kt/CastGenerics.kt.txt | 4 +- .../output_kt/IntersectionTypeTest.kt.txt | 2 +- .../output_kt/NotNullAssertionProblems.kt.txt | 2 +- 5 files changed, 60 insertions(+), 4 deletions(-) create mode 100644 transpiler/java/com/google/j2cl/transpiler/passes/RemoveUnneededCastsJ2kt.java diff --git a/transpiler/java/com/google/j2cl/transpiler/backend/Backend.java b/transpiler/java/com/google/j2cl/transpiler/backend/Backend.java index 611c8ffc94..b54544cecb 100644 --- a/transpiler/java/com/google/j2cl/transpiler/backend/Backend.java +++ b/transpiler/java/com/google/j2cl/transpiler/backend/Backend.java @@ -174,6 +174,7 @@ import com.google.j2cl.transpiler.passes.RemoveNoopStatements; import com.google.j2cl.transpiler.passes.RemoveUnnecessaryLabels; import com.google.j2cl.transpiler.passes.RemoveUnneededCasts; +import com.google.j2cl.transpiler.passes.RemoveUnneededCastsJ2kt; import com.google.j2cl.transpiler.passes.RemoveUnneededJsDocCasts; import com.google.j2cl.transpiler.passes.RemoveUnneededNotNullChecks; import com.google.j2cl.transpiler.passes.RemoveUnreachableCode; @@ -775,6 +776,7 @@ public ImmutableList> getPassFactories(BackendOption () -> new RemoveUnnecessaryLabels(/* onlyLoopsAreBreakable= */ true), RemoveNestedBlocks::new, RemoveNoopStatements::new, + RemoveUnneededCastsJ2kt::new, // Passes that breaks the invariants for running ConversionContextVisitor related passes. NormalizeVarargInvocationsJ2kt::new, diff --git a/transpiler/java/com/google/j2cl/transpiler/passes/RemoveUnneededCastsJ2kt.java b/transpiler/java/com/google/j2cl/transpiler/passes/RemoveUnneededCastsJ2kt.java new file mode 100644 index 0000000000..a4fe1879b1 --- /dev/null +++ b/transpiler/java/com/google/j2cl/transpiler/passes/RemoveUnneededCastsJ2kt.java @@ -0,0 +1,54 @@ +/* + * Copyright 2024 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ +package com.google.j2cl.transpiler.passes; + +import com.google.j2cl.transpiler.ast.AbstractRewriter; +import com.google.j2cl.transpiler.ast.CastExpression; +import com.google.j2cl.transpiler.ast.CompilationUnit; +import com.google.j2cl.transpiler.ast.Expression; +import com.google.j2cl.transpiler.ast.Node; + +/** Removes casts which are unneeded in J2KT. */ +public class RemoveUnneededCastsJ2kt extends NormalizationPass { + + @Override + public void applyTo(CompilationUnit compilationUnit) { + compilationUnit.accept( + new AbstractRewriter() { + @Override + public Node rewriteCastExpression(CastExpression castExpression) { + Expression innerExpression = castExpression.getExpression(); + if (!(innerExpression instanceof CastExpression)) { + return castExpression; + } + + // Deduplicate casts of the same base type. + CastExpression innerCastExpression = (CastExpression) innerExpression; + if (!castExpression + .getCastTypeDescriptor() + .toRawTypeDescriptor() + .isSameBaseType( + innerCastExpression.getCastTypeDescriptor().toRawTypeDescriptor())) { + return castExpression; + } + + return CastExpression.Builder.from(castExpression) + .setExpression(innerCastExpression.getExpression()) + .build(); + } + }); + } +} diff --git a/transpiler/javatests/com/google/j2cl/readable/java/cast/output_kt/CastGenerics.kt.txt b/transpiler/javatests/com/google/j2cl/readable/java/cast/output_kt/CastGenerics.kt.txt index b7aec9b764..ba715c385f 100644 --- a/transpiler/javatests/com/google/j2cl/readable/java/cast/output_kt/CastGenerics.kt.txt +++ b/transpiler/javatests/com/google/j2cl/readable/java/cast/output_kt/CastGenerics.kt.txt @@ -64,7 +64,7 @@ open class CastGenerics { open fun testCastToRawToGeneric( @ObjCName("withCastCastGenerics_Foo") foo: CastGenerics.Foo? ): CastGenerics.Foo? { - return foo as CastGenerics.Foo? as CastGenerics.Foo? + return foo as CastGenerics.Foo? } @ObjCName("outerGenericMethod") @@ -81,7 +81,7 @@ open class CastGenerics { @ObjCName("withId") o: Any? ): EE where EE: CastGenerics.Empty1?, EE: CastGenerics.Empty2? { if (o is CastGenerics.Empty1) { - return o as EE? as EE + return o as EE } return null as EE } diff --git a/transpiler/javatests/com/google/j2cl/readable/java/intersectiontype/output_kt/IntersectionTypeTest.kt.txt b/transpiler/javatests/com/google/j2cl/readable/java/intersectiontype/output_kt/IntersectionTypeTest.kt.txt index 167bf95ff9..d6ca61b6d1 100644 --- a/transpiler/javatests/com/google/j2cl/readable/java/intersectiontype/output_kt/IntersectionTypeTest.kt.txt +++ b/transpiler/javatests/com/google/j2cl/readable/java/intersectiontype/output_kt/IntersectionTypeTest.kt.txt @@ -175,7 +175,7 @@ open class IntersectionTypeTest { private fun m(): T where T: IntersectionTypeTest.A?, T: IntersectionTypeTest.EmptyA? { return IntersectionTypeTest.get( Any(), - ) as T? as T + ) as T } @JvmStatic diff --git a/transpiler/javatests/com/google/j2cl/readable/java/j2kt/output_kt/NotNullAssertionProblems.kt.txt b/transpiler/javatests/com/google/j2cl/readable/java/j2kt/output_kt/NotNullAssertionProblems.kt.txt index a61c260131..2241863b72 100644 --- a/transpiler/javatests/com/google/j2cl/readable/java/j2kt/output_kt/NotNullAssertionProblems.kt.txt +++ b/transpiler/javatests/com/google/j2cl/readable/java/j2kt/output_kt/NotNullAssertionProblems.kt.txt @@ -395,7 +395,7 @@ open class NotNullAssertionProblems { @ObjCName("J2ktJ2ktNotNullAssertionProblems_C", exact = true) open class C internal constructor() { @JvmField - internal var defaultValue_pp_j2kt: V = null as V? as V + internal var defaultValue_pp_j2kt: V = null as V internal open fun f_pp_j2kt(): V { return (if (true) this.defaultValue_pp_j2kt else this.defaultValue_pp_j2kt) as V