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:
@@ -19,7 +19,6 @@ package org.jetbrains.kotlin.codegen;
|
|||||||
import com.google.common.collect.Lists;
|
import com.google.common.collect.Lists;
|
||||||
import com.google.common.collect.Maps;
|
import com.google.common.collect.Maps;
|
||||||
import com.intellij.openapi.progress.ProcessCanceledException;
|
import com.intellij.openapi.progress.ProcessCanceledException;
|
||||||
import com.intellij.openapi.util.Ref;
|
|
||||||
import com.intellij.psi.PsiElement;
|
import com.intellij.psi.PsiElement;
|
||||||
import com.intellij.psi.tree.IElementType;
|
import com.intellij.psi.tree.IElementType;
|
||||||
import com.intellij.util.ArrayUtil;
|
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.FakeCallableDescriptorForObject;
|
||||||
import org.jetbrains.kotlin.resolve.calls.util.UnderscoreUtilKt;
|
import org.jetbrains.kotlin.resolve.calls.util.UnderscoreUtilKt;
|
||||||
import org.jetbrains.kotlin.resolve.constants.*;
|
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.constants.evaluate.ConstantExpressionEvaluatorKt;
|
||||||
import org.jetbrains.kotlin.resolve.descriptorUtil.DescriptorUtilsKt;
|
import org.jetbrains.kotlin.resolve.descriptorUtil.DescriptorUtilsKt;
|
||||||
import org.jetbrains.kotlin.resolve.inline.InlineUtil;
|
import org.jetbrains.kotlin.resolve.inline.InlineUtil;
|
||||||
|
|||||||
@@ -295,7 +295,7 @@ public class JvmCodegenUtil {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static boolean isInlinedJavaConstProperty(VariableDescriptor descriptor) {
|
public static boolean isInlinedJavaConstProperty(VariableDescriptor descriptor) {
|
||||||
return JvmConstantsKt.isInlinedJavaConstProperty(descriptor);
|
return descriptor instanceof JavaPropertyDescriptor && descriptor.isConst();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
|
|||||||
@@ -42,7 +42,7 @@ fun getCompileTimeConstant(
|
|||||||
if (!shouldInlineConstVals && !takeUpConstValsAsConst && compileTimeValue.usesVariableAsConstant) {
|
if (!shouldInlineConstVals && !takeUpConstValsAsConst && compileTimeValue.usesVariableAsConstant) {
|
||||||
val constantChecker = ConstantsChecker(bindingContext)
|
val constantChecker = ConstantsChecker(bindingContext)
|
||||||
expression.accept(constantChecker)
|
expression.accept(constantChecker)
|
||||||
if (constantChecker.containsNonInlinedVals) return null
|
if (constantChecker.containsKotlinConstVals) return null
|
||||||
}
|
}
|
||||||
|
|
||||||
val expectedType = bindingContext.getType(expression) ?: return null
|
val expectedType = bindingContext.getType(expression) ?: return null
|
||||||
@@ -52,25 +52,21 @@ fun getCompileTimeConstant(
|
|||||||
|
|
||||||
|
|
||||||
private class ConstantsChecker(private val bindingContext: BindingContext) : KtVisitorVoid() {
|
private class ConstantsChecker(private val bindingContext: BindingContext) : KtVisitorVoid() {
|
||||||
var containsNonInlinedVals = false
|
var containsKotlinConstVals = false
|
||||||
|
|
||||||
override fun visitSimpleNameExpression(expression: KtSimpleNameExpression) {
|
override fun visitSimpleNameExpression(expression: KtSimpleNameExpression) {
|
||||||
val resolvedCall = expression.getResolvedCall(bindingContext)
|
val resolvedCall = expression.getResolvedCall(bindingContext)
|
||||||
if (resolvedCall != null) {
|
if (resolvedCall != null) {
|
||||||
val callableDescriptor = resolvedCall.resultingDescriptor
|
val callableDescriptor = resolvedCall.resultingDescriptor
|
||||||
if (callableDescriptor is PropertyDescriptor && isInlinedJavaConstProperty(callableDescriptor as VariableDescriptor)) {
|
if (callableDescriptor is PropertyDescriptor && callableDescriptor !is JavaPropertyDescriptor && callableDescriptor.isConst) {
|
||||||
containsNonInlinedVals = true
|
containsKotlinConstVals = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun visitKtElement(element: KtElement) {
|
override fun visitKtElement(element: KtElement) {
|
||||||
if (!containsNonInlinedVals) {
|
if (!containsKotlinConstVals) {
|
||||||
element.acceptChildren(this)
|
element.acceptChildren(this)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
fun isInlinedJavaConstProperty(descriptor: VariableDescriptor): Boolean =
|
|
||||||
(descriptor as? JavaPropertyDescriptor)?.isConst ?: false
|
|
||||||
+14
@@ -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
|
||||||
+15
@@ -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
|
||||||
+15
@@ -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);
|
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")
|
@TestMetadata("nullableByteAndShort.kt")
|
||||||
public void testNullableByteAndShort() throws Exception {
|
public void testNullableByteAndShort() throws Exception {
|
||||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/bytecodeText/constants/nullableByteAndShort.kt");
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/bytecodeText/constants/nullableByteAndShort.kt");
|
||||||
|
|||||||
Reference in New Issue
Block a user