Don't look at raw type's arguments while enhancing super types

^KT-48172 Fixed
This commit is contained in:
Victor Petukhov
2021-08-17 18:41:34 +03:00
committed by TeamCityServer
parent 63cefe228d
commit d730db094a
14 changed files with 188 additions and 33 deletions
@@ -1350,6 +1350,11 @@ public class IncrementalFirJvmCompilerRunnerTestGenerated extends AbstractIncrem
runTest("jps-plugin/testData/incremental/withJava/javaUsedInKotlin/notChangeSignature/");
}
@TestMetadata("rawErrorTypeDuringSerialization")
public void testRawErrorTypeDuringSerialization() throws Exception {
runTest("jps-plugin/testData/incremental/withJava/javaUsedInKotlin/rawErrorTypeDuringSerialization/");
}
@TestMetadata("jps-plugin/testData/incremental/withJava/javaUsedInKotlin/changeFieldType")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
@@ -1597,6 +1602,19 @@ public class IncrementalFirJvmCompilerRunnerTestGenerated extends AbstractIncrem
}
}
@TestMetadata("jps-plugin/testData/incremental/withJava/javaUsedInKotlin/rawErrorTypeDuringSerialization")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class RawErrorTypeDuringSerialization extends AbstractIncrementalFirJvmCompilerRunnerTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, TargetBackend.JVM_IR, testDataFilePath);
}
public void testAllFilesPresentInRawErrorTypeDuringSerialization() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("jps-plugin/testData/incremental/withJava/javaUsedInKotlin/rawErrorTypeDuringSerialization"), Pattern.compile("^([^\\.]+)$"), null, TargetBackend.JVM_IR, true);
}
}
@TestMetadata("jps-plugin/testData/incremental/withJava/javaUsedInKotlin/samConversions")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
@@ -1350,6 +1350,11 @@ public class IncrementalJvmCompilerRunnerTestGenerated extends AbstractIncrement
runTest("jps-plugin/testData/incremental/withJava/javaUsedInKotlin/notChangeSignature/");
}
@TestMetadata("rawErrorTypeDuringSerialization")
public void testRawErrorTypeDuringSerialization() throws Exception {
runTest("jps-plugin/testData/incremental/withJava/javaUsedInKotlin/rawErrorTypeDuringSerialization/");
}
@TestMetadata("jps-plugin/testData/incremental/withJava/javaUsedInKotlin/changeFieldType")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
@@ -1597,6 +1602,19 @@ public class IncrementalJvmCompilerRunnerTestGenerated extends AbstractIncrement
}
}
@TestMetadata("jps-plugin/testData/incremental/withJava/javaUsedInKotlin/rawErrorTypeDuringSerialization")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class RawErrorTypeDuringSerialization extends AbstractIncrementalJvmCompilerRunnerTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, TargetBackend.JVM_IR, testDataFilePath);
}
public void testAllFilesPresentInRawErrorTypeDuringSerialization() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("jps-plugin/testData/incremental/withJava/javaUsedInKotlin/rawErrorTypeDuringSerialization"), Pattern.compile("^([^\\.]+)$"), null, TargetBackend.JVM_IR, true);
}
}
@TestMetadata("jps-plugin/testData/incremental/withJava/javaUsedInKotlin/samConversions")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
@@ -1350,6 +1350,11 @@ public class IncrementalJvmOldBackendCompilerRunnerTestGenerated extends Abstrac
runTest("jps-plugin/testData/incremental/withJava/javaUsedInKotlin/notChangeSignature/");
}
@TestMetadata("rawErrorTypeDuringSerialization")
public void testRawErrorTypeDuringSerialization() throws Exception {
runTest("jps-plugin/testData/incremental/withJava/javaUsedInKotlin/rawErrorTypeDuringSerialization/");
}
@TestMetadata("jps-plugin/testData/incremental/withJava/javaUsedInKotlin/changeFieldType")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
@@ -1597,6 +1602,19 @@ public class IncrementalJvmOldBackendCompilerRunnerTestGenerated extends Abstrac
}
}
@TestMetadata("jps-plugin/testData/incremental/withJava/javaUsedInKotlin/rawErrorTypeDuringSerialization")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class RawErrorTypeDuringSerialization extends AbstractIncrementalJvmOldBackendCompilerRunnerTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, TargetBackend.JVM, testDataFilePath);
}
public void testAllFilesPresentInRawErrorTypeDuringSerialization() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("jps-plugin/testData/incremental/withJava/javaUsedInKotlin/rawErrorTypeDuringSerialization"), Pattern.compile("^([^\\.]+)$"), null, TargetBackend.JVM, true);
}
}
@TestMetadata("jps-plugin/testData/incremental/withJava/javaUsedInKotlin/samConversions")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
@@ -3,7 +3,7 @@ package test
public open class RawSuperTypeWithRecursiveBound {
public constructor RawSuperTypeWithRecursiveBound()
public open inner class Derived : test.RawSuperTypeWithRecursiveBound.Super<(raw) *> {
public open inner class Derived : test.RawSuperTypeWithRecursiveBound.Super<(raw) test.RawSuperTypeWithRecursiveBound.Super<*>!> {
public constructor Derived()
public open override /*1*/ fun dummy(): kotlin.Unit
public open fun foo(/*0*/ p0: kotlin.Any!): kotlin.Unit
@@ -3,7 +3,7 @@ package test
public open class RawSuperTypeWithRecursiveBoundMultipleParameters {
public constructor RawSuperTypeWithRecursiveBoundMultipleParameters()
public open inner class Derived : test.RawSuperTypeWithRecursiveBoundMultipleParameters.Super<(raw) kotlin.Any!, (raw) *> {
public open inner class Derived : test.RawSuperTypeWithRecursiveBoundMultipleParameters.Super<(raw) kotlin.Any!, (raw) test.RawSuperTypeWithRecursiveBoundMultipleParameters.Super<*, *>!> {
public constructor Derived()
public open override /*1*/ fun dummy(): kotlin.Unit
public open fun foo(/*0*/ p0: kotlin.Any!, /*1*/ p1: kotlin.Any!): kotlin.Unit
@@ -252,7 +252,10 @@ class SignatureEnhancement(
* class A extends B<@NotNull Integer> {}
*/
fun enhanceSuperType(type: KotlinType, context: LazyJavaResolverContext) =
SignatureParts(null, type, emptyList(), false, context, AnnotationQualifierApplicabilityType.TYPE_USE).enhance().type
SignatureParts(
typeContainer = null, type, emptyList(), isCovariant = false,
context, AnnotationQualifierApplicabilityType.TYPE_USE, isSuperTypesEnhancement = true
).enhance().type
private inner class SignatureParts(
private val typeContainer: Annotated?,
@@ -261,7 +264,8 @@ class SignatureEnhancement(
private val isCovariant: Boolean,
private val containerContext: LazyJavaResolverContext,
private val containerApplicabilityType: AnnotationQualifierApplicabilityType,
private val typeParameterBounds: Boolean = false
private val typeParameterBounds: Boolean = false,
private val isSuperTypesEnhancement: Boolean = false
) {
private val isForVarargParameter get() = typeContainer.safeAs<ValueParameterDescriptor>()?.varargElementType != null
@@ -275,15 +279,21 @@ class SignatureEnhancement(
}
}
val containsFunctionN = TypeUtils.contains(fromOverride) {
val classifier = it.constructor.declarationDescriptor ?: return@contains false
fun containsFunctionN(type: UnwrappedType): Boolean {
val classifier = type.constructor.declarationDescriptor ?: return false
classifier.name == JavaToKotlinClassMap.FUNCTION_N_FQ_NAME.shortName() &&
return classifier.name == JavaToKotlinClassMap.FUNCTION_N_FQ_NAME.shortName() &&
classifier.fqNameOrNull() == JavaToKotlinClassMap.FUNCTION_N_FQ_NAME
}
val containsFunctionN = if (isSuperTypesEnhancement) {
TypeUtils.containsStoppingAt(fromOverride, ::containsFunctionN) { it is RawType }
} else {
TypeUtils.contains(fromOverride, ::containsFunctionN)
}
return with(typeEnhancement) {
fromOverride.enhance(qualifiersWithPredefined ?: qualifiers)?.let { enhanced ->
fromOverride.enhance(qualifiersWithPredefined ?: qualifiers, isSuperTypesEnhancement)?.let { enhanced ->
PartEnhancementResult(enhanced, wereChanges = true, containsFunctionN = containsFunctionN)
} ?: PartEnhancementResult(fromOverride, wereChanges = false, containsFunctionN = containsFunctionN)
}
@@ -531,6 +541,8 @@ class SignatureEnhancement(
)
)
if (isSuperTypesEnhancement && type is RawType) return
for ((arg, parameter) in type.arguments.zip(type.constructor.parameters)) {
if (arg.isStarProjection) {
// TODO: sort out how to handle wildcards
@@ -52,15 +52,24 @@ class JavaTypeEnhancement(private val javaResolverSettings: JavaResolverSettings
// Example: for `A<B, C<D, E>>`, indices go as follows: `0 - A<...>, 1 - B, 2 - C<D, E>, 3 - D, 4 - E`,
// which corresponds to the left-to-right breadth-first walk of the tree representation of the type.
// For flexible types, both bounds are indexed in the same way: `(A<B>..C<D>)` gives `0 - (A<B>..C<D>), 1 - B and D`.
fun KotlinType.enhance(qualifiers: (Int) -> JavaTypeQualifiers) = unwrap().enhancePossiblyFlexible(qualifiers, 0).type
fun KotlinType.enhance(qualifiers: (Int) -> JavaTypeQualifiers, isSuperTypesEnhancement: Boolean = false) =
unwrap().enhancePossiblyFlexible(qualifiers, 0, isSuperTypesEnhancement).type
private fun UnwrappedType.enhancePossiblyFlexible(qualifiers: (Int) -> JavaTypeQualifiers, index: Int): Result {
private fun UnwrappedType.enhancePossiblyFlexible(
qualifiers: (Int) -> JavaTypeQualifiers,
index: Int,
isSuperTypesEnhancement: Boolean = false
): Result {
if (isError) return Result(null, 1)
return when (this) {
is FlexibleType -> {
val isRawType = this is RawType
val lowerResult = lowerBound.enhanceInflexible(qualifiers, index, TypeComponentPosition.FLEXIBLE_LOWER, isRawType)
val upperResult = upperBound.enhanceInflexible(qualifiers, index, TypeComponentPosition.FLEXIBLE_UPPER, isRawType)
val lowerResult = lowerBound.enhanceInflexible(
qualifiers, index, TypeComponentPosition.FLEXIBLE_LOWER, isRawType, isSuperTypesEnhancement
)
val upperResult = upperBound.enhanceInflexible(
qualifiers, index, TypeComponentPosition.FLEXIBLE_UPPER, isRawType, isSuperTypesEnhancement
)
assert(lowerResult.subtreeSize == upperResult.subtreeSize) {
"Different tree sizes of bounds: " +
"lower = ($lowerBound, ${lowerResult.subtreeSize}), " +
@@ -80,7 +89,9 @@ class JavaTypeEnhancement(private val javaResolverSettings: JavaResolverSettings
Result(type, lowerResult.subtreeSize)
}
is SimpleType -> {
val result = enhanceInflexible(qualifiers, index, TypeComponentPosition.INFLEXIBLE)
val result = enhanceInflexible(
qualifiers, index, TypeComponentPosition.INFLEXIBLE, isSuperTypesEnhancement = isSuperTypesEnhancement
)
Result(if (result.forWarnings) wrapEnhancement(result.type) else result.type, result.subtreeSize)
}
}
@@ -90,7 +101,8 @@ class JavaTypeEnhancement(private val javaResolverSettings: JavaResolverSettings
qualifiers: (Int) -> JavaTypeQualifiers,
index: Int,
position: TypeComponentPosition,
isBoundOfRawType: Boolean = false
isBoundOfRawType: Boolean = false,
isSuperTypesEnhancement: Boolean = false
): SimpleResult {
val shouldEnhance = position.shouldEnhance()
if (!shouldEnhance && arguments.isEmpty()) return SimpleResult(null, 1, false)
@@ -105,24 +117,29 @@ class JavaTypeEnhancement(private val javaResolverSettings: JavaResolverSettings
var globalArgIndex = index + 1
var wereChanges = enhancedMutabilityAnnotations != null
val enhancedArguments = arguments.mapIndexed { localArgIndex, arg ->
if (arg.isStarProjection) {
val qualifiersForStarProjection = qualifiers(globalArgIndex)
globalArgIndex++
val enhancedArguments = if (!isSuperTypesEnhancement || !isBoundOfRawType) {
arguments.mapIndexed { localArgIndex, arg ->
if (arg.isStarProjection) {
val qualifiersForStarProjection = qualifiers(globalArgIndex)
globalArgIndex++
if (qualifiersForStarProjection.nullability == NOT_NULL && !isBoundOfRawType) {
val enhanced = arg.type.unwrap().makeNotNullable()
createProjection(enhanced, arg.projectionKind, typeParameterDescriptor = typeConstructor.parameters[localArgIndex])
if (qualifiersForStarProjection.nullability == NOT_NULL && !isBoundOfRawType) {
val enhanced = arg.type.unwrap().makeNotNullable()
createProjection(enhanced, arg.projectionKind, typeParameterDescriptor = typeConstructor.parameters[localArgIndex])
} else {
TypeUtils.makeStarProjection(enhancedClassifier.typeConstructor.parameters[localArgIndex])
}
} else {
TypeUtils.makeStarProjection(enhancedClassifier.typeConstructor.parameters[localArgIndex])
}
} else {
val unwrapped = arg.type.unwrap()
val enhanced = unwrapped.enhancePossiblyFlexible(qualifiers, globalArgIndex)
globalArgIndex += enhanced.subtreeSize
val type = enhanced.type?.also { wereChanges = true } ?: unwrapped
val unwrapped = arg.type.unwrap()
val enhanced = unwrapped.enhancePossiblyFlexible(qualifiers, globalArgIndex, isSuperTypesEnhancement)
globalArgIndex += enhanced.subtreeSize
val type = enhanced.type?.also { wereChanges = true } ?: unwrapped
createProjection(type, arg.projectionKind, typeParameterDescriptor = typeConstructor.parameters[localArgIndex])
}
}
} else {
globalArgIndex += arguments.size
arguments
}
val (enhancedNullability, enhancedNullabilityAnnotations) = this.getEnhancedNullability(effectiveQualifiers, position)
@@ -425,12 +425,21 @@ public class TypeUtils {
@Nullable KotlinType type,
@NotNull Function1<UnwrappedType, Boolean> isSpecialType
) {
return contains(type, isSpecialType, null);
return contains(type, isSpecialType, null, null);
}
public static boolean containsStoppingAt(
@Nullable KotlinType type,
@NotNull Function1<UnwrappedType, Boolean> isSpecialType,
@NotNull Function1<KotlinType, Boolean> shouldStopAt
) {
return contains(type, isSpecialType, shouldStopAt, null);
}
private static boolean contains(
@Nullable KotlinType type,
@NotNull Function1<UnwrappedType, Boolean> isSpecialType,
@Nullable Function1<KotlinType, Boolean> shouldStopAt,
SmartSet<KotlinType> visited
) {
if (type == null) return false;
@@ -440,6 +449,7 @@ public class TypeUtils {
if (noExpectedType(type)) return isSpecialType.invoke(unwrappedType);
if (visited != null && visited.contains(type)) return false;
if (isSpecialType.invoke(unwrappedType)) return true;
if (shouldStopAt != null && shouldStopAt.invoke(unwrappedType)) return false;
if (visited == null) {
visited = SmartSet.create();
@@ -448,12 +458,13 @@ public class TypeUtils {
FlexibleType flexibleType = unwrappedType instanceof FlexibleType ? (FlexibleType) unwrappedType : null;
if (flexibleType != null
&& (contains(flexibleType.getLowerBound(), isSpecialType, visited) || contains(flexibleType.getUpperBound(), isSpecialType, visited))) {
&& (contains(flexibleType.getLowerBound(), isSpecialType, shouldStopAt, visited)
|| contains(flexibleType.getUpperBound(), isSpecialType, shouldStopAt, visited))) {
return true;
}
if (unwrappedType instanceof DefinitelyNotNullType &&
contains(((DefinitelyNotNullType) unwrappedType).getOriginal(), isSpecialType, visited)) {
contains(((DefinitelyNotNullType) unwrappedType).getOriginal(), isSpecialType, shouldStopAt, visited)) {
return true;
}
@@ -461,13 +472,14 @@ public class TypeUtils {
if (typeConstructor instanceof IntersectionTypeConstructor) {
IntersectionTypeConstructor intersectionTypeConstructor = (IntersectionTypeConstructor) typeConstructor;
for (KotlinType supertype : intersectionTypeConstructor.getSupertypes()) {
if (contains(supertype, isSpecialType, visited)) return true;
if (contains(supertype, isSpecialType, shouldStopAt, visited)) return true;
}
return false;
}
for (TypeProjection projection : type.getArguments()) {
if (!projection.isStarProjection() && contains(projection.getType(), isSpecialType, visited)) return true;
if (projection.isStarProjection()) continue;
if (contains(projection.getType(), isSpecialType, shouldStopAt, visited)) return true;
}
return false;
}
@@ -0,0 +1,2 @@
class Bar<K> {
}
@@ -0,0 +1,27 @@
// WITH_RUNTIME
// TARGET_BACKEND: JVM
/*
ServletOpenApiContextBuilder<
T : raw (
ServletOpenApiContextBuilder<ServletOpenApiContextBuilder<*>>
..
ServletOpenApiContextBuilder<out ServletOpenApiContextBuilder<*>>?
)
>
: GenericOpenApiContextBuilder<
raw (
ServletOpenApiContextBuilder<[ERROR : <LOOP IN SUPERTYPES>]> // exception on this error type during serialization
..
ServletOpenApiContextBuilder<*>?
)
>
*/
public class Foo<T extends Foo> extends Bar<Foo> {
String ctxId = "";
public T ctxId(String ctxId) {
this.ctxId = ctxId;
return (T) this;
}
}
@@ -0,0 +1,11 @@
// WITH_RUNTIME
// TARGET_BACKEND: JVM
public class Foo<T extends Foo> extends Bar<Foo> {
String ctxId = "";
public T ctxId(String ctxId) {
this.ctxId = ctxId;
return (T) this;
}
}
@@ -0,0 +1,6 @@
================ Step #1 =================
Compiling files:
End of files
Exit code: OK
@@ -0,0 +1,7 @@
================ Step #1 =================
Compiling files:
src/main.kt
End of files
Exit code: OK
@@ -0,0 +1,7 @@
class Main {
fun init() {
Foo<Foo<*>>() //this is the call that causes the build exception, if you comment it out everything works fine
.ctxId("")
}
}
fun box() = "OK"