Make computation of arguments for raw types lazy
See how we translate raw types to Kotlin model: RawType(A) = A<ErasedUpperBound(T1), ...> ErasedUpperBound(T : G<t>) = G<*> // UpperBound(T) is a type G<t> with arguments ErasedUpperBound(T : A) = A // UpperBound(T) is a type A without arguments ErasedUpperBound(T : F) = UpperBound(F) // UB(T) is another type parameter F Stack overflow happens with the following classes: class A<X extends B> // NB: raw type B in upper bound class B<Y extends A> // NB: raw type A in upper bound when calculating raw type for A, we start calculate ErasedUpperBound(Y), thus starting calculating raw type for B => ErasedUpperBound(X) => RawType(A), so we have SOE here. The problem is that we calculating the arguments for these raw types eagerly, while from the definition of ErasedUpperBound(Y) we only need a type constructor of raw type B (and the number of parameters), we don't use its arguments. The solution is to make arguments calculating for raw types lazy #KT-16528 Fixed
This commit is contained in:
@@ -0,0 +1,19 @@
|
||||
// FILE: JavaScriptParser.java
|
||||
public class JavaScriptParser<T extends JSPsiTypeParser> {
|
||||
public String foo() {return "OK";}
|
||||
}
|
||||
// FILE: JSPsiTypeParser.java
|
||||
public class JSPsiTypeParser<T extends JavaScriptParser> {}
|
||||
|
||||
// FILE: ES6Parser.java
|
||||
|
||||
public class ES6Parser<T extends JSPsiTypeParser> extends JavaScriptParser<T> {}
|
||||
|
||||
// FILE: main.kt
|
||||
|
||||
fun createParser(): JavaScriptParser<*> {
|
||||
return ES6Parser<JSPsiTypeParser<*>>()
|
||||
}
|
||||
|
||||
fun box(): String = createParser().foo()
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
// WITH_RUNTIME
|
||||
// FILE: Device.java
|
||||
import java.util.Collection;
|
||||
|
||||
public class Device<D extends Device, S extends Service> {
|
||||
public static Collection<Device<Device, Service>> getLoop() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
// FILE: Service.java
|
||||
|
||||
public class Service<D extends Device, S extends Service> {
|
||||
}
|
||||
|
||||
// FILE: loop.kt
|
||||
|
||||
fun box(): String {
|
||||
val x = Device.getLoop()?.firstOrNull() // compilation error
|
||||
return "OK"
|
||||
}
|
||||
+4
@@ -0,0 +1,4 @@
|
||||
// FILE: JavaScriptParser.java
|
||||
public class JavaScriptParser<F extends JSPsiTypeParser> {}
|
||||
// FILE: JSPsiTypeParser.java
|
||||
public class JSPsiTypeParser<T extends JavaScriptParser> {}
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
package
|
||||
|
||||
public open class JSPsiTypeParser</*0*/ T : JavaScriptParser<(raw) JSPsiTypeParser<*>!>!> {
|
||||
public constructor JSPsiTypeParser</*0*/ T : JavaScriptParser<(raw) JSPsiTypeParser<*>!>!>()
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
|
||||
public open class JavaScriptParser</*0*/ F : JSPsiTypeParser<(raw) JavaScriptParser<*>!>!> {
|
||||
public constructor JavaScriptParser</*0*/ F : JSPsiTypeParser<(raw) JavaScriptParser<*>!>!>()
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
@@ -15273,6 +15273,12 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTest {
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("interClassesRecursion.kt")
|
||||
public void testInterClassesRecursion() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/platformTypes/rawTypes/interClassesRecursion.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("nonGenericRawMember.kt")
|
||||
public void testNonGenericRawMember() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/platformTypes/rawTypes/nonGenericRawMember.kt");
|
||||
|
||||
+21
@@ -477,6 +477,27 @@ public class BlackBoxAgainstJavaCodegenTestGenerated extends AbstractBlackBoxAga
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("compiler/testData/codegen/boxAgainstJava/recursiveRawTypes")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
public static class RecursiveRawTypes extends AbstractBlackBoxAgainstJavaCodegenTest {
|
||||
public void testAllFilesPresentInRecursiveRawTypes() throws Exception {
|
||||
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/boxAgainstJava/recursiveRawTypes"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true);
|
||||
}
|
||||
|
||||
@TestMetadata("kt16528.kt")
|
||||
public void testKt16528() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxAgainstJava/recursiveRawTypes/kt16528.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("kt16639.kt")
|
||||
public void testKt16639() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxAgainstJava/recursiveRawTypes/kt16639.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("compiler/testData/codegen/boxAgainstJava/reflection")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
|
||||
+4
-2
@@ -218,8 +218,10 @@ class JavaTypeResolver(
|
||||
// so we get A<*, *>.
|
||||
// Summary result for upper bound of T is `A<A<*, *>, A<*, *>>..A<out A<*, *>, out A<*, *>>`
|
||||
val erasedUpperBound =
|
||||
parameter.getErasedUpperBound(attr.upperBoundOfTypeParameter) {
|
||||
constructor.declarationDescriptor!!.defaultType.replaceArgumentsWithStarProjections()
|
||||
LazyWrappedType(c.storageManager) {
|
||||
parameter.getErasedUpperBound(attr.upperBoundOfTypeParameter) {
|
||||
constructor.declarationDescriptor!!.defaultType.replaceArgumentsWithStarProjections()
|
||||
}
|
||||
}
|
||||
|
||||
RawSubstitution.computeProjection(parameter, attr, erasedUpperBound)
|
||||
|
||||
Reference in New Issue
Block a user