diff --git a/compiler/frontend/serialization/src/org/jetbrains/jet/descriptors/serialization/DescriptorSerializer.java b/compiler/frontend/serialization/src/org/jetbrains/jet/descriptors/serialization/DescriptorSerializer.java index ea477901277..cf8feea814b 100644 --- a/compiler/frontend/serialization/src/org/jetbrains/jet/descriptors/serialization/DescriptorSerializer.java +++ b/compiler/frontend/serialization/src/org/jetbrains/jet/descriptors/serialization/DescriptorSerializer.java @@ -21,6 +21,7 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.jet.lang.descriptors.*; import org.jetbrains.jet.lang.descriptors.annotations.Annotated; import org.jetbrains.jet.lang.resolve.DescriptorFactory; +import org.jetbrains.jet.lang.resolve.DescriptorUtils; import org.jetbrains.jet.lang.types.JetType; import org.jetbrains.jet.lang.types.TypeConstructor; import org.jetbrains.jet.lang.types.TypeProjection; @@ -196,7 +197,7 @@ public class DescriptorSerializer { } } - hasConstant = !propertyDescriptor.isVar() && propertyDescriptor.getCompileTimeInitializer() != null; + hasConstant = propertyDescriptor.getCompileTimeInitializer() != null; } builder.setFlags(Flags.getCallableFlags( diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/BodyResolver.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/BodyResolver.java index 3d708528038..b0e7d61e537 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/BodyResolver.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/BodyResolver.java @@ -32,6 +32,7 @@ import org.jetbrains.jet.lang.resolve.calls.context.ResolutionResultsCacheImpl; import org.jetbrains.jet.lang.resolve.calls.context.SimpleResolutionContext; import org.jetbrains.jet.lang.resolve.calls.results.OverloadResolutionResults; import org.jetbrains.jet.lang.resolve.calls.util.CallMaker; +import org.jetbrains.jet.lang.resolve.constants.CompileTimeConstant; import org.jetbrains.jet.lang.resolve.scopes.*; import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverValue; import org.jetbrains.jet.lang.types.*; @@ -565,7 +566,10 @@ public class BodyResolver { JetScope propertyDeclarationInnerScope = JetScopeUtils.getPropertyDeclarationInnerScopeForInitializer( scope, propertyDescriptor.getTypeParameters(), NO_RECEIVER_PARAMETER, trace); JetType expectedTypeForInitializer = property.getTypeRef() != null ? propertyDescriptor.getType() : NO_EXPECTED_TYPE; - expressionTypingServices.getType(propertyDeclarationInnerScope, initializer, expectedTypeForInitializer, c.getOuterDataFlowInfo(), trace); + CompileTimeConstant compileTimeInitializer = propertyDescriptor.getCompileTimeInitializer(); + if (compileTimeInitializer == null) { + expressionTypingServices.getType(propertyDeclarationInnerScope, initializer, expectedTypeForInitializer, c.getOuterDataFlowInfo(), trace); + } } @NotNull diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/DescriptorResolver.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/DescriptorResolver.java index 0eff4c6f007..e90b07ed5c2 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/DescriptorResolver.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/DescriptorResolver.java @@ -959,7 +959,7 @@ public class DescriptorResolver { @Override public JetType invoke() { JetType initializerType = resolveInitializerType(scope, initializer, dataFlowInfo, trace); - setConstantForVariableIfNeeded(variableDescriptor, initializer, initializerType, trace); + setConstantForVariableIfNeeded(variableDescriptor, scope, variable, dataFlowInfo, initializerType, trace); return transformAnonymousTypeIfNeeded(variableDescriptor, variable, initializerType, trace); } } @@ -967,40 +967,45 @@ public class DescriptorResolver { } else { JetType initializerType = resolveInitializerType(scope, initializer, dataFlowInfo, trace); - setConstantForVariableIfNeeded(variableDescriptor, initializer, initializerType, trace); + setConstantForVariableIfNeeded(variableDescriptor, scope, variable, dataFlowInfo, initializerType, trace); return initializerType; } } } else { JetType type = typeResolver.resolveType(scope, propertyTypeRef, trace, true); - JetExpression initializer = variable.getInitializer(); - if (initializer != null) { - setConstantForVariableIfNeeded(variableDescriptor, initializer, type, trace); - } + setConstantForVariableIfNeeded(variableDescriptor, scope, variable, dataFlowInfo, type, trace); return type; } } private void setConstantForVariableIfNeeded( @NotNull VariableDescriptorImpl variableDescriptor, - @NotNull final JetExpression initializer, - @NotNull final JetType initializerType, + @NotNull final JetScope scope, + @NotNull JetVariableDeclaration variable, + @NotNull final DataFlowInfo dataFlowInfo, + @NotNull final JetType variableType, @NotNull final BindingTrace trace ) { - if (variableDescriptor.isVar()) return; + if (!shouldRecordInitializerForProperty(variableDescriptor, variableType)) return; - variableDescriptor.setCompileTimeInitializer(storageManager.createRecursionTolerantNullableLazyValue(new Function0>() { - @Nullable - @Override - public CompileTimeConstant invoke() { - CompileTimeConstant constant = ConstantExpressionEvaluator.object$.evaluate(initializer, trace, initializerType); - if ((constant instanceof IntegerValueTypeConstant)) { - return EvaluatePackage.createCompileTimeConstantWithType((IntegerValueTypeConstant) constant, initializerType); + final JetExpression initializer = variable.getInitializer(); + if (initializer == null) return; + + variableDescriptor.setCompileTimeInitializer( + storageManager.createRecursionTolerantNullableLazyValue(new Function0>() { + @Nullable + @Override + public CompileTimeConstant invoke() { + JetType initializerType = expressionTypingServices.safeGetType(scope, initializer, variableType, dataFlowInfo, trace); + CompileTimeConstant constant = ConstantExpressionEvaluator.object$.evaluate(initializer, trace, initializerType); + if (constant instanceof IntegerValueTypeConstant) { + return EvaluatePackage.createCompileTimeConstantWithType((IntegerValueTypeConstant) constant, initializerType); + } + return constant; } - return constant; - } - }, null)); + }, null) + ); } @NotNull diff --git a/compiler/testData/evaluate/constant/differentTypes.kt b/compiler/testData/evaluate/constant/differentTypes.kt new file mode 100644 index 00000000000..177b6806ec8 --- /dev/null +++ b/compiler/testData/evaluate/constant/differentTypes.kt @@ -0,0 +1,45 @@ +package test + +// val prop1: 1 +val prop1: Int = 1 + +// val prop2: 1 +val prop2: Int? = 1 + +// val prop3: 1 +val prop3: Number? = 1 + +// val prop4: 1 +val prop4: Any? = 1 + +// val prop5: 1 +val prop5: Number = 1 + +// val prop6: 1 +val prop6: Any = 1 + +// val prop7: \"a\" +val prop7: String = "a" + +// val prop8: \"a\" +val prop8: String? = "a" + +// val prop9: \"a\" +val prop9: Any? = "a" + +// val prop10: \"a\" +val prop10: Any = "a" + +// val prop11: null +val prop11: aaa = 1 + +// val prop14: null +val prop14: aaa? = 1 + +class A + +// val prop15: null +val prop15: A = 1 + +// val prop16: 1 +val prop16: A? = 1 diff --git a/compiler/testData/evaluate/constant/divideByZero.kt b/compiler/testData/evaluate/constant/divideByZero.kt index adc2ee5e019..2cfc49b8f3e 100644 --- a/compiler/testData/evaluate/constant/divideByZero.kt +++ b/compiler/testData/evaluate/constant/divideByZero.kt @@ -1,34 +1,34 @@ package test -// val prop1: Division by zero +// val prop1: null val prop1 = 1 / 0 -// val prop2: Division by zero +// val prop2: null val prop2 = 1 / 0.0 -// val prop3: Division by zero +// val prop3: null val prop3 = 1.0 / 0 // val prop4: 10.0.toDouble() val prop4 = 1 / 0.1 -// val prop5: Division by zero +// val prop5: null val prop5 = 1 / 0.toLong() -// val prop6: Division by zero +// val prop6: null val prop6 = 1.0 / 0.toInt() -// val prop7: Division by zero +// val prop7: null val prop7 = 1.0 / 0.toLong() -// val prop8: Division by zero +// val prop8: null val prop8 = 1.0 / 0.toByte() -// val prop9: Division by zero +// val prop9: null val prop9 = 1.0 / 0.toShort() -// val prop10: Division by zero +// val prop10: null val prop10 = 1.0 / 0.toFloat() -// val prop11: Division by zero +// val prop11: null val prop11 = 1.0 / 0.toDouble() \ No newline at end of file diff --git a/compiler/testData/loadJava/compiledJavaCompareWithKotlin/ClassWithConstVal.java b/compiler/testData/loadJava/compiledJavaCompareWithKotlin/ClassWithConstVal.java new file mode 100644 index 00000000000..2cdac74ebb1 --- /dev/null +++ b/compiler/testData/loadJava/compiledJavaCompareWithKotlin/ClassWithConstVal.java @@ -0,0 +1,6 @@ +package test; + +public final class ClassWithConstVal { + public final int f = 1; + public final int f2 = f; +} diff --git a/compiler/testData/loadJava/compiledJavaCompareWithKotlin/ClassWithConstVal.kt b/compiler/testData/loadJava/compiledJavaCompareWithKotlin/ClassWithConstVal.kt new file mode 100644 index 00000000000..50f79015519 --- /dev/null +++ b/compiler/testData/loadJava/compiledJavaCompareWithKotlin/ClassWithConstVal.kt @@ -0,0 +1,6 @@ +package test + +public class ClassWithConstVal() : java.lang.Object() { + public val f: Int = 1 + public val f2: Int = f +} diff --git a/compiler/testData/loadJava/compiledJavaCompareWithKotlin/ClassWithConstVal.txt b/compiler/testData/loadJava/compiledJavaCompareWithKotlin/ClassWithConstVal.txt new file mode 100644 index 00000000000..99c1103a2e2 --- /dev/null +++ b/compiler/testData/loadJava/compiledJavaCompareWithKotlin/ClassWithConstVal.txt @@ -0,0 +1,7 @@ +package test + +public final class ClassWithConstVal : java.lang.Object { + public constructor ClassWithConstVal() + public final val f: kotlin.Int = 1 + public final val f2: kotlin.Int = 1 +} diff --git a/compiler/tests/org/jetbrains/jet/evaluate/EvaluateExpressionTestGenerated.java b/compiler/tests/org/jetbrains/jet/evaluate/EvaluateExpressionTestGenerated.java index f59fdcd8058..89de1e1eda9 100644 --- a/compiler/tests/org/jetbrains/jet/evaluate/EvaluateExpressionTestGenerated.java +++ b/compiler/tests/org/jetbrains/jet/evaluate/EvaluateExpressionTestGenerated.java @@ -48,6 +48,11 @@ public class EvaluateExpressionTestGenerated extends AbstractEvaluateExpressionT doConstantTest("compiler/testData/evaluate/constant/compareTo.kt"); } + @TestMetadata("differentTypes.kt") + public void testDifferentTypes() throws Exception { + doConstantTest("compiler/testData/evaluate/constant/differentTypes.kt"); + } + @TestMetadata("divideByZero.kt") public void testDivideByZero() throws Exception { doConstantTest("compiler/testData/evaluate/constant/divideByZero.kt"); diff --git a/compiler/tests/org/jetbrains/jet/jvm/compiler/LoadJavaTestGenerated.java b/compiler/tests/org/jetbrains/jet/jvm/compiler/LoadJavaTestGenerated.java index bd6e11ff109..299b95236c4 100644 --- a/compiler/tests/org/jetbrains/jet/jvm/compiler/LoadJavaTestGenerated.java +++ b/compiler/tests/org/jetbrains/jet/jvm/compiler/LoadJavaTestGenerated.java @@ -546,6 +546,11 @@ public class LoadJavaTestGenerated extends AbstractLoadJavaTest { doTestCompiledJavaCompareWithKotlin("compiler/testData/loadJava/compiledJavaCompareWithKotlin/ClassDoesNotOverrideMethod.java"); } + @TestMetadata("ClassWithConstVal.java") + public void testClassWithConstVal() throws Exception { + doTestCompiledJavaCompareWithKotlin("compiler/testData/loadJava/compiledJavaCompareWithKotlin/ClassWithConstVal.java"); + } + @TestMetadata("ClassWithTypeP.java") public void testClassWithTypeP() throws Exception { doTestCompiledJavaCompareWithKotlin("compiler/testData/loadJava/compiledJavaCompareWithKotlin/ClassWithTypeP.java"); diff --git a/compiler/tests/org/jetbrains/jet/lang/resolve/lazy/LazyResolveRecursiveComparingTestGenerated.java b/compiler/tests/org/jetbrains/jet/lang/resolve/lazy/LazyResolveRecursiveComparingTestGenerated.java index a0c841e29ee..4adb3d4aae6 100644 --- a/compiler/tests/org/jetbrains/jet/lang/resolve/lazy/LazyResolveRecursiveComparingTestGenerated.java +++ b/compiler/tests/org/jetbrains/jet/lang/resolve/lazy/LazyResolveRecursiveComparingTestGenerated.java @@ -1509,6 +1509,11 @@ public class LazyResolveRecursiveComparingTestGenerated extends AbstractLazyReso doTestNotCheckingPrimaryConstructors("compiler/testData/loadJava/compiledJavaCompareWithKotlin/ClassDoesNotOverrideMethod.kt"); } + @TestMetadata("ClassWithConstVal.kt") + public void testClassWithConstVal() throws Exception { + doTestNotCheckingPrimaryConstructors("compiler/testData/loadJava/compiledJavaCompareWithKotlin/ClassWithConstVal.kt"); + } + @TestMetadata("ClassWithTypeP.kt") public void testClassWithTypeP() throws Exception { doTestNotCheckingPrimaryConstructors("compiler/testData/loadJava/compiledJavaCompareWithKotlin/ClassWithTypeP.kt"); diff --git a/core/descriptor.loader.java/src/org/jetbrains/jet/lang/resolve/java/lazy/descriptors/LazyJavaMemberScope.kt b/core/descriptor.loader.java/src/org/jetbrains/jet/lang/resolve/java/lazy/descriptors/LazyJavaMemberScope.kt index 9bda99280a8..64b1f7ab7e1 100644 --- a/core/descriptor.loader.java/src/org/jetbrains/jet/lang/resolve/java/lazy/descriptors/LazyJavaMemberScope.kt +++ b/core/descriptor.loader.java/src/org/jetbrains/jet/lang/resolve/java/lazy/descriptors/LazyJavaMemberScope.kt @@ -266,7 +266,7 @@ public abstract class LazyJavaMemberScope( propertyDescriptor.setType(effectiveSignature.getReturnType(), Collections.emptyList(), DescriptorUtils.getExpectedThisObjectIfNeeded(getContainingDeclaration()), null : JetType?) - if (!propertyDescriptor.isVar()) { + if (DescriptorUtils.shouldRecordInitializerForProperty(propertyDescriptor, propertyDescriptor.getType())) { propertyDescriptor.setCompileTimeInitializer( c.storageManager.createNullableLazyValue { JavaPropertyInitializerEvaluator.getInstance().getInitializerConstant(field, propertyDescriptor) diff --git a/core/descriptors/src/org/jetbrains/jet/lang/resolve/DescriptorUtils.java b/core/descriptors/src/org/jetbrains/jet/lang/resolve/DescriptorUtils.java index d6a748e2299..c0157d27657 100644 --- a/core/descriptors/src/org/jetbrains/jet/lang/resolve/DescriptorUtils.java +++ b/core/descriptors/src/org/jetbrains/jet/lang/resolve/DescriptorUtils.java @@ -495,4 +495,16 @@ public class DescriptorUtils { } return false; } + + public static boolean shouldRecordInitializerForProperty(@NotNull VariableDescriptor variable, @NotNull JetType type) { + if (variable.isVar() || type.isError()) return false; + + if (type instanceof LazyType || type.isNullable()) return true; + + KotlinBuiltIns builtIns = KotlinBuiltIns.getInstance(); + return builtIns.isPrimitiveType(type) || + builtIns.getStringType().equals(type) || + builtIns.getNumber().getDefaultType().equals(type) || + builtIns.getAnyType().equals(type); + } }