From 9e48ef85eafc60687fb97171ab7776a7bb0006fc Mon Sep 17 00:00:00 2001 From: Victor Petukhov Date: Wed, 7 Jul 2021 14:19:55 +0300 Subject: [PATCH] Add tests for inferring self types from Java --- .../basicInferenceForImplicitSelfType.fir.kt | 1 - .../basicInferenceForImplicitSelfType.kt | 1 - .../basicInferenceForImplicitSelfType.fir.kt | 31 +++++++++++++++++-- .../basicInferenceForImplicitSelfType.kt | 25 +++++++++++++++ .../basicInferenceForImplicitSelfType.txt | 11 +++++++ .../recursiveTypeWithTwoTypeParams.fir.kt | 17 ++++++++-- .../recursiveTypeWithTwoTypeParams.kt | 13 ++++++++ .../writerAppenderExampleRecursive.fir.kt | 25 +++++++++++++++ .../writerAppenderExampleRecursive.kt | 25 +++++++++++++++ .../writerAppenderExampleRecursive.txt | 24 ++++++++++++++ .../kotlin/types/AbstractTypeChecker.kt | 8 +++-- 11 files changed, 171 insertions(+), 10 deletions(-) diff --git a/compiler/testData/diagnostics/tests/inference/recursiveTypes/selfTypes/disabledInferenceOnSelfTypes/basicInferenceForImplicitSelfType.fir.kt b/compiler/testData/diagnostics/tests/inference/recursiveTypes/selfTypes/disabledInferenceOnSelfTypes/basicInferenceForImplicitSelfType.fir.kt index eee33a37eb3..25789449fad 100644 --- a/compiler/testData/diagnostics/tests/inference/recursiveTypes/selfTypes/disabledInferenceOnSelfTypes/basicInferenceForImplicitSelfType.fir.kt +++ b/compiler/testData/diagnostics/tests/inference/recursiveTypes/selfTypes/disabledInferenceOnSelfTypes/basicInferenceForImplicitSelfType.fir.kt @@ -2,7 +2,6 @@ class Builder> { fun test(): T = TODO() - fun foo() {} } diff --git a/compiler/testData/diagnostics/tests/inference/recursiveTypes/selfTypes/disabledInferenceOnSelfTypes/basicInferenceForImplicitSelfType.kt b/compiler/testData/diagnostics/tests/inference/recursiveTypes/selfTypes/disabledInferenceOnSelfTypes/basicInferenceForImplicitSelfType.kt index 321714c2e49..a0e2f3e65bb 100644 --- a/compiler/testData/diagnostics/tests/inference/recursiveTypes/selfTypes/disabledInferenceOnSelfTypes/basicInferenceForImplicitSelfType.kt +++ b/compiler/testData/diagnostics/tests/inference/recursiveTypes/selfTypes/disabledInferenceOnSelfTypes/basicInferenceForImplicitSelfType.kt @@ -2,7 +2,6 @@ class Builder> { fun test(): T = TODO() - fun foo() {} } diff --git a/compiler/testData/diagnostics/tests/inference/recursiveTypes/selfTypes/enabledInferenceOnSelfTypes/basicInferenceForImplicitSelfType.fir.kt b/compiler/testData/diagnostics/tests/inference/recursiveTypes/selfTypes/enabledInferenceOnSelfTypes/basicInferenceForImplicitSelfType.fir.kt index a5837fe1b92..ae1910abaa0 100644 --- a/compiler/testData/diagnostics/tests/inference/recursiveTypes/selfTypes/enabledInferenceOnSelfTypes/basicInferenceForImplicitSelfType.fir.kt +++ b/compiler/testData/diagnostics/tests/inference/recursiveTypes/selfTypes/enabledInferenceOnSelfTypes/basicInferenceForImplicitSelfType.fir.kt @@ -1,5 +1,14 @@ // !LANGUAGE: +TypeInferenceOnCallsWithSelfTypes +// FILE: JavaBuilder.java +public class JavaBuilder> { + T test() { + return null; + } + void foo() { } +} + +// FILE: main.kt class Builder> { fun test(): T = TODO() @@ -7,7 +16,7 @@ class Builder> { } fun testStar(builder: Builder<*>) { - builder.test() + ")!>builder.test() builder .test() @@ -15,9 +24,25 @@ fun testStar(builder: Builder<*>) { } fun > testTypeParam(builder: Builder) { - builder.test() + builder.test() builder .test() .foo() -} \ No newline at end of file +} + +fun testStarJava(builder: JavaBuilder<*>) { + ")!>builder.test() + + builder + .test() + .foo() +} + +fun > testTypeParamJava(builder: JavaBuilder) { + builder.test() + + builder + .test() + .foo() +} diff --git a/compiler/testData/diagnostics/tests/inference/recursiveTypes/selfTypes/enabledInferenceOnSelfTypes/basicInferenceForImplicitSelfType.kt b/compiler/testData/diagnostics/tests/inference/recursiveTypes/selfTypes/enabledInferenceOnSelfTypes/basicInferenceForImplicitSelfType.kt index 9d4dcd671f3..dba9e266066 100644 --- a/compiler/testData/diagnostics/tests/inference/recursiveTypes/selfTypes/enabledInferenceOnSelfTypes/basicInferenceForImplicitSelfType.kt +++ b/compiler/testData/diagnostics/tests/inference/recursiveTypes/selfTypes/enabledInferenceOnSelfTypes/basicInferenceForImplicitSelfType.kt @@ -1,5 +1,14 @@ // !LANGUAGE: +TypeInferenceOnCallsWithSelfTypes +// FILE: JavaBuilder.java +public class JavaBuilder> { + T test() { + return null; + } + void foo() { } +} + +// FILE: main.kt class Builder> { fun test(): T = TODO() @@ -21,3 +30,19 @@ fun > testTypeParam(builder: Builder) { .test() .foo() } + +fun testStarJava(builder: JavaBuilder<*>) { + ..JavaBuilder<*>?)")!>builder.test() + + builder + .test() + .foo() +} + +fun > testTypeParamJava(builder: JavaBuilder) { + builder.test() + + builder + .test() + .foo() +} diff --git a/compiler/testData/diagnostics/tests/inference/recursiveTypes/selfTypes/enabledInferenceOnSelfTypes/basicInferenceForImplicitSelfType.txt b/compiler/testData/diagnostics/tests/inference/recursiveTypes/selfTypes/enabledInferenceOnSelfTypes/basicInferenceForImplicitSelfType.txt index 37b74c7fc6f..a649ecfa7d8 100644 --- a/compiler/testData/diagnostics/tests/inference/recursiveTypes/selfTypes/enabledInferenceOnSelfTypes/basicInferenceForImplicitSelfType.txt +++ b/compiler/testData/diagnostics/tests/inference/recursiveTypes/selfTypes/enabledInferenceOnSelfTypes/basicInferenceForImplicitSelfType.txt @@ -1,7 +1,9 @@ package public fun testStar(/*0*/ builder: Builder<*>): kotlin.Unit +public fun testStarJava(/*0*/ builder: JavaBuilder<*>): kotlin.Unit public fun > testTypeParam(/*0*/ builder: Builder): kotlin.Unit +public fun > testTypeParamJava(/*0*/ builder: JavaBuilder): kotlin.Unit public final class Builder> { public constructor Builder>() @@ -12,3 +14,12 @@ public final class Builder> { public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String } +public open class JavaBuilder!> { + public constructor JavaBuilder!>() + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public/*package*/ open fun foo(): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public/*package*/ open fun test(): T! + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} + diff --git a/compiler/testData/diagnostics/tests/inference/recursiveTypes/selfTypes/enabledInferenceOnSelfTypes/recursiveTypeWithTwoTypeParams.fir.kt b/compiler/testData/diagnostics/tests/inference/recursiveTypes/selfTypes/enabledInferenceOnSelfTypes/recursiveTypeWithTwoTypeParams.fir.kt index 5d339b162dd..a816d2089fd 100644 --- a/compiler/testData/diagnostics/tests/inference/recursiveTypes/selfTypes/enabledInferenceOnSelfTypes/recursiveTypeWithTwoTypeParams.fir.kt +++ b/compiler/testData/diagnostics/tests/inference/recursiveTypes/selfTypes/enabledInferenceOnSelfTypes/recursiveTypeWithTwoTypeParams.fir.kt @@ -1,10 +1,23 @@ // !LANGUAGE: +TypeInferenceOnCallsWithSelfTypes +// FILE: JavaBodySpec.java +public interface JavaBodySpec> { + default T isEqualTo(B expected) { + return null; + } +} + +// FILE: main.kt interface BodySpec> { fun isEqualTo(expected: B): T } fun test(b: BodySpec) { val x = b.isEqualTo("") - x -} \ No newline at end of file + ")!>x +} + +fun testJava(b: JavaBodySpec) { + val x = b.isEqualTo("") + ")!>x +} diff --git a/compiler/testData/diagnostics/tests/inference/recursiveTypes/selfTypes/enabledInferenceOnSelfTypes/recursiveTypeWithTwoTypeParams.kt b/compiler/testData/diagnostics/tests/inference/recursiveTypes/selfTypes/enabledInferenceOnSelfTypes/recursiveTypeWithTwoTypeParams.kt index e81db1d2289..31661ec2b46 100644 --- a/compiler/testData/diagnostics/tests/inference/recursiveTypes/selfTypes/enabledInferenceOnSelfTypes/recursiveTypeWithTwoTypeParams.kt +++ b/compiler/testData/diagnostics/tests/inference/recursiveTypes/selfTypes/enabledInferenceOnSelfTypes/recursiveTypeWithTwoTypeParams.kt @@ -1,5 +1,13 @@ // !LANGUAGE: +TypeInferenceOnCallsWithSelfTypes +// FILE: JavaBodySpec.java +public interface JavaBodySpec> { + default T isEqualTo(B expected) { + return null; + } +} + +// FILE: main.kt interface BodySpec> { fun isEqualTo(expected: B): T } @@ -8,3 +16,8 @@ fun test(b: BodySpec) { val x = b.isEqualTo("") ")!>x } + +fun testJava(b: JavaBodySpec) { + val x = b.isEqualTo("") + ..JavaBodySpec<*, *>?)")!>x +} diff --git a/compiler/testData/diagnostics/tests/inference/recursiveTypes/selfTypes/enabledInferenceOnSelfTypes/writerAppenderExampleRecursive.fir.kt b/compiler/testData/diagnostics/tests/inference/recursiveTypes/selfTypes/enabledInferenceOnSelfTypes/writerAppenderExampleRecursive.fir.kt index 6375ab9f202..3722e2e66b7 100644 --- a/compiler/testData/diagnostics/tests/inference/recursiveTypes/selfTypes/enabledInferenceOnSelfTypes/writerAppenderExampleRecursive.fir.kt +++ b/compiler/testData/diagnostics/tests/inference/recursiveTypes/selfTypes/enabledInferenceOnSelfTypes/writerAppenderExampleRecursive.fir.kt @@ -1,5 +1,23 @@ // !LANGUAGE: +TypeInferenceOnCallsWithSelfTypes +// FILE: JavaWriterAppender.java +public class JavaWriterAppender { + interface Builder2> {} + + class Builder1> { + B asBuilder() { return null; } + } + + > B newBuilder() { + return null; + } + + & Builder2> B intersectTwoSelfTypes() { + return null; + } +} + +// FILE: main.kt fun test() { ")!>WriterAppender.newBuilder() >")!>WriterAppender.Builder1() @@ -7,6 +25,13 @@ fun test() { & Builder2<*>}")!>WriterAppender.intersectTwoSelfTypes() } +fun testJava(appender: JavaWriterAppender) { + ")!>appender.newBuilder() + >")!>appender.Builder1() + + & Builder2<*>}")!>appender.intersectTwoSelfTypes() +} + object WriterAppender { interface Builder2> diff --git a/compiler/testData/diagnostics/tests/inference/recursiveTypes/selfTypes/enabledInferenceOnSelfTypes/writerAppenderExampleRecursive.kt b/compiler/testData/diagnostics/tests/inference/recursiveTypes/selfTypes/enabledInferenceOnSelfTypes/writerAppenderExampleRecursive.kt index 6375ab9f202..0d6c208ad9e 100644 --- a/compiler/testData/diagnostics/tests/inference/recursiveTypes/selfTypes/enabledInferenceOnSelfTypes/writerAppenderExampleRecursive.kt +++ b/compiler/testData/diagnostics/tests/inference/recursiveTypes/selfTypes/enabledInferenceOnSelfTypes/writerAppenderExampleRecursive.kt @@ -1,5 +1,23 @@ // !LANGUAGE: +TypeInferenceOnCallsWithSelfTypes +// FILE: JavaWriterAppender.java +public class JavaWriterAppender { + interface Builder2> {} + + class Builder1> { + B asBuilder() { return null; } + } + + > B newBuilder() { + return null; + } + + & Builder2> B intersectTwoSelfTypes() { + return null; + } +} + +// FILE: main.kt fun test() { ")!>WriterAppender.newBuilder() >")!>WriterAppender.Builder1() @@ -7,6 +25,13 @@ fun test() { & Builder2<*>}")!>WriterAppender.intersectTwoSelfTypes() } +fun testJava(appender: JavaWriterAppender) { + ..JavaWriterAppender.Builder1<*>?)")!>appender.newBuilder() + ..JavaWriterAppender.Builder1<*>?)>")!>appender.Builder1() + + & Builder2<*>}..{Builder1<*>? & Builder2<*>?}?)")!>appender.intersectTwoSelfTypes() +} + object WriterAppender { interface Builder2> diff --git a/compiler/testData/diagnostics/tests/inference/recursiveTypes/selfTypes/enabledInferenceOnSelfTypes/writerAppenderExampleRecursive.txt b/compiler/testData/diagnostics/tests/inference/recursiveTypes/selfTypes/enabledInferenceOnSelfTypes/writerAppenderExampleRecursive.txt index fe013b5adc8..a23ac5e853c 100644 --- a/compiler/testData/diagnostics/tests/inference/recursiveTypes/selfTypes/enabledInferenceOnSelfTypes/writerAppenderExampleRecursive.txt +++ b/compiler/testData/diagnostics/tests/inference/recursiveTypes/selfTypes/enabledInferenceOnSelfTypes/writerAppenderExampleRecursive.txt @@ -1,6 +1,30 @@ package public fun test(): kotlin.Unit +public fun testJava(/*0*/ appender: JavaWriterAppender): kotlin.Unit + +public open class JavaWriterAppender { + public constructor JavaWriterAppender() + 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/*package*/ open fun !> intersectTwoSelfTypes(): B! where B : JavaWriterAppender.Builder2! + public/*package*/ open fun !> newBuilder(): B! + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String + + public/*package*/ open inner class Builder1!> { + public/*package*/ constructor Builder1!>() + public/*package*/ open fun asBuilder(): B! + 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/*package*/ interface Builder2!> { + 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 object WriterAppender { private constructor WriterAppender() diff --git a/core/compiler.common/src/org/jetbrains/kotlin/types/AbstractTypeChecker.kt b/core/compiler.common/src/org/jetbrains/kotlin/types/AbstractTypeChecker.kt index f8a362f3e5d..0f68bdf036e 100644 --- a/core/compiler.common/src/org/jetbrains/kotlin/types/AbstractTypeChecker.kt +++ b/core/compiler.common/src/org/jetbrains/kotlin/types/AbstractTypeChecker.kt @@ -546,13 +546,15 @@ object AbstractTypeChecker { targetType: KotlinTypeMarker ): TypeParameterMarker? { for (i in 0 until baseType.argumentsCount()) { - val typeArgument = baseType.getArgument(i).takeIf { !it.isStarProjection() } ?: continue + val typeArgument = baseType.getArgument(i).takeIf { !it.isStarProjection() }?.getType() ?: continue + val areBothTypesCaptured = + typeArgument.lowerBoundIfFlexible().isCapturedType() && targetType.lowerBoundIfFlexible().isCapturedType() - if (typeArgument.getType() == targetType) { + if (typeArgument == targetType || (areBothTypesCaptured && typeArgument.typeConstructor() == targetType.typeConstructor())) { return baseType.typeConstructor().getParameter(i) } - getTypeParameterForArgumentInBaseIfItEqualToTarget(typeArgument.getType(), targetType)?.let { return it } + getTypeParameterForArgumentInBaseIfItEqualToTarget(typeArgument, targetType)?.let { return it } } return null