Fix constant expression inlining logic

Constant expressions are inlined if they do not depend on non-inlineable
vals.
Java constants are always inlined.
Kotlin constants are inlined in LV 1.1+.
This commit is contained in:
Dmitry Petrov
2017-10-13 15:14:58 +03:00
parent 5acc992956
commit 16b7bece46
7 changed files with 68 additions and 12 deletions
@@ -19,7 +19,6 @@ package org.jetbrains.kotlin.codegen;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.intellij.openapi.progress.ProcessCanceledException;
import com.intellij.openapi.util.Ref;
import com.intellij.psi.PsiElement;
import com.intellij.psi.tree.IElementType;
import com.intellij.util.ArrayUtil;
@@ -74,7 +73,6 @@ import org.jetbrains.kotlin.resolve.calls.util.CallMaker;
import org.jetbrains.kotlin.resolve.calls.util.FakeCallableDescriptorForObject;
import org.jetbrains.kotlin.resolve.calls.util.UnderscoreUtilKt;
import org.jetbrains.kotlin.resolve.constants.*;
import org.jetbrains.kotlin.resolve.constants.evaluate.ConstantExpressionEvaluator;
import org.jetbrains.kotlin.resolve.constants.evaluate.ConstantExpressionEvaluatorKt;
import org.jetbrains.kotlin.resolve.descriptorUtil.DescriptorUtilsKt;
import org.jetbrains.kotlin.resolve.inline.InlineUtil;
@@ -295,7 +295,7 @@ public class JvmCodegenUtil {
}
public static boolean isInlinedJavaConstProperty(VariableDescriptor descriptor) {
return JvmConstantsKt.isInlinedJavaConstProperty(descriptor);
return descriptor instanceof JavaPropertyDescriptor && descriptor.isConst();
}
@Nullable
@@ -42,7 +42,7 @@ fun getCompileTimeConstant(
if (!shouldInlineConstVals && !takeUpConstValsAsConst && compileTimeValue.usesVariableAsConstant) {
val constantChecker = ConstantsChecker(bindingContext)
expression.accept(constantChecker)
if (constantChecker.containsNonInlinedVals) return null
if (constantChecker.containsKotlinConstVals) return null
}
val expectedType = bindingContext.getType(expression) ?: return null
@@ -52,25 +52,21 @@ fun getCompileTimeConstant(
private class ConstantsChecker(private val bindingContext: BindingContext) : KtVisitorVoid() {
var containsNonInlinedVals = false
var containsKotlinConstVals = false
override fun visitSimpleNameExpression(expression: KtSimpleNameExpression) {
val resolvedCall = expression.getResolvedCall(bindingContext)
if (resolvedCall != null) {
val callableDescriptor = resolvedCall.resultingDescriptor
if (callableDescriptor is PropertyDescriptor && isInlinedJavaConstProperty(callableDescriptor as VariableDescriptor)) {
containsNonInlinedVals = true
if (callableDescriptor is PropertyDescriptor && callableDescriptor !is JavaPropertyDescriptor && callableDescriptor.isConst) {
containsKotlinConstVals = true
}
}
}
override fun visitKtElement(element: KtElement) {
if (!containsNonInlinedVals) {
if (!containsKotlinConstVals) {
element.acceptChildren(this)
}
}
}
fun isInlinedJavaConstProperty(descriptor: VariableDescriptor): Boolean =
(descriptor as? JavaPropertyDescriptor)?.isConst ?: false
@@ -0,0 +1,14 @@
// FILE: test.kt
fun test1(a: A) = a.X
fun test2(a: A) = 1 + a.X
fun test3(a: A) = 1 < a.X
// FILE: A.java
public class A {
public final int X = 42;
}
// @TestKt.class:
// 0 42
// 0 43
// 3 GETFIELD A.X
@@ -0,0 +1,15 @@
// LANGUAGE_VERSION: 1.0
// FILE: test.kt
fun test1(a: A) = a.X
fun test2(a: A) = 1 + a.X
fun test3(a: A) = 1 < a.X
// FILE: A.java
public class A {
public final int X = 42;
}
// @TestKt.class:
// 0 42
// 0 43
// 3 GETFIELD A.X
@@ -0,0 +1,15 @@
// LANGUAGE_VERSION: 1.1
// FILE: test.kt
fun test1(a: A) = a.X
fun test2(a: A) = 1 + a.X
fun test3(a: A) = 1 < a.X
// FILE: A.java
public class A {
public final int X = 42;
}
// @TestKt.class:
// 0 42
// 0 43
// 3 GETFIELD A.X
@@ -1010,6 +1010,24 @@ public class BytecodeTextTestGenerated extends AbstractBytecodeTextTest {
doTest(fileName);
}
@TestMetadata("noInlineNonStaticJavaField.kt")
public void testNoInlineNonStaticJavaField() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/bytecodeText/constants/noInlineNonStaticJavaField.kt");
doTest(fileName);
}
@TestMetadata("noInlineNonStaticJavaField_lv10.kt")
public void testNoInlineNonStaticJavaField_lv10() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/bytecodeText/constants/noInlineNonStaticJavaField_lv10.kt");
doTest(fileName);
}
@TestMetadata("noInlineNonStaticJavaField_lv11.kt")
public void testNoInlineNonStaticJavaField_lv11() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/bytecodeText/constants/noInlineNonStaticJavaField_lv11.kt");
doTest(fileName);
}
@TestMetadata("nullableByteAndShort.kt")
public void testNullableByteAndShort() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/bytecodeText/constants/nullableByteAndShort.kt");