JS: fix losing lambda in inline function after incremental compilation

See KT-21493

It's hard to maintain staticRef in cached AST. In fact, we don't need
it in this optimization. We'll get excessive names in used set,
which is ok: non-function names don't matter, they'll be simply ignored.
One possible concern: there's more chance to get name same to
some function's name and it won't be removed. First, it's not fatal,
it won't break the code (but put some excessive code that will likely
be removed by DCE). Second, there's same chance of two functions
having same names, and we manage to avoid this (otherwise we'll get
many problems).
This commit is contained in:
Alexey Andreev
2017-11-28 19:42:33 +03:00
parent 29b494cdac
commit 19438a3a07
4 changed files with 22 additions and 7 deletions
@@ -20,7 +20,7 @@ import org.jetbrains.kotlin.js.backend.ast.*
import org.jetbrains.kotlin.js.backend.ast.metadata.isLocal
import org.jetbrains.kotlin.js.backend.ast.metadata.staticRef
import org.jetbrains.kotlin.js.inline.util.IdentitySet
import org.jetbrains.kotlin.js.inline.util.collectFunctionReferencesInside
import org.jetbrains.kotlin.js.inline.util.collectReferencedNames
/**
* Removes unused function definitions:
@@ -93,13 +93,13 @@ private class UnusedLocalFunctionsCollector(private val functions: Map<JsName, J
}
private fun processLocalFunction(name: JsName, function: JsFunction) {
for (referenced in collectFunctionReferencesInside(function)) {
for (referenced in collectReferencedNames(function)) {
tracker.addRemovableReference(name, referenced)
}
}
private fun processNonLocalFunction(function: JsFunction) {
for (referenced in collectFunctionReferencesInside(function)) {
for (referenced in collectReferencedNames(function)) {
tracker.markReachable(referenced)
}
}
@@ -19,14 +19,10 @@ package org.jetbrains.kotlin.js.inline.util
import org.jetbrains.kotlin.js.backend.JsToStringGenerationVisitor
import org.jetbrains.kotlin.js.backend.ast.*
import org.jetbrains.kotlin.js.backend.ast.metadata.imported
import org.jetbrains.kotlin.js.backend.ast.metadata.staticRef
import org.jetbrains.kotlin.js.inline.util.collectors.InstanceCollector
import org.jetbrains.kotlin.js.translate.expression.InlineMetadata
import org.jetbrains.kotlin.js.translate.utils.JsAstUtils
fun collectFunctionReferencesInside(scope: JsNode): List<JsName> =
collectReferencedNames(scope).filter { it.staticRef is JsFunction }
fun collectReferencedNames(scope: JsNode): Set<JsName> {
val references = mutableSetOf<JsName>()
@@ -3803,6 +3803,12 @@ public class BoxJsTestGenerated extends AbstractBoxJsTest {
doTest(fileName);
}
@TestMetadata("inlineLambda.kt")
public void testInlineLambda() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("js/js.translator/testData/box/incremental/inlineLambda.kt");
doTest(fileName);
}
@TestMetadata("jsModule.kt")
public void testJsModule() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("js/js.translator/testData/box/incremental/jsModule.kt");
@@ -0,0 +1,13 @@
// EXPECTED_REACHABLE_NODES: 1128
// FILE: a.kt
inline fun foo(f: () -> String): () -> String {
val result = f()
return { result }
}
// FILE: main.kt
// RECOMPILE
fun bar(f: () -> String) = foo(f)()
fun box(): String = bar { "OK" }