From 517688e1638ad4b18d9bb8948f7596b344ca898a Mon Sep 17 00:00:00 2001 From: Pavel Kirpichenkov Date: Thu, 30 Jan 2020 19:06:21 +0300 Subject: [PATCH] [NI] Revise variance calculation method for completion mode Before fix only one level of type arguments was used to determine variance of type variable to find out direction requirements. This incorrect in general case, because outer variance affects subtyping deductions, for example: Inv> <: Inv> => A <: B; B <: A, despite A and B are in covariant position if only one level is considered ^KT-36233 Fixed --- ...irOldFrontendDiagnosticsTestGenerated.java | 30 ++++++ .../components/CompletionModeCalculator.kt | 95 +++++++++++-------- .../completion/definetlyNotNullType.fir.kt | 39 ++++++++ .../completion/definetlyNotNullType.kt | 39 ++++++++ .../completion/definetlyNotNullType.txt | 43 +++++++++ .../inference/completion/flexibleType.fir.kt | 60 ++++++++++++ .../inference/completion/flexibleType.kt | 60 ++++++++++++ .../inference/completion/flexibleType.txt | 60 ++++++++++++ .../completion/intersectionType.fir.kt | 42 ++++++++ .../inference/completion/intersectionType.kt | 42 ++++++++ .../inference/completion/intersectionType.txt | 60 ++++++++++++ .../tests/inference/completion/kt36233.fir.kt | 13 +++ .../tests/inference/completion/kt36233.kt | 13 +++ .../tests/inference/completion/kt36233.txt | 19 ++++ .../completion/nestedVariance.fir.kt | 78 +++++++++++++++ .../inference/completion/nestedVariance.kt | 78 +++++++++++++++ .../inference/completion/nestedVariance.txt | 67 +++++++++++++ .../completion/nothingFromNestedCall.fir.kt | 13 +++ .../completion/nothingFromNestedCall.kt | 13 +++ .../completion/nothingFromNestedCall.txt | 19 ++++ .../checkers/DiagnosticsTestGenerated.java | 30 ++++++ .../DiagnosticsUsingJavacTestGenerated.java | 30 ++++++ 22 files changed, 904 insertions(+), 39 deletions(-) create mode 100644 compiler/testData/diagnostics/tests/inference/completion/definetlyNotNullType.fir.kt create mode 100644 compiler/testData/diagnostics/tests/inference/completion/definetlyNotNullType.kt create mode 100644 compiler/testData/diagnostics/tests/inference/completion/definetlyNotNullType.txt create mode 100644 compiler/testData/diagnostics/tests/inference/completion/flexibleType.fir.kt create mode 100644 compiler/testData/diagnostics/tests/inference/completion/flexibleType.kt create mode 100644 compiler/testData/diagnostics/tests/inference/completion/flexibleType.txt create mode 100644 compiler/testData/diagnostics/tests/inference/completion/intersectionType.fir.kt create mode 100644 compiler/testData/diagnostics/tests/inference/completion/intersectionType.kt create mode 100644 compiler/testData/diagnostics/tests/inference/completion/intersectionType.txt create mode 100644 compiler/testData/diagnostics/tests/inference/completion/kt36233.fir.kt create mode 100644 compiler/testData/diagnostics/tests/inference/completion/kt36233.kt create mode 100644 compiler/testData/diagnostics/tests/inference/completion/kt36233.txt create mode 100644 compiler/testData/diagnostics/tests/inference/completion/nestedVariance.fir.kt create mode 100644 compiler/testData/diagnostics/tests/inference/completion/nestedVariance.kt create mode 100644 compiler/testData/diagnostics/tests/inference/completion/nestedVariance.txt create mode 100644 compiler/testData/diagnostics/tests/inference/completion/nothingFromNestedCall.fir.kt create mode 100644 compiler/testData/diagnostics/tests/inference/completion/nothingFromNestedCall.kt create mode 100644 compiler/testData/diagnostics/tests/inference/completion/nothingFromNestedCall.txt diff --git a/compiler/fir/resolve/tests/org/jetbrains/kotlin/fir/FirOldFrontendDiagnosticsTestGenerated.java b/compiler/fir/resolve/tests/org/jetbrains/kotlin/fir/FirOldFrontendDiagnosticsTestGenerated.java index ea5c05149c7..38a724a200c 100644 --- a/compiler/fir/resolve/tests/org/jetbrains/kotlin/fir/FirOldFrontendDiagnosticsTestGenerated.java +++ b/compiler/fir/resolve/tests/org/jetbrains/kotlin/fir/FirOldFrontendDiagnosticsTestGenerated.java @@ -10602,21 +10602,51 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirOldFronte runTest("compiler/testData/diagnostics/tests/inference/completion/basic.kt"); } + @TestMetadata("definetlyNotNullType.kt") + public void testDefinetlyNotNullType() throws Exception { + runTest("compiler/testData/diagnostics/tests/inference/completion/definetlyNotNullType.kt"); + } + @TestMetadata("equalityConstraintUpstairs.kt") public void testEqualityConstraintUpstairs() throws Exception { runTest("compiler/testData/diagnostics/tests/inference/completion/equalityConstraintUpstairs.kt"); } + @TestMetadata("flexibleType.kt") + public void testFlexibleType() throws Exception { + runTest("compiler/testData/diagnostics/tests/inference/completion/flexibleType.kt"); + } + + @TestMetadata("intersectionType.kt") + public void testIntersectionType() throws Exception { + runTest("compiler/testData/diagnostics/tests/inference/completion/intersectionType.kt"); + } + @TestMetadata("kt33166.kt") public void testKt33166() throws Exception { runTest("compiler/testData/diagnostics/tests/inference/completion/kt33166.kt"); } + @TestMetadata("kt36233.kt") + public void testKt36233() throws Exception { + runTest("compiler/testData/diagnostics/tests/inference/completion/kt36233.kt"); + } + @TestMetadata("lambdaWithVariableAndNothing.kt") public void testLambdaWithVariableAndNothing() throws Exception { runTest("compiler/testData/diagnostics/tests/inference/completion/lambdaWithVariableAndNothing.kt"); } + @TestMetadata("nestedVariance.kt") + public void testNestedVariance() throws Exception { + runTest("compiler/testData/diagnostics/tests/inference/completion/nestedVariance.kt"); + } + + @TestMetadata("nothingFromNestedCall.kt") + public void testNothingFromNestedCall() throws Exception { + runTest("compiler/testData/diagnostics/tests/inference/completion/nothingFromNestedCall.kt"); + } + @TestMetadata("partialForIlt.kt") public void testPartialForIlt() throws Exception { runTest("compiler/testData/diagnostics/tests/inference/completion/partialForIlt.kt"); diff --git a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/CompletionModeCalculator.kt b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/CompletionModeCalculator.kt index 5d1f16609bb..f2fc75067e8 100644 --- a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/CompletionModeCalculator.kt +++ b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/CompletionModeCalculator.kt @@ -83,19 +83,16 @@ class CompletionModeCalculator { while (typesToProcess.isNotEmpty()) { val type = typesToProcess.poll() ?: break - fixationDirectionForTopLevel(type)?.let { directionForVariable -> + if (!type.contains { it.typeConstructor() in notFixedTypeVariables }) + continue + + val fixationDirectionsFromType = mutableSetOf() + collectRequiredDirectionsForVariables(type, TypeVariance.OUT, fixationDirectionsFromType) + + for (directionForVariable in fixationDirectionsFromType) { updateDirection(directionForVariable) enqueueTypesFromConstraints(directionForVariable.variable) } - - // find all variables in type and make requirements for them - type.contains { typePart -> - for (directionForVariable in directionsForVariablesInTypeArguments(typePart)) { - updateDirection(directionForVariable) - enqueueTypesFromConstraints(directionForVariable.variable) - } - false - } } } @@ -130,42 +127,62 @@ class CompletionModeCalculator { private data class FixationDirectionForVariable(val variable: VariableWithConstraints, val direction: FixationDirection) - private fun CsCompleterContext.fixationDirectionForTopLevel(type: KotlinTypeMarker): FixationDirectionForVariable? { - return notFixedTypeVariables[type.typeConstructor()]?.let { - FixationDirectionForVariable(it, FixationDirection.TO_SUBTYPE) + private fun CsCompleterContext.collectRequiredDirectionsForVariables( + type: KotlinTypeMarker, outerVariance: TypeVariance, + fixationDirectionsCollector: MutableSet + ) { + val typeArgumentsCount = type.argumentsCount() + if (typeArgumentsCount > 0) { + for (position in 0 until typeArgumentsCount) { + val argument = type.getArgument(position) + val parameter = type.typeConstructor().getParameter(position) + + if (argument.isStarProjection()) + continue + + collectRequiredDirectionsForVariables( + argument.getType(), + compositeVariance(outerVariance, argument, parameter), + fixationDirectionsCollector + ) + } + } else { + processTypeWithoutParameters(type, outerVariance, fixationDirectionsCollector) } } - private fun CsCompleterContext.directionsForVariablesInTypeArguments(type: KotlinTypeMarker): List { - assert(type.argumentsCount() == type.typeConstructor().parametersCount()) { - "Arguments and parameters count don't match for type $type. " + - "Arguments: ${type.argumentsCount()}, parameters: ${type.typeConstructor().parametersCount()}" + private fun CsCompleterContext.compositeVariance( + outerVariance: TypeVariance, + argument: TypeArgumentMarker, + parameter: TypeParameterMarker + ): TypeVariance { + val effectiveArgumentVariance = AbstractTypeChecker.effectiveVariance(parameter.getVariance(), argument.getVariance()) + ?: TypeVariance.INV // conflicting variance + return when (outerVariance) { + TypeVariance.INV -> TypeVariance.INV + TypeVariance.OUT -> effectiveArgumentVariance + TypeVariance.IN -> effectiveArgumentVariance.reversed() } + } - val directionsForVariables = mutableListOf() + private fun TypeVariance.reversed(): TypeVariance = when (this) { + TypeVariance.IN -> TypeVariance.OUT + TypeVariance.OUT -> TypeVariance.IN + TypeVariance.INV -> TypeVariance.INV + } - for (position in 0 until type.argumentsCount()) { - val argument = type.getArgument(position) - if (!argument.getType().mayBeTypeVariable()) - continue - - val variableWithConstraints = notFixedTypeVariables[argument.getType().typeConstructor()] ?: continue - - val parameter = type.typeConstructor().getParameter(position) - val effectiveVariance = AbstractTypeChecker.effectiveVariance(parameter.getVariance(), argument.getVariance()) - ?: TypeVariance.INV - - val direction = when (effectiveVariance) { - TypeVariance.IN -> FixationDirection.EQUALITY // Assuming that variables in contravariant positions are fixed to subtype - TypeVariance.OUT -> FixationDirection.TO_SUBTYPE - TypeVariance.INV -> FixationDirection.EQUALITY - } - - val requirement = FixationDirectionForVariable(variableWithConstraints, direction) - directionsForVariables.add(requirement) + private fun CsCompleterContext.processTypeWithoutParameters( + type: KotlinTypeMarker, compositeVariance: TypeVariance, + newRequirementsCollector: MutableSet + ) { + val variableWithConstraints = notFixedTypeVariables[type.typeConstructor()] ?: return + val direction = when (compositeVariance) { + TypeVariance.IN -> FixationDirection.EQUALITY // Assuming that variables in contravariant positions are fixed to subtype + TypeVariance.OUT -> FixationDirection.TO_SUBTYPE + TypeVariance.INV -> FixationDirection.EQUALITY } - - return directionsForVariables + val requirement = FixationDirectionForVariable(variableWithConstraints, direction) + newRequirementsCollector.add(requirement) } private fun CsCompleterContext.hasProperConstraint( diff --git a/compiler/testData/diagnostics/tests/inference/completion/definetlyNotNullType.fir.kt b/compiler/testData/diagnostics/tests/inference/completion/definetlyNotNullType.fir.kt new file mode 100644 index 00000000000..7b7d0461d29 --- /dev/null +++ b/compiler/testData/diagnostics/tests/inference/completion/definetlyNotNullType.fir.kt @@ -0,0 +1,39 @@ +// !LANGUAGE: +NewInference +// !DIAGNOSTICS: -UNUSED_PARAMETER + +fun test(derived: T) { + id>( + makeOut( + makeDnn(derived) + ) + ) + id>( + makeIn( + makeDnn(derived) + ) + ) + id>( + makeInv( + makeDnn(derived) + ) + ) + id>>( + makeInIn( + makeDnn(derived) + ) + ) +} + +interface Base +open class Derived : Base + +class Inv +class Out +class In + +fun id(arg: K) = arg +fun makeDnn(arg: T?): T = TODO() +fun makeInv(arg: T): Inv = TODO() +fun makeOut(arg: T): Out = TODO() +fun makeIn(arg: T): In = TODO() +fun makeInIn(arg: T): In> = TODO() diff --git a/compiler/testData/diagnostics/tests/inference/completion/definetlyNotNullType.kt b/compiler/testData/diagnostics/tests/inference/completion/definetlyNotNullType.kt new file mode 100644 index 00000000000..589fcb9da92 --- /dev/null +++ b/compiler/testData/diagnostics/tests/inference/completion/definetlyNotNullType.kt @@ -0,0 +1,39 @@ +// !LANGUAGE: +NewInference +// !DIAGNOSTICS: -UNUSED_PARAMETER + +fun test(derived: T) { + ")!>id>( + makeOut( + makeDnn(derived) + ) + ) + ")!>id>( + ")!>makeIn( + makeDnn(derived) + ) + ) + ")!>id>( + ")!>makeInv( + makeDnn(derived) + ) + ) + >")!>id>>( + makeInIn( + makeDnn(derived) + ) + ) +} + +interface Base +open class Derived : Base + +class Inv +class Out +class In + +fun id(arg: K) = arg +fun makeDnn(arg: T?): T = TODO() +fun makeInv(arg: T): Inv = TODO() +fun makeOut(arg: T): Out = TODO() +fun makeIn(arg: T): In = TODO() +fun makeInIn(arg: T): In> = TODO() diff --git a/compiler/testData/diagnostics/tests/inference/completion/definetlyNotNullType.txt b/compiler/testData/diagnostics/tests/inference/completion/definetlyNotNullType.txt new file mode 100644 index 00000000000..bbf7ae9ea43 --- /dev/null +++ b/compiler/testData/diagnostics/tests/inference/completion/definetlyNotNullType.txt @@ -0,0 +1,43 @@ +package + +public fun id(/*0*/ arg: K): K +public fun makeDnn(/*0*/ arg: T?): T +public fun makeIn(/*0*/ arg: T): In +public fun makeInIn(/*0*/ arg: T): In> +public fun makeInv(/*0*/ arg: T): Inv +public fun makeOut(/*0*/ arg: T): Out +public fun test(/*0*/ derived: T): kotlin.Unit + +public interface Base { + 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 Derived : Base { + public constructor Derived() + 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 final class In { + public constructor In() + 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 final class Inv { + public constructor Inv() + 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 final class Out { + public constructor Out() + 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 +} diff --git a/compiler/testData/diagnostics/tests/inference/completion/flexibleType.fir.kt b/compiler/testData/diagnostics/tests/inference/completion/flexibleType.fir.kt new file mode 100644 index 00000000000..868db4ac7ea --- /dev/null +++ b/compiler/testData/diagnostics/tests/inference/completion/flexibleType.fir.kt @@ -0,0 +1,60 @@ +// !LANGUAGE: +NewInference +// !DIAGNOSTICS: -UNUSED_PARAMETER + +// FILE: Test.kt + +fun test(arg: Derived) { + id>( + createOut( + JavaCls.makeFlexible(arg) + ) + ) + id>( + createIn( + JavaCls.makeFlexible(arg) + ) + ) + id>( + createInv( + JavaCls.makeFlexible(arg) + ) + ) + id>>( + createJavaInv( + JavaCls.makeFlexible(arg) + ) + ) + id>>( + createInIn( + JavaCls.makeFlexible(arg) + ) + ) +} + +interface Base +class Derived : Base + +class Inv +class Out +class In + +fun id(arg: K) = arg + +fun createInv(arg: T): Inv = TODO() +fun createOut(arg: T): Out = TODO() +fun createIn(arg: T): In = TODO() +fun createInIn(arg: T): In> = TODO() +fun createJavaInv(arg: T): JavaInv> = TODO() + +// FILE: JavaCls.java + +public class JavaCls { + public static T makeFlexible(T argument) { + return argument; + } +} + +// FILE: JavaInv.java + +public class JavaInv { +} diff --git a/compiler/testData/diagnostics/tests/inference/completion/flexibleType.kt b/compiler/testData/diagnostics/tests/inference/completion/flexibleType.kt new file mode 100644 index 00000000000..42b595213d2 --- /dev/null +++ b/compiler/testData/diagnostics/tests/inference/completion/flexibleType.kt @@ -0,0 +1,60 @@ +// !LANGUAGE: +NewInference +// !DIAGNOSTICS: -UNUSED_PARAMETER + +// FILE: Test.kt + +fun test(arg: Derived) { + ")!>id>( + ")!>createOut( + JavaCls.makeFlexible(arg) + ) + ) + ")!>id>( + ")!>createIn( + JavaCls.makeFlexible(arg) + ) + ) + ")!>id>( + ")!>createInv( + JavaCls.makeFlexible(arg) + ) + ) + >")!>id>>( + >")!>createJavaInv( + JavaCls.makeFlexible(arg) + ) + ) + >")!>id>>( + >")!>createInIn( + JavaCls.makeFlexible(arg) + ) + ) +} + +interface Base +class Derived : Base + +class Inv +class Out +class In + +fun id(arg: K) = arg + +fun createInv(arg: T): Inv = TODO() +fun createOut(arg: T): Out = TODO() +fun createIn(arg: T): In = TODO() +fun createInIn(arg: T): In> = TODO() +fun createJavaInv(arg: T): JavaInv> = TODO() + +// FILE: JavaCls.java + +public class JavaCls { + public static T makeFlexible(T argument) { + return argument; + } +} + +// FILE: JavaInv.java + +public class JavaInv { +} diff --git a/compiler/testData/diagnostics/tests/inference/completion/flexibleType.txt b/compiler/testData/diagnostics/tests/inference/completion/flexibleType.txt new file mode 100644 index 00000000000..e71cf655402 --- /dev/null +++ b/compiler/testData/diagnostics/tests/inference/completion/flexibleType.txt @@ -0,0 +1,60 @@ +package + +public fun createIn(/*0*/ arg: T): In +public fun createInIn(/*0*/ arg: T): In> +public fun createInv(/*0*/ arg: T): Inv +public fun createJavaInv(/*0*/ arg: T): JavaInv> +public fun createOut(/*0*/ arg: T): Out +public fun id(/*0*/ arg: K): K +public fun test(/*0*/ arg: Derived): kotlin.Unit + +public interface Base { + 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 final class Derived : Base { + public constructor Derived() + 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 final class In { + public constructor In() + 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 final class Inv { + public constructor Inv() + 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 JavaCls { + public constructor JavaCls() + 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 + + // Static members + public open fun makeFlexible(/*0*/ argument: T!): T! +} + +public open class JavaInv { + public constructor JavaInv() + 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 final class Out { + public constructor Out() + 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 +} diff --git a/compiler/testData/diagnostics/tests/inference/completion/intersectionType.fir.kt b/compiler/testData/diagnostics/tests/inference/completion/intersectionType.fir.kt new file mode 100644 index 00000000000..b3d3927f06d --- /dev/null +++ b/compiler/testData/diagnostics/tests/inference/completion/intersectionType.fir.kt @@ -0,0 +1,42 @@ +// !LANGUAGE: +NewInference +// !DIAGNOSTICS: -UNUSED_PARAMETER + +fun test(a: D1, b: D2) { + id>( + makeOut( + select(a, b) + ) + ) + id>( + makeInv( + select(a, b) + ) + ) + id>( + makeIn( + select(a, b) + ) + ) + id>>( + makeInIn( + select(a, b) + ) + ) +} + +interface Base +interface B1 : Base +interface B2 : Base +interface D1 : B1, B2 +interface D2 : B1, B2 + +fun select(a: S, b: S): S = TODO() +class Inv +class Out +class In + +fun id(arg: K) = arg +fun makeInv(arg: T): Inv = TODO() +fun makeOut(arg: T): Out = TODO() +fun makeIn(arg: T): In = TODO() +fun makeInIn(arg: T): In> = TODO() diff --git a/compiler/testData/diagnostics/tests/inference/completion/intersectionType.kt b/compiler/testData/diagnostics/tests/inference/completion/intersectionType.kt new file mode 100644 index 00000000000..9c570ab1f93 --- /dev/null +++ b/compiler/testData/diagnostics/tests/inference/completion/intersectionType.kt @@ -0,0 +1,42 @@ +// !LANGUAGE: +NewInference +// !DIAGNOSTICS: -UNUSED_PARAMETER + +fun test(a: D1, b: D2) { + ")!>id>( + ")!>makeOut( + select(a, b) + ) + ) + ")!>id>( + ")!>makeInv( + select(a, b) + ) + ) + ")!>id>( + ")!>makeIn( + select(a, b) + ) + ) + >")!>id>>( + >")!>makeInIn( + select(a, b) + ) + ) +} + +interface Base +interface B1 : Base +interface B2 : Base +interface D1 : B1, B2 +interface D2 : B1, B2 + +fun select(a: S, b: S): S = TODO() +class Inv +class Out +class In + +fun id(arg: K) = arg +fun makeInv(arg: T): Inv = TODO() +fun makeOut(arg: T): Out = TODO() +fun makeIn(arg: T): In = TODO() +fun makeInIn(arg: T): In> = TODO() diff --git a/compiler/testData/diagnostics/tests/inference/completion/intersectionType.txt b/compiler/testData/diagnostics/tests/inference/completion/intersectionType.txt new file mode 100644 index 00000000000..fd566881caf --- /dev/null +++ b/compiler/testData/diagnostics/tests/inference/completion/intersectionType.txt @@ -0,0 +1,60 @@ +package + +public fun id(/*0*/ arg: K): K +public fun makeIn(/*0*/ arg: T): In +public fun makeInIn(/*0*/ arg: T): In> +public fun makeInv(/*0*/ arg: T): Inv +public fun makeOut(/*0*/ arg: T): Out +public fun select(/*0*/ a: S, /*1*/ b: S): S +public fun test(/*0*/ a: D1, /*1*/ b: D2): kotlin.Unit + +public interface B1 : Base { + 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 interface B2 : Base { + 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 interface Base { + 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 interface D1 : B1, B2 { + public open override /*2*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*2*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*2*/ /*fake_override*/ fun toString(): kotlin.String +} + +public interface D2 : B1, B2 { + public open override /*2*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*2*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*2*/ /*fake_override*/ fun toString(): kotlin.String +} + +public final class In { + public constructor In() + 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 final class Inv { + public constructor Inv() + 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 final class Out { + public constructor Out() + 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 +} diff --git a/compiler/testData/diagnostics/tests/inference/completion/kt36233.fir.kt b/compiler/testData/diagnostics/tests/inference/completion/kt36233.fir.kt new file mode 100644 index 00000000000..a0c83c074d7 --- /dev/null +++ b/compiler/testData/diagnostics/tests/inference/completion/kt36233.fir.kt @@ -0,0 +1,13 @@ +// !LANGUAGE: +NewInference +// !DIAGNOSTICS: -UNUSED_PARAMETER -USELESS_CAST + +class Inv +class Out + +fun foo(y: K?) = Inv>() +fun test(x: Inv>) {} + +fun main() { + test(foo(null)) // type mismatch + test(foo(1 as Int)) // type mismatch +} diff --git a/compiler/testData/diagnostics/tests/inference/completion/kt36233.kt b/compiler/testData/diagnostics/tests/inference/completion/kt36233.kt new file mode 100644 index 00000000000..a0c83c074d7 --- /dev/null +++ b/compiler/testData/diagnostics/tests/inference/completion/kt36233.kt @@ -0,0 +1,13 @@ +// !LANGUAGE: +NewInference +// !DIAGNOSTICS: -UNUSED_PARAMETER -USELESS_CAST + +class Inv +class Out + +fun foo(y: K?) = Inv>() +fun test(x: Inv>) {} + +fun main() { + test(foo(null)) // type mismatch + test(foo(1 as Int)) // type mismatch +} diff --git a/compiler/testData/diagnostics/tests/inference/completion/kt36233.txt b/compiler/testData/diagnostics/tests/inference/completion/kt36233.txt new file mode 100644 index 00000000000..b403cd3e992 --- /dev/null +++ b/compiler/testData/diagnostics/tests/inference/completion/kt36233.txt @@ -0,0 +1,19 @@ +package + +public fun foo(/*0*/ y: K?): Inv> +public fun main(): kotlin.Unit +public fun test(/*0*/ x: Inv>): kotlin.Unit + +public final class Inv { + public constructor Inv() + 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 final class Out { + public constructor Out() + 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 +} diff --git a/compiler/testData/diagnostics/tests/inference/completion/nestedVariance.fir.kt b/compiler/testData/diagnostics/tests/inference/completion/nestedVariance.fir.kt new file mode 100644 index 00000000000..903f7319022 --- /dev/null +++ b/compiler/testData/diagnostics/tests/inference/completion/nestedVariance.fir.kt @@ -0,0 +1,78 @@ +// !LANGUAGE: +NewInference +// !DIAGNOSTICS: -UNUSED_PARAMETER + +interface Base +class Derived : Base +class OtherDerived : Base + +class Inv +class Out +class In + +class BiParam + +fun id(arg: K) = arg + +fun createDoubleIn(arg: D): In> = TODO() +fun createDoubleInOut1(arg: D): In>> = TODO() +fun createDoubleInOut2(arg: D): In>> = TODO() +fun createDoubleInOut3(arg: D): Out>> = TODO() + +fun createInOut(arg: D): In> = TODO() +fun createOutIn(arg: D): Out> = TODO() +fun createInvOut(arg: D): Inv> = TODO() +fun createOutInvDoubleIn(arg: D): Out>>> = TODO() + +fun biparamEarly(first: F, second: S): BiParam>, Out> = TODO() +fun biparamEarlyIrrelevantInv(first: F, second: S): BiParam>, Inv> = TODO() +fun biparamEarlyStarProjection(first: F, second: S): BiParam<*, In>> = TODO() + +fun biparamLateIn(first: F, second: S): BiParam>, S> = TODO() +fun biparamLateInv(first: F, second: S): BiParam>, S> = TODO() + +fun take(biParam: BiParam<*, In>>) {} + +fun testEarlyCompletion(derived: Derived, otherDerived: OtherDerived) { + id>>( + createDoubleIn(derived) + ) + id>>>( + createDoubleInOut1(derived) + ) + id>>>( + createDoubleInOut2(derived) + ) + id>>>( + createDoubleInOut3(derived) + ) + id>, Out>>( + biparamEarly(derived, otherDerived) + ) + id>, Inv>>( + biparamEarlyIrrelevantInv(derived, otherDerived) + ) + take( + biparamEarlyStarProjection(derived, otherDerived) + ) +} + +fun testLateCompletion(derived: Derived, otherDerived: OtherDerived) { + id>>( + createInOut(derived) + ) + id>>( + createOutIn(derived) + ) + id>>( + createInvOut(derived) + ) + id>>>>( + createOutInvDoubleIn(derived) + ) + id>, OtherDerived>>( + biparamLateIn(derived, otherDerived) + ) + id>, OtherDerived>>( + biparamLateInv(derived, otherDerived) + ) +} diff --git a/compiler/testData/diagnostics/tests/inference/completion/nestedVariance.kt b/compiler/testData/diagnostics/tests/inference/completion/nestedVariance.kt new file mode 100644 index 00000000000..3a65e39af07 --- /dev/null +++ b/compiler/testData/diagnostics/tests/inference/completion/nestedVariance.kt @@ -0,0 +1,78 @@ +// !LANGUAGE: +NewInference +// !DIAGNOSTICS: -UNUSED_PARAMETER + +interface Base +class Derived : Base +class OtherDerived : Base + +class Inv +class Out +class In + +class BiParam + +fun id(arg: K) = arg + +fun createDoubleIn(arg: D): In> = TODO() +fun createDoubleInOut1(arg: D): In>> = TODO() +fun createDoubleInOut2(arg: D): In>> = TODO() +fun createDoubleInOut3(arg: D): Out>> = TODO() + +fun createInOut(arg: D): In> = TODO() +fun createOutIn(arg: D): Out> = TODO() +fun createInvOut(arg: D): Inv> = TODO() +fun createOutInvDoubleIn(arg: D): Out>>> = TODO() + +fun biparamEarly(first: F, second: S): BiParam>, Out> = TODO() +fun biparamEarlyIrrelevantInv(first: F, second: S): BiParam>, Inv> = TODO() +fun biparamEarlyStarProjection(first: F, second: S): BiParam<*, In>> = TODO() + +fun biparamLateIn(first: F, second: S): BiParam>, S> = TODO() +fun biparamLateInv(first: F, second: S): BiParam>, S> = TODO() + +fun take(biParam: BiParam<*, In>>) {} + +fun testEarlyCompletion(derived: Derived, otherDerived: OtherDerived) { + id>>( + >")!>createDoubleIn(derived) + ) + id>>>( + >>")!>createDoubleInOut1(derived) + ) + id>>>( + >>")!>createDoubleInOut2(derived) + ) + id>>>( + >>")!>createDoubleInOut3(derived) + ) + id>, Out>>( + >, Out>")!>biparamEarly(derived, otherDerived) + ) + id>, Inv>>( + >, Inv>")!>biparamEarlyIrrelevantInv(derived, otherDerived) + ) + take( + >>")!>biparamEarlyStarProjection(derived, otherDerived) + ) +} + +fun testLateCompletion(derived: Derived, otherDerived: OtherDerived) { + id>>( + >")!>createInOut(derived) + ) + id>>( + >")!>createOutIn(derived) + ) + id>>( + >")!>createInvOut(derived) + ) + id>>>>( + >>>")!>createOutInvDoubleIn(derived) + ) + id>, OtherDerived>>( + >, OtherDerived>")!>biparamLateIn(derived, otherDerived) + ) + id>, OtherDerived>>( + >, OtherDerived>")!>biparamLateInv(derived, otherDerived) + ) +} diff --git a/compiler/testData/diagnostics/tests/inference/completion/nestedVariance.txt b/compiler/testData/diagnostics/tests/inference/completion/nestedVariance.txt new file mode 100644 index 00000000000..3b915f9c179 --- /dev/null +++ b/compiler/testData/diagnostics/tests/inference/completion/nestedVariance.txt @@ -0,0 +1,67 @@ +package + +public fun biparamEarly(/*0*/ first: F, /*1*/ second: S): BiParam>, Out> +public fun biparamEarlyIrrelevantInv(/*0*/ first: F, /*1*/ second: S): BiParam>, Inv> +public fun biparamEarlyStarProjection(/*0*/ first: F, /*1*/ second: S): BiParam<*, In>> +public fun biparamLateIn(/*0*/ first: F, /*1*/ second: S): BiParam>, S> +public fun biparamLateInv(/*0*/ first: F, /*1*/ second: S): BiParam>, S> +public fun createDoubleIn(/*0*/ arg: D): In> +public fun createDoubleInOut1(/*0*/ arg: D): In>> +public fun createDoubleInOut2(/*0*/ arg: D): In>> +public fun createDoubleInOut3(/*0*/ arg: D): Out>> +public fun createInOut(/*0*/ arg: D): In> +public fun createInvOut(/*0*/ arg: D): Inv> +public fun createOutIn(/*0*/ arg: D): Out> +public fun createOutInvDoubleIn(/*0*/ arg: D): Out>>> +public fun id(/*0*/ arg: K): K +public fun take(/*0*/ biParam: BiParam<*, In>>): kotlin.Unit +public fun testEarlyCompletion(/*0*/ derived: Derived, /*1*/ otherDerived: OtherDerived): kotlin.Unit +public fun testLateCompletion(/*0*/ derived: Derived, /*1*/ otherDerived: OtherDerived): kotlin.Unit + +public interface Base { + 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 final class BiParam { + public constructor BiParam() + 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 final class Derived : Base { + public constructor Derived() + 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 final class In { + public constructor In() + 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 final class Inv { + public constructor Inv() + 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 final class OtherDerived : Base { + public constructor OtherDerived() + 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 final class Out { + public constructor Out() + 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 +} diff --git a/compiler/testData/diagnostics/tests/inference/completion/nothingFromNestedCall.fir.kt b/compiler/testData/diagnostics/tests/inference/completion/nothingFromNestedCall.fir.kt new file mode 100644 index 00000000000..e97e31bbaf8 --- /dev/null +++ b/compiler/testData/diagnostics/tests/inference/completion/nothingFromNestedCall.fir.kt @@ -0,0 +1,13 @@ +// !LANGUAGE: +NewInference +// !CHECK_TYPE +// !DIAGNOSTICS: -UNUSED_PARAMETER -UNREACHABLE_CODE + +class Inv +class Out + +fun invOut(y: K?): Inv> = TODO() +fun test(x: Inv>): R = TODO() + +fun testNothing() { + test(invOut(null)) checkType { _() } +} diff --git a/compiler/testData/diagnostics/tests/inference/completion/nothingFromNestedCall.kt b/compiler/testData/diagnostics/tests/inference/completion/nothingFromNestedCall.kt new file mode 100644 index 00000000000..407707c2e8f --- /dev/null +++ b/compiler/testData/diagnostics/tests/inference/completion/nothingFromNestedCall.kt @@ -0,0 +1,13 @@ +// !LANGUAGE: +NewInference +// !CHECK_TYPE +// !DIAGNOSTICS: -UNUSED_PARAMETER -UNREACHABLE_CODE + +class Inv +class Out + +fun invOut(y: K?): Inv> = TODO() +fun test(x: Inv>): R = TODO() + +fun testNothing() { + test(invOut(null)) checkType { _() } +} diff --git a/compiler/testData/diagnostics/tests/inference/completion/nothingFromNestedCall.txt b/compiler/testData/diagnostics/tests/inference/completion/nothingFromNestedCall.txt new file mode 100644 index 00000000000..ac6f79ea30d --- /dev/null +++ b/compiler/testData/diagnostics/tests/inference/completion/nothingFromNestedCall.txt @@ -0,0 +1,19 @@ +package + +public fun invOut(/*0*/ y: K?): Inv> +public fun test(/*0*/ x: Inv>): R +public fun testNothing(): kotlin.Unit + +public final class Inv { + public constructor Inv() + 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 final class Out { + public constructor Out() + 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 +} diff --git a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java index 66a4f9f5ad0..d36b4ae7374 100644 --- a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java @@ -10609,21 +10609,51 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTest { runTest("compiler/testData/diagnostics/tests/inference/completion/basic.kt"); } + @TestMetadata("definetlyNotNullType.kt") + public void testDefinetlyNotNullType() throws Exception { + runTest("compiler/testData/diagnostics/tests/inference/completion/definetlyNotNullType.kt"); + } + @TestMetadata("equalityConstraintUpstairs.kt") public void testEqualityConstraintUpstairs() throws Exception { runTest("compiler/testData/diagnostics/tests/inference/completion/equalityConstraintUpstairs.kt"); } + @TestMetadata("flexibleType.kt") + public void testFlexibleType() throws Exception { + runTest("compiler/testData/diagnostics/tests/inference/completion/flexibleType.kt"); + } + + @TestMetadata("intersectionType.kt") + public void testIntersectionType() throws Exception { + runTest("compiler/testData/diagnostics/tests/inference/completion/intersectionType.kt"); + } + @TestMetadata("kt33166.kt") public void testKt33166() throws Exception { runTest("compiler/testData/diagnostics/tests/inference/completion/kt33166.kt"); } + @TestMetadata("kt36233.kt") + public void testKt36233() throws Exception { + runTest("compiler/testData/diagnostics/tests/inference/completion/kt36233.kt"); + } + @TestMetadata("lambdaWithVariableAndNothing.kt") public void testLambdaWithVariableAndNothing() throws Exception { runTest("compiler/testData/diagnostics/tests/inference/completion/lambdaWithVariableAndNothing.kt"); } + @TestMetadata("nestedVariance.kt") + public void testNestedVariance() throws Exception { + runTest("compiler/testData/diagnostics/tests/inference/completion/nestedVariance.kt"); + } + + @TestMetadata("nothingFromNestedCall.kt") + public void testNothingFromNestedCall() throws Exception { + runTest("compiler/testData/diagnostics/tests/inference/completion/nothingFromNestedCall.kt"); + } + @TestMetadata("partialForIlt.kt") public void testPartialForIlt() throws Exception { runTest("compiler/testData/diagnostics/tests/inference/completion/partialForIlt.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsUsingJavacTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsUsingJavacTestGenerated.java index 22764a5d6a7..05aebd0e52e 100644 --- a/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsUsingJavacTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsUsingJavacTestGenerated.java @@ -10604,21 +10604,51 @@ public class DiagnosticsUsingJavacTestGenerated extends AbstractDiagnosticsUsing runTest("compiler/testData/diagnostics/tests/inference/completion/basic.kt"); } + @TestMetadata("definetlyNotNullType.kt") + public void testDefinetlyNotNullType() throws Exception { + runTest("compiler/testData/diagnostics/tests/inference/completion/definetlyNotNullType.kt"); + } + @TestMetadata("equalityConstraintUpstairs.kt") public void testEqualityConstraintUpstairs() throws Exception { runTest("compiler/testData/diagnostics/tests/inference/completion/equalityConstraintUpstairs.kt"); } + @TestMetadata("flexibleType.kt") + public void testFlexibleType() throws Exception { + runTest("compiler/testData/diagnostics/tests/inference/completion/flexibleType.kt"); + } + + @TestMetadata("intersectionType.kt") + public void testIntersectionType() throws Exception { + runTest("compiler/testData/diagnostics/tests/inference/completion/intersectionType.kt"); + } + @TestMetadata("kt33166.kt") public void testKt33166() throws Exception { runTest("compiler/testData/diagnostics/tests/inference/completion/kt33166.kt"); } + @TestMetadata("kt36233.kt") + public void testKt36233() throws Exception { + runTest("compiler/testData/diagnostics/tests/inference/completion/kt36233.kt"); + } + @TestMetadata("lambdaWithVariableAndNothing.kt") public void testLambdaWithVariableAndNothing() throws Exception { runTest("compiler/testData/diagnostics/tests/inference/completion/lambdaWithVariableAndNothing.kt"); } + @TestMetadata("nestedVariance.kt") + public void testNestedVariance() throws Exception { + runTest("compiler/testData/diagnostics/tests/inference/completion/nestedVariance.kt"); + } + + @TestMetadata("nothingFromNestedCall.kt") + public void testNothingFromNestedCall() throws Exception { + runTest("compiler/testData/diagnostics/tests/inference/completion/nothingFromNestedCall.kt"); + } + @TestMetadata("partialForIlt.kt") public void testPartialForIlt() throws Exception { runTest("compiler/testData/diagnostics/tests/inference/completion/partialForIlt.kt");