KT-3307 Compiler exception trying to call Java method
#KT-3307 Fixed
This commit is contained in:
+10
-1
@@ -95,7 +95,8 @@ public class RawTypesCheck {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (HierarchicalMethodSignature superSignature : method.getHierarchicalMethodSignature().getSuperSignatures()) {
|
for (HierarchicalMethodSignature superSignature : method.getHierarchicalMethodSignature().getSuperSignatures()) {
|
||||||
if (superSignature.isRaw() || hasRawTypesInSignature(superSignature.getMethod())) {
|
PsiMethod superMethod = superSignature.getMethod();
|
||||||
|
if (superSignature.isRaw() || typeParameterIsErased(method, superMethod) || hasRawTypesInSignature(superMethod)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -103,6 +104,14 @@ public class RawTypesCheck {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static boolean typeParameterIsErased(@NotNull PsiMethod a, @NotNull PsiMethod b) {
|
||||||
|
// Java allows you to write
|
||||||
|
// <T extends Foo> T foo(), in the superclass and then
|
||||||
|
// Foo foo(), in the subclass
|
||||||
|
// this is a valid Java override, but in fact it is an erasure
|
||||||
|
return a.getTypeParameters().length != b.getTypeParameters().length;
|
||||||
|
}
|
||||||
|
|
||||||
private RawTypesCheck() {
|
private RawTypesCheck() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ import com.google.common.collect.Maps;
|
|||||||
import com.google.common.collect.Sets;
|
import com.google.common.collect.Sets;
|
||||||
import com.intellij.util.Function;
|
import com.intellij.util.Function;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
import org.jetbrains.jet.lang.descriptors.*;
|
import org.jetbrains.jet.lang.descriptors.*;
|
||||||
import org.jetbrains.jet.lang.types.*;
|
import org.jetbrains.jet.lang.types.*;
|
||||||
import org.jetbrains.jet.lang.types.checker.JetTypeChecker;
|
import org.jetbrains.jet.lang.types.checker.JetTypeChecker;
|
||||||
@@ -222,6 +223,7 @@ public class OverridingUtil {
|
|||||||
|
|
||||||
public static boolean isReturnTypeOkForOverride(@NotNull JetTypeChecker typeChecker, @NotNull CallableDescriptor superDescriptor, @NotNull CallableDescriptor subDescriptor) {
|
public static boolean isReturnTypeOkForOverride(@NotNull JetTypeChecker typeChecker, @NotNull CallableDescriptor superDescriptor, @NotNull CallableDescriptor subDescriptor) {
|
||||||
TypeSubstitutor typeSubstitutor = prepareTypeSubstitutor(superDescriptor, subDescriptor);
|
TypeSubstitutor typeSubstitutor = prepareTypeSubstitutor(superDescriptor, subDescriptor);
|
||||||
|
if (typeSubstitutor == null) return false;
|
||||||
|
|
||||||
JetType superReturnType = superDescriptor.getReturnType();
|
JetType superReturnType = superDescriptor.getReturnType();
|
||||||
assert superReturnType != null;
|
assert superReturnType != null;
|
||||||
@@ -235,11 +237,14 @@ public class OverridingUtil {
|
|||||||
return typeChecker.isSubtypeOf(subReturnType, substitutedSuperReturnType);
|
return typeChecker.isSubtypeOf(subReturnType, substitutedSuperReturnType);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
private static TypeSubstitutor prepareTypeSubstitutor(@NotNull CallableDescriptor superDescriptor, @NotNull CallableDescriptor subDescriptor) {
|
private static TypeSubstitutor prepareTypeSubstitutor(@NotNull CallableDescriptor superDescriptor, @NotNull CallableDescriptor subDescriptor) {
|
||||||
List<TypeParameterDescriptor> superTypeParameters = superDescriptor.getTypeParameters();
|
List<TypeParameterDescriptor> superTypeParameters = superDescriptor.getTypeParameters();
|
||||||
List<TypeParameterDescriptor> subTypeParameters = subDescriptor.getTypeParameters();
|
List<TypeParameterDescriptor> subTypeParameters = subDescriptor.getTypeParameters();
|
||||||
|
if (subTypeParameters.size() != superTypeParameters.size()) return null;
|
||||||
|
|
||||||
Map<TypeConstructor, TypeProjection> substitutionContext = Maps.newHashMap();
|
Map<TypeConstructor, TypeProjection> substitutionContext = Maps.newHashMap();
|
||||||
for (int i = 0, typeParametersSize = superTypeParameters.size(); i < typeParametersSize; i++) {
|
for (int i = 0; i < superTypeParameters.size(); i++) {
|
||||||
TypeParameterDescriptor superTypeParameter = superTypeParameters.get(i);
|
TypeParameterDescriptor superTypeParameter = superTypeParameters.get(i);
|
||||||
TypeParameterDescriptor subTypeParameter = subTypeParameters.get(i);
|
TypeParameterDescriptor subTypeParameter = subTypeParameters.get(i);
|
||||||
substitutionContext.put(
|
substitutionContext.put(
|
||||||
|
|||||||
@@ -0,0 +1,21 @@
|
|||||||
|
// FILE: Bug.java
|
||||||
|
|
||||||
|
public interface Bug {
|
||||||
|
<RET extends Bug> RET save();
|
||||||
|
}
|
||||||
|
|
||||||
|
// FILE: SubBug.java
|
||||||
|
|
||||||
|
public class SubBug implements Bug {
|
||||||
|
public SubBug save() {
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// FILE: Bug.kt
|
||||||
|
|
||||||
|
fun TestBug() {
|
||||||
|
SubBug().save() // can resolve on subtype
|
||||||
|
val bug: Bug = SubBug()
|
||||||
|
bug.save<Bug>() // can resolve on supertype
|
||||||
|
}
|
||||||
+19
@@ -0,0 +1,19 @@
|
|||||||
|
package test;
|
||||||
|
|
||||||
|
public interface MethodTypeParameterErased {
|
||||||
|
|
||||||
|
public interface Bug<T> {
|
||||||
|
<RET extends Bug<T>> RET save();
|
||||||
|
void foo();
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract class SubBug implements Bug<Object> {
|
||||||
|
public SubBug save() {
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void foo() {}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
+13
@@ -0,0 +1,13 @@
|
|||||||
|
package test
|
||||||
|
|
||||||
|
public trait MethodTypeParameterErased : java.lang.Object {
|
||||||
|
|
||||||
|
public trait Bug</*0*/ T> : java.lang.Object {
|
||||||
|
public abstract fun </*0*/ RET : test.MethodTypeParameterErased.Bug<T>?> save() : RET?
|
||||||
|
}
|
||||||
|
|
||||||
|
public open class SubBug : test.MethodTypeParameterErased.Bug<jet.Any> {
|
||||||
|
public constructor SubBug()
|
||||||
|
public open fun save() : test.MethodTypeParameterErased.SubBug?
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -16,16 +16,13 @@
|
|||||||
|
|
||||||
package org.jetbrains.jet.checkers;
|
package org.jetbrains.jet.checkers;
|
||||||
|
|
||||||
import junit.framework.Assert;
|
|
||||||
import junit.framework.Test;
|
import junit.framework.Test;
|
||||||
import junit.framework.TestSuite;
|
import junit.framework.TestSuite;
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import org.jetbrains.jet.JetTestUtils;
|
import org.jetbrains.jet.JetTestUtils;
|
||||||
import org.jetbrains.jet.test.InnerTestClasses;
|
import org.jetbrains.jet.test.InnerTestClasses;
|
||||||
import org.jetbrains.jet.test.TestMetadata;
|
import org.jetbrains.jet.test.TestMetadata;
|
||||||
|
|
||||||
import org.jetbrains.jet.checkers.AbstractDiagnosticsTestWithEagerResolve;
|
import java.io.File;
|
||||||
|
|
||||||
/** This class is generated by {@link org.jetbrains.jet.generators.tests.GenerateTests}. DO NOT MODIFY MANUALLY */
|
/** This class is generated by {@link org.jetbrains.jet.generators.tests.GenerateTests}. DO NOT MODIFY MANUALLY */
|
||||||
@SuppressWarnings("all")
|
@SuppressWarnings("all")
|
||||||
@@ -2629,6 +2626,11 @@ public class JetDiagnosticsTestGenerated extends AbstractDiagnosticsTestWithEage
|
|||||||
doTest("compiler/testData/diagnostics/tests/j+k/kt2890.kt");
|
doTest("compiler/testData/diagnostics/tests/j+k/kt2890.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("kt3307.kt")
|
||||||
|
public void testKt3307() throws Exception {
|
||||||
|
doTest("compiler/testData/diagnostics/tests/j+k/kt3307.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("mutableIterator.kt")
|
@TestMetadata("mutableIterator.kt")
|
||||||
public void testMutableIterator() throws Exception {
|
public void testMutableIterator() throws Exception {
|
||||||
doTest("compiler/testData/diagnostics/tests/j+k/mutableIterator.kt");
|
doTest("compiler/testData/diagnostics/tests/j+k/mutableIterator.kt");
|
||||||
|
|||||||
@@ -161,6 +161,12 @@ public final class LoadJavaCustomTest extends KotlinTestWithEnvironment {
|
|||||||
dir + "SubclassWithRawType.java");
|
dir + "SubclassWithRawType.java");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void testMethodTypeParameterErased() throws Exception {
|
||||||
|
String dir = PATH + "/methodTypeParameterErased/";
|
||||||
|
doTest(dir + "MethodTypeParameterErased.txt",
|
||||||
|
dir + "MethodTypeParameterErased.java");
|
||||||
|
}
|
||||||
|
|
||||||
public static class SubclassingKotlinInJavaTest extends KotlinTestWithEnvironmentManagement {
|
public static class SubclassingKotlinInJavaTest extends KotlinTestWithEnvironmentManagement {
|
||||||
public void testSubclassingKotlinInJava() throws Exception {
|
public void testSubclassingKotlinInJava() throws Exception {
|
||||||
doTest(PATH + "/" + getTestName(true));
|
doTest(PATH + "/" + getTestName(true));
|
||||||
|
|||||||
Reference in New Issue
Block a user