Fix for KT-10313: ClassCastException with Generics

#KT-10313 Fixed
This commit is contained in:
Anton Sukhonosenko
2015-12-15 08:54:09 +03:00
committed by Michael Bogdanov
parent edf6a2142b
commit 0073257841
12 changed files with 140 additions and 2 deletions
@@ -1242,12 +1242,21 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
@Nullable
public static ConstantValue<?> getCompileTimeConstant(@NotNull KtExpression expression, @NotNull BindingContext bindingContext) {
return getCompileTimeConstant(expression, bindingContext, false);
}
@Nullable
public static ConstantValue<?> getCompileTimeConstant(
@NotNull KtExpression expression,
@NotNull BindingContext bindingContext,
boolean checkPure
) {
CompileTimeConstant<?> compileTimeValue = ConstantExpressionEvaluator.getConstant(expression, bindingContext);
if (compileTimeValue == null) {
return null;
}
if (compileTimeValue.getUsesNonConstValAsConstant()) return null;
if (compileTimeValue.getUsesNonConstValAsConstant() || (checkPure && !compileTimeValue.getParameters().isPure())) return null;
KotlinType expectedType = bindingContext.getType(expression);
return compileTimeValue.toConstantValue(expectedType);
@@ -2893,6 +2902,11 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
expression.getRight(), reference);
}
else {
ConstantValue<?> compileTimeConstant = getCompileTimeConstant(expression, bindingContext, true);
if (compileTimeConstant != null) {
return StackValue.constant(compileTimeConstant.getValue(), expressionType(expression));
}
ResolvedCall<?> resolvedCall = CallUtilKt.getResolvedCallWithAssert(expression, bindingContext);
FunctionDescriptor descriptor = (FunctionDescriptor) resolvedCall.getResultingDescriptor();
@@ -3165,6 +3179,11 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
@Override
public StackValue visitPrefixExpression(@NotNull KtPrefixExpression expression, @NotNull StackValue receiver) {
ConstantValue<?> compileTimeConstant = getCompileTimeConstant(expression, bindingContext, true);
if (compileTimeConstant != null) {
return StackValue.constant(compileTimeConstant.getValue(), expressionType(expression));
}
DeclarationDescriptor originalOperation = bindingContext.get(REFERENCE_TARGET, expression.getOperationReference());
ResolvedCall<?> resolvedCall = CallUtilKt.getResolvedCallWithAssert(expression, bindingContext);
CallableDescriptor op = resolvedCall.getResultingDescriptor();
@@ -0,0 +1,7 @@
class Box<T>(val value: T)
fun box() : String {
val b = Box<Long>(2 * 3)
val expected: Long? = 6L
return if (b.value == expected) "OK" else "fail"
}
@@ -0,0 +1,7 @@
class Box<T>(val value: T)
fun box() : String {
val b = Box<Long>(x@ (1 + 2))
val expected: Long? = 3L
return if (b.value == expected) "OK" else "fail"
}
@@ -0,0 +1,7 @@
class Box<T>(val value: T)
fun box() : String {
val b = Box<Long>((-1))
val expected: Long? = -1L
return if (b.value == expected) "OK" else "fail"
}
@@ -0,0 +1,7 @@
open class Base<T>(val value: T)
class Box(): Base<Long>(-1)
fun box(): String {
val expected: Long? = -1L
return if (Box().value == expected) "OK" else "fail"
}
@@ -0,0 +1,7 @@
class Box<T>(val value: T)
fun box() : String {
val b = Box<Long>(-1)
val expected: Long? = -1L
return if (b.value == expected) "OK" else "fail"
}
@@ -0,0 +1,11 @@
class Box<T>(val value: T)
fun <T> run(vararg z: T): Box<T> {
return Box<T>(z[0])
}
fun box(): String {
val b = run<Long>(-1, -1, -1)
val expected: Long? = -1L
return if (b.value == expected) "OK" else "fail"
}
@@ -0,0 +1,15 @@
public class Box<T> {
private final T value;
public Box(T value) {
this.value = value;
}
public static <T> Box<T> create(T defaultValue) {
return new Box(defaultValue);
}
public T getValue() {
return value;
}
}
@@ -0,0 +1,4 @@
fun box(): String {
val sub = Box<Long>(-1)
return if (sub.value == -1L) "OK" else "fail"
}
@@ -1,5 +1,8 @@
const val one = 1
const val two = 2
fun test1() {
if (!(1 < 2)) {
if (!(one < two)) {
val p = 1
}
}
@@ -987,6 +987,51 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/casts/unitNullableCast.kt");
doTest(fileName);
}
@TestMetadata("compiler/testData/codegen/box/casts/literalExpressionAsGenericArgument")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class LiteralExpressionAsGenericArgument extends AbstractBlackBoxCodegenTest {
public void testAllFilesPresentInLiteralExpressionAsGenericArgument() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/casts/literalExpressionAsGenericArgument"), Pattern.compile("^(.+)\\.kt$"), true);
}
@TestMetadata("binaryExpressionCast.kt")
public void testBinaryExpressionCast() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/casts/literalExpressionAsGenericArgument/binaryExpressionCast.kt");
doTest(fileName);
}
@TestMetadata("labeledExpressionCast.kt")
public void testLabeledExpressionCast() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/casts/literalExpressionAsGenericArgument/labeledExpressionCast.kt");
doTest(fileName);
}
@TestMetadata("parenthesizedExpressionCast.kt")
public void testParenthesizedExpressionCast() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/casts/literalExpressionAsGenericArgument/parenthesizedExpressionCast.kt");
doTest(fileName);
}
@TestMetadata("superConstructor.kt")
public void testSuperConstructor() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/casts/literalExpressionAsGenericArgument/superConstructor.kt");
doTest(fileName);
}
@TestMetadata("unaryExpressionCast.kt")
public void testUnaryExpressionCast() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/casts/literalExpressionAsGenericArgument/unaryExpressionCast.kt");
doTest(fileName);
}
@TestMetadata("vararg.kt")
public void testVararg() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/casts/literalExpressionAsGenericArgument/vararg.kt");
doTest(fileName);
}
}
}
@TestMetadata("compiler/testData/codegen/box/classes")
@@ -241,6 +241,12 @@ public class BlackBoxWithJavaCodegenTestGenerated extends AbstractBlackBoxCodege
doTestWithJava(fileName);
}
@TestMetadata("literalExpressionAsGenericArgument")
public void testLiteralExpressionAsGenericArgument() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxWithJava/casts/literalExpressionAsGenericArgument/");
doTestWithJava(fileName);
}
}
@TestMetadata("compiler/testData/codegen/boxWithJava/collections")