diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/types/ConeTypeContext.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/types/ConeTypeContext.kt index 81303465cf1..6d289b0911c 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/types/ConeTypeContext.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/types/ConeTypeContext.kt @@ -557,4 +557,11 @@ class ConeTypeCheckerContext( else ConeTypeCheckerContext(errorTypesEqualToAnything, stubTypesEqualToAnything, session) + override fun createTypeWithAlternativeForIntersectionResult( + firstCandidate: KotlinTypeMarker, + secondCandidate: KotlinTypeMarker + ): KotlinTypeMarker { + TODO("Not yet implemented") + } + } 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 620beb7814f..c6ca1b3d0ee 100644 --- a/compiler/fir/resolve/tests/org/jetbrains/kotlin/fir/FirOldFrontendDiagnosticsTestGenerated.java +++ b/compiler/fir/resolve/tests/org/jetbrains/kotlin/fir/FirOldFrontendDiagnosticsTestGenerated.java @@ -10226,6 +10226,11 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirOldFronte runTest("compiler/testData/diagnostics/tests/inference/tooEagerSmartcast.kt"); } + @TestMetadata("topLevelIntersection.kt") + public void testTopLevelIntersection() throws Exception { + runTest("compiler/testData/diagnostics/tests/inference/topLevelIntersection.kt"); + } + @TestMetadata("tryNumberLowerBoundsBeforeUpperBounds.kt") public void testTryNumberLowerBoundsBeforeUpperBounds() throws Exception { runTest("compiler/testData/diagnostics/tests/inference/tryNumberLowerBoundsBeforeUpperBounds.kt"); @@ -11022,6 +11027,84 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirOldFronte } } + @TestMetadata("compiler/testData/diagnostics/tests/inference/publicApproximation") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class PublicApproximation extends AbstractFirOldFrontendDiagnosticsTest { + private void runTest(String testDataFilePath) throws Exception { + KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); + } + + public void testAllFilesPresentInPublicApproximation() throws Exception { + KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/diagnostics/tests/inference/publicApproximation"), Pattern.compile("^(.+)\\.kt$"), Pattern.compile("^(.+)\\.fir\\.kts?$"), true); + } + + @TestMetadata("approximatedIntersectionMorePreciseThanBound.kt") + public void testApproximatedIntersectionMorePreciseThanBound() throws Exception { + runTest("compiler/testData/diagnostics/tests/inference/publicApproximation/approximatedIntersectionMorePreciseThanBound.kt"); + } + + @TestMetadata("chainedLambdas.kt") + public void testChainedLambdas() throws Exception { + runTest("compiler/testData/diagnostics/tests/inference/publicApproximation/chainedLambdas.kt"); + } + + @TestMetadata("declarationTypes.kt") + public void testDeclarationTypes() throws Exception { + runTest("compiler/testData/diagnostics/tests/inference/publicApproximation/declarationTypes.kt"); + } + + @TestMetadata("intersectionAfterSmartCastInLambdaReturn.kt") + public void testIntersectionAfterSmartCastInLambdaReturn() throws Exception { + runTest("compiler/testData/diagnostics/tests/inference/publicApproximation/intersectionAfterSmartCastInLambdaReturn.kt"); + } + + @TestMetadata("intersectionAlternative.kt") + public void testIntersectionAlternative() throws Exception { + runTest("compiler/testData/diagnostics/tests/inference/publicApproximation/intersectionAlternative.kt"); + } + + @TestMetadata("intersectionLocations.kt") + public void testIntersectionLocations() throws Exception { + runTest("compiler/testData/diagnostics/tests/inference/publicApproximation/intersectionLocations.kt"); + } + + @TestMetadata("lambdaReturnArgumentCall.kt") + public void testLambdaReturnArgumentCall() throws Exception { + runTest("compiler/testData/diagnostics/tests/inference/publicApproximation/lambdaReturnArgumentCall.kt"); + } + + @TestMetadata("lambdaReturnTypeApproximation.kt") + public void testLambdaReturnTypeApproximation() throws Exception { + runTest("compiler/testData/diagnostics/tests/inference/publicApproximation/lambdaReturnTypeApproximation.kt"); + } + + @TestMetadata("nonTrivialVariance.kt") + public void testNonTrivialVariance() throws Exception { + runTest("compiler/testData/diagnostics/tests/inference/publicApproximation/nonTrivialVariance.kt"); + } + + @TestMetadata("parameterInBound.kt") + public void testParameterInBound() throws Exception { + runTest("compiler/testData/diagnostics/tests/inference/publicApproximation/parameterInBound.kt"); + } + + @TestMetadata("projections.kt") + public void testProjections() throws Exception { + runTest("compiler/testData/diagnostics/tests/inference/publicApproximation/projections.kt"); + } + + @TestMetadata("smartCastInLambdaReturnAfterIntersection.kt") + public void testSmartCastInLambdaReturnAfterIntersection() throws Exception { + runTest("compiler/testData/diagnostics/tests/inference/publicApproximation/smartCastInLambdaReturnAfterIntersection.kt"); + } + + @TestMetadata("twoIntersections.kt") + public void testTwoIntersections() throws Exception { + runTest("compiler/testData/diagnostics/tests/inference/publicApproximation/twoIntersections.kt"); + } + } + @TestMetadata("compiler/testData/diagnostics/tests/inference/recursiveCalls") @TestDataPath("$PROJECT_ROOT") @RunWith(JUnit3RunnerWithInners.class) diff --git a/compiler/fir/resolve/tests/org/jetbrains/kotlin/fir/FirOldFrontendDiagnosticsTestWithStdlibGenerated.java b/compiler/fir/resolve/tests/org/jetbrains/kotlin/fir/FirOldFrontendDiagnosticsTestWithStdlibGenerated.java index 928fda2a2bb..873cae3d933 100644 --- a/compiler/fir/resolve/tests/org/jetbrains/kotlin/fir/FirOldFrontendDiagnosticsTestWithStdlibGenerated.java +++ b/compiler/fir/resolve/tests/org/jetbrains/kotlin/fir/FirOldFrontendDiagnosticsTestWithStdlibGenerated.java @@ -1901,6 +1901,11 @@ public class FirOldFrontendDiagnosticsTestWithStdlibGenerated extends AbstractFi runTest("compiler/testData/diagnostics/testsWithStdLib/inference/kt35847.kt"); } + @TestMetadata("kt36249.kt") + public void testKt36249() throws Exception { + runTest("compiler/testData/diagnostics/testsWithStdLib/inference/kt36249.kt"); + } + @TestMetadata("kt4975.kt") public void testKt4975() throws Exception { runTest("compiler/testData/diagnostics/testsWithStdLib/inference/kt4975.kt"); diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/CallResolverUtil.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/CallResolverUtil.kt index 07c041eeec3..a4f47479855 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/CallResolverUtil.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/CallResolverUtil.kt @@ -113,15 +113,14 @@ fun getErasedReceiverType(receiverParameterDescriptor: ReceiverParameterDescript fakeTypeArguments.add(TypeProjectionImpl(typeProjection.projectionKind, DONT_CARE)) } - val receiverTypeConstructor = if (receiverType.constructor is IntersectionTypeConstructor) { - val superTypesWithFakeArguments = receiverType.constructor.supertypes.map { supertype -> + val oldReceiverTypeConstructor = receiverType.constructor + val receiverTypeConstructor = if (oldReceiverTypeConstructor is IntersectionTypeConstructor) { + oldReceiverTypeConstructor.transformComponents { supertype -> val fakeArguments = supertype.arguments.map { TypeProjectionImpl(it.projectionKind, DONT_CARE) } supertype.replace(fakeArguments) - } - - IntersectionTypeConstructor(superTypesWithFakeArguments) + } ?: oldReceiverTypeConstructor } else { - receiverType.constructor + oldReceiverTypeConstructor } return KotlinTypeFactory.simpleTypeWithNonTrivialMemberScope( diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/smartcasts/SmartCastManager.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/smartcasts/SmartCastManager.kt index 19a706b527c..038b04c637e 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/smartcasts/SmartCastManager.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/smartcasts/SmartCastManager.kt @@ -34,8 +34,6 @@ import org.jetbrains.kotlin.resolve.scopes.receivers.ImplicitReceiver import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.kotlin.types.TypeUtils -import org.jetbrains.kotlin.types.checker.TypeIntersector -import org.jetbrains.kotlin.types.checker.intersectTypes import org.jetbrains.kotlin.types.checker.intersectWrappedTypes import org.jetbrains.kotlin.types.typeUtil.expandIntersectionTypeIfNecessary import org.jetbrains.kotlin.utils.addIfNotNull diff --git a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/inference/components/NewTypeSubstitutor.kt b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/inference/components/NewTypeSubstitutor.kt index 8f827a053d8..4bb9ca05567 100644 --- a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/inference/components/NewTypeSubstitutor.kt +++ b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/inference/components/NewTypeSubstitutor.kt @@ -106,12 +106,16 @@ interface NewTypeSubstitutor: TypeSubstitutorMarker { } if (typeConstructor is IntersectionTypeConstructor) { - var thereIsChanges = false + fun updateNullability(substituted: UnwrappedType) = + if (type.isMarkedNullable) substituted.makeNullableAsSpecified(true) else substituted + + substituteNotNullTypeWithConstructor(typeConstructor)?.let { return updateNullability(it) } + var thereAreChanges = false val newTypes = typeConstructor.supertypes.map { - substitute(it.unwrap(), keepAnnotation, runCapturedChecks)?.apply { thereIsChanges = true } ?: it.unwrap() + substitute(it.unwrap(), keepAnnotation, runCapturedChecks)?.apply { thereAreChanges = true } ?: it.unwrap() } - if (!thereIsChanges) return null - return intersectTypes(newTypes).let { if (type.isMarkedNullable) it.makeNullableAsSpecified(true) else it } + if (!thereAreChanges) return null + return updateNullability(intersectTypes(newTypes)) } // simple classifier type diff --git a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/inference/components/ResultTypeResolver.kt b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/inference/components/ResultTypeResolver.kt index d65374540c6..94fc5aacaa8 100644 --- a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/inference/components/ResultTypeResolver.kt +++ b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/inference/components/ResultTypeResolver.kt @@ -19,8 +19,7 @@ package org.jetbrains.kotlin.resolve.calls.inference.components import org.jetbrains.kotlin.resolve.calls.NewCommonSuperTypeCalculator import org.jetbrains.kotlin.resolve.calls.inference.components.TypeVariableDirectionCalculator.ResolveDirection import org.jetbrains.kotlin.resolve.calls.inference.model.* -import org.jetbrains.kotlin.types.AbstractTypeApproximator -import org.jetbrains.kotlin.types.TypeApproximatorConfiguration +import org.jetbrains.kotlin.types.* import org.jetbrains.kotlin.types.model.* class ResultTypeResolver( @@ -65,6 +64,10 @@ class ResultTypeResolver( ): KotlinTypeMarker? { if (firstCandidate == null || secondCandidate == null) return firstCandidate ?: secondCandidate + specialResultForIntersectionType(firstCandidate, secondCandidate)?.let { intersectionWithAlternative -> + return intersectionWithAlternative + } + if (isSuitableType(firstCandidate, variableWithConstraints)) return firstCandidate return if (isSuitableType(secondCandidate, variableWithConstraints)) { @@ -74,6 +77,22 @@ class ResultTypeResolver( } } + private fun Context.specialResultForIntersectionType( + firstCandidate: KotlinTypeMarker, + secondCandidate: KotlinTypeMarker, + ): KotlinTypeMarker? { + if (firstCandidate.typeConstructor() is IntersectionTypeConstructor) { + if (!AbstractTypeChecker.isSubtypeOf(this, firstCandidate.toPublicType(), secondCandidate.toPublicType())) { + return createTypeWithAlternativeForIntersectionResult(firstCandidate, secondCandidate) + } + } + + return null + } + + private fun KotlinTypeMarker.toPublicType(): KotlinTypeMarker = + typeApproximator.approximateToSuperType(this, TypeApproximatorConfiguration.PublicDeclaration) ?: this + private fun Context.isSuitableType(resultType: KotlinTypeMarker, variableWithConstraints: VariableWithConstraints): Boolean { val filteredConstraints = variableWithConstraints.constraints.filter { isProperType(it.type) } for (constraint in filteredConstraints) { diff --git a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/inference/model/NewConstraintSystemImpl.kt b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/inference/model/NewConstraintSystemImpl.kt index 9053dc8167a..7f91901e128 100644 --- a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/inference/model/NewConstraintSystemImpl.kt +++ b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/inference/model/NewConstraintSystemImpl.kt @@ -13,9 +13,7 @@ import org.jetbrains.kotlin.resolve.calls.inference.components.ResultTypeResolve import org.jetbrains.kotlin.resolve.calls.model.KotlinCallDiagnostic import org.jetbrains.kotlin.resolve.calls.model.OnlyInputTypesDiagnostic import org.jetbrains.kotlin.resolve.calls.model.ResolvedAtom -import org.jetbrains.kotlin.types.AbstractTypeChecker -import org.jetbrains.kotlin.types.IntersectionTypeConstructor -import org.jetbrains.kotlin.types.KotlinType +import org.jetbrains.kotlin.types.* import org.jetbrains.kotlin.types.checker.NewKotlinTypeChecker import org.jetbrains.kotlin.types.model.* import org.jetbrains.kotlin.utils.SmartList diff --git a/compiler/resolution/src/org/jetbrains/kotlin/types/TypeApproximator.kt b/compiler/resolution/src/org/jetbrains/kotlin/types/TypeApproximator.kt index 44b048875a6..dc1be049f1e 100644 --- a/compiler/resolution/src/org/jetbrains/kotlin/types/TypeApproximator.kt +++ b/compiler/resolution/src/org/jetbrains/kotlin/types/TypeApproximator.kt @@ -115,7 +115,8 @@ class TypeApproximator(builtIns: KotlinBuiltIns) : AbstractTypeApproximator(Clas if (!languageVersionSettings.supportsFeature(LanguageFeature.NewInference)) return baseType.unwrap() val configuration = if (local) TypeApproximatorConfiguration.LocalDeclaration else TypeApproximatorConfiguration.PublicDeclaration - return approximateToSuperType(baseType.unwrap(), configuration) ?: baseType.unwrap() + val preparedType = if (local) baseType.unwrap() else substituteAlternativesInPublicType(baseType) + return approximateToSuperType(preparedType, configuration) ?: preparedType } // null means that this input type is the result, i.e. input type not contains not-allowed kind of types diff --git a/compiler/resolution/src/org/jetbrains/kotlin/types/alternativeTypeSubstitution.kt b/compiler/resolution/src/org/jetbrains/kotlin/types/alternativeTypeSubstitution.kt new file mode 100644 index 00000000000..71f93f7f75d --- /dev/null +++ b/compiler/resolution/src/org/jetbrains/kotlin/types/alternativeTypeSubstitution.kt @@ -0,0 +1,29 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlin.types + +import org.jetbrains.kotlin.resolve.calls.inference.components.NewTypeSubstitutor +import org.jetbrains.kotlin.types.typeUtil.contains + +fun substituteAlternativesInPublicType(type: KotlinType): UnwrappedType { + val substitutor = object : NewTypeSubstitutor { + override fun substituteNotNullTypeWithConstructor(constructor: TypeConstructor): UnwrappedType? { + if (constructor is IntersectionTypeConstructor) { + constructor.getAlternativeType()?.let { alternative -> + return safeSubstitute(alternative.unwrap()) + } + } + + return null + } + + override val isEmpty: Boolean by lazy { + !type.contains { it.constructor is IntersectionTypeConstructor } + } + } + + return substitutor.safeSubstitute(type.unwrap()) +} diff --git a/compiler/testData/diagnostics/tests/inference/publicApproximation/approximatedIntersectionMorePreciseThanBound.kt b/compiler/testData/diagnostics/tests/inference/publicApproximation/approximatedIntersectionMorePreciseThanBound.kt new file mode 100644 index 00000000000..0bec3ef6b20 --- /dev/null +++ b/compiler/testData/diagnostics/tests/inference/publicApproximation/approximatedIntersectionMorePreciseThanBound.kt @@ -0,0 +1,20 @@ +// FIR_IDENTICAL +// !DIAGNOSTICS: -UNUSED_PARAMETER +// !LANGUAGE: +NewInference + +interface Bound { + fun foo() {} +} +interface Bound1 : Bound +interface Bound2 : Bound +object First : Bound1, Bound2 +object Second : Bound1, Bound2 + +class Out(val param: O) + +fun anyBound(vararg elements: S): Out = TODO() +fun topLevel() = anyBound(First, Second) + +fun test() { + topLevel().param.foo() +} diff --git a/compiler/testData/diagnostics/tests/inference/publicApproximation/approximatedIntersectionMorePreciseThanBound.txt b/compiler/testData/diagnostics/tests/inference/publicApproximation/approximatedIntersectionMorePreciseThanBound.txt new file mode 100644 index 00000000000..6ce90f2406e --- /dev/null +++ b/compiler/testData/diagnostics/tests/inference/publicApproximation/approximatedIntersectionMorePreciseThanBound.txt @@ -0,0 +1,50 @@ +package + +public fun anyBound(/*0*/ vararg elements: S /*kotlin.Array*/): Out +public fun test(): kotlin.Unit +public fun topLevel(): Out + +public interface Bound { + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open fun foo(): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} + +public interface Bound1 : Bound { + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun foo(): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} + +public interface Bound2 : Bound { + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun foo(): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} + +public object First : Bound1, Bound2 { + private constructor First() + public open override /*2*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*2*/ /*fake_override*/ fun foo(): kotlin.Unit + public open override /*2*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*2*/ /*fake_override*/ fun toString(): kotlin.String +} + +public final class Out { + public constructor Out(/*0*/ param: O) + public final val param: O + 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 Second : Bound1, Bound2 { + private constructor Second() + public open override /*2*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*2*/ /*fake_override*/ fun foo(): kotlin.Unit + public open override /*2*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*2*/ /*fake_override*/ fun toString(): kotlin.String +} diff --git a/compiler/testData/diagnostics/tests/inference/publicApproximation/chainedLambdas.fir.kt b/compiler/testData/diagnostics/tests/inference/publicApproximation/chainedLambdas.fir.kt new file mode 100644 index 00000000000..0059860e2bb --- /dev/null +++ b/compiler/testData/diagnostics/tests/inference/publicApproximation/chainedLambdas.fir.kt @@ -0,0 +1,34 @@ +// !DIAGNOSTICS: -UNUSED_PARAMETER +// !WITH_NEW_INFERENCE +// NI_EXPECTED_FILE + +interface First { + fun first() {} +} +interface Second +interface Third +interface Fourth + +fun chained1(arg: First) = run { + if (arg !is Second) throw Exception() + arg +}.let { third -> + if (third !is Third) throw Exception() + third +} + +fun chained2(arg: First) = run { + if (arg !is Second) throw Exception() + arg +}.let { third -> + if (third !is Third) throw Exception() + third +}.let { fourth -> + if (fourth !is Fourth) throw Exception() + fourth +} + +fun test(arg: First) { + chained1(arg).first() + chained2(arg).first() +} diff --git a/compiler/testData/diagnostics/tests/inference/publicApproximation/chainedLambdas.kt b/compiler/testData/diagnostics/tests/inference/publicApproximation/chainedLambdas.kt new file mode 100644 index 00000000000..89184ee31a2 --- /dev/null +++ b/compiler/testData/diagnostics/tests/inference/publicApproximation/chainedLambdas.kt @@ -0,0 +1,34 @@ +// !DIAGNOSTICS: -UNUSED_PARAMETER +// !WITH_NEW_INFERENCE +// NI_EXPECTED_FILE + +interface First { + fun first() {} +} +interface Second +interface Third +interface Fourth + +fun chained1(arg: First) = run { + if (arg !is Second) throw Exception() + arg +}.let { third -> + if (third !is Third) throw Exception() + third +} + +fun chained2(arg: First) = run { + if (arg !is Second) throw Exception() + arg +}.let { third -> + if (third !is Third) throw Exception() + third +}.let { fourth -> + if (fourth !is Fourth) throw Exception() + fourth +} + +fun test(arg: First) { + chained1(arg).first() + chained2(arg).first() +} diff --git a/compiler/testData/diagnostics/tests/inference/publicApproximation/chainedLambdas.ni.txt b/compiler/testData/diagnostics/tests/inference/publicApproximation/chainedLambdas.ni.txt new file mode 100644 index 00000000000..3b61b201485 --- /dev/null +++ b/compiler/testData/diagnostics/tests/inference/publicApproximation/chainedLambdas.ni.txt @@ -0,0 +1,30 @@ +package + +public fun chained1(/*0*/ arg: First): kotlin.Any +public fun chained2(/*0*/ arg: First): kotlin.Any +public fun test(/*0*/ arg: First): kotlin.Unit + +public interface First { + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open fun first(): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} + +public interface Fourth { + 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 Second { + 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 Third { + 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/publicApproximation/chainedLambdas.txt b/compiler/testData/diagnostics/tests/inference/publicApproximation/chainedLambdas.txt new file mode 100644 index 00000000000..ad47684e487 --- /dev/null +++ b/compiler/testData/diagnostics/tests/inference/publicApproximation/chainedLambdas.txt @@ -0,0 +1,30 @@ +package + +public fun chained1(/*0*/ arg: First): First +public fun chained2(/*0*/ arg: First): First +public fun test(/*0*/ arg: First): kotlin.Unit + +public interface First { + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open fun first(): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} + +public interface Fourth { + 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 Second { + 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 Third { + 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/publicApproximation/declarationTypes.fir.kt b/compiler/testData/diagnostics/tests/inference/publicApproximation/declarationTypes.fir.kt new file mode 100644 index 00000000000..e177d28b10c --- /dev/null +++ b/compiler/testData/diagnostics/tests/inference/publicApproximation/declarationTypes.fir.kt @@ -0,0 +1,59 @@ +// !DIAGNOSTICS: -UNUSED_PARAMETER -UNUSED_VARIABLE -UNUSED_EXPRESSION +// !LANGUAGE: +NewInference + +interface Bound1 +interface Bound2 +object First : Bound1, Bound2 +object Second : Bound1, Bound2 + +fun intersect(vararg elements: S): S = TODO() + +fun topLevelFunction() = intersect(First, Second) +val Any.extensionProperty + get() = intersect(First, Second) + +fun Any.extensionFunction() = intersect(First, Second) + +class Cls { + val publicProperty = intersect(First, Second) + private val privateProperty = intersect(First, Second) + + fun publicMemberFunction() = intersect(First, Second) + private fun privateMemberFunction() = intersect(First, Second) + + fun testLocalDeclarations() { + val localVariable = intersect(First, Second) + fun localFunction() = intersect(First, Second) + localVariable + privateProperty + localFunction() + privateMemberFunction() + } +} + +object Obj { + val publicProperty = intersect(First, Second) + private val privateProperty = intersect(First, Second) + + fun publicMemberFunction() = intersect(First, Second) + private fun privateMemberFunction() = intersect(First, Second) + + fun testLocalDeclarations() { + val localVariable = intersect(First, Second) + fun localFunction() = intersect(First, Second) + localVariable + localFunction() + privateProperty + privateMemberFunction() + } +} + +fun test(cls: Cls, obj: Obj) { + topLevelFunction() + Unit.extensionProperty + Unit.extensionFunction() + cls.publicProperty + cls.publicMemberFunction() + obj.publicProperty + obj.publicMemberFunction() +} diff --git a/compiler/testData/diagnostics/tests/inference/publicApproximation/declarationTypes.kt b/compiler/testData/diagnostics/tests/inference/publicApproximation/declarationTypes.kt new file mode 100644 index 00000000000..219aa252e46 --- /dev/null +++ b/compiler/testData/diagnostics/tests/inference/publicApproximation/declarationTypes.kt @@ -0,0 +1,59 @@ +// !DIAGNOSTICS: -UNUSED_PARAMETER -UNUSED_VARIABLE -UNUSED_EXPRESSION +// !LANGUAGE: +NewInference + +interface Bound1 +interface Bound2 +object First : Bound1, Bound2 +object Second : Bound1, Bound2 + +fun intersect(vararg elements: S): S = TODO() + +fun topLevelFunction() = intersect(First, Second) +val Any.extensionProperty + get() = intersect(First, Second) + +fun Any.extensionFunction() = intersect(First, Second) + +class Cls { + val publicProperty = intersect(First, Second) + private val privateProperty = intersect(First, Second) + + fun publicMemberFunction() = intersect(First, Second) + private fun privateMemberFunction() = intersect(First, Second) + + fun testLocalDeclarations() { + val localVariable = intersect(First, Second) + fun localFunction() = intersect(First, Second) + localVariable + privateProperty + localFunction() + privateMemberFunction() + } +} + +object Obj { + val publicProperty = intersect(First, Second) + private val privateProperty = intersect(First, Second) + + fun publicMemberFunction() = intersect(First, Second) + private fun privateMemberFunction() = intersect(First, Second) + + fun testLocalDeclarations() { + val localVariable = intersect(First, Second) + fun localFunction() = intersect(First, Second) + localVariable + localFunction() + privateProperty + privateMemberFunction() + } +} + +fun test(cls: Cls, obj: Obj) { + topLevelFunction() + Unit.extensionProperty + Unit.extensionFunction() + cls.publicProperty + cls.publicMemberFunction() + obj.publicProperty + obj.publicMemberFunction() +} diff --git a/compiler/testData/diagnostics/tests/inference/publicApproximation/declarationTypes.txt b/compiler/testData/diagnostics/tests/inference/publicApproximation/declarationTypes.txt new file mode 100644 index 00000000000..6cf11cb3de4 --- /dev/null +++ b/compiler/testData/diagnostics/tests/inference/publicApproximation/declarationTypes.txt @@ -0,0 +1,57 @@ +package + +public val kotlin.Any.extensionProperty: Bound1 +public fun intersect(/*0*/ vararg elements: S /*kotlin.Array*/): S +public fun test(/*0*/ cls: Cls, /*1*/ obj: Obj): kotlin.Unit +public fun topLevelFunction(): Bound1 +public fun kotlin.Any.extensionFunction(): Bound1 + +public interface Bound1 { + 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 Bound2 { + 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 Cls { + public constructor Cls() + private final val privateProperty: Bound1 + public final val publicProperty: Bound1 + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + private final fun privateMemberFunction(): Bound1 + public final fun publicMemberFunction(): Bound1 + public final fun testLocalDeclarations(): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} + +public object First : Bound1, Bound2 { + private constructor First() + 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 object Obj { + private constructor Obj() + private final val privateProperty: Bound1 + public final val publicProperty: Bound1 + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + private final fun privateMemberFunction(): Bound1 + public final fun publicMemberFunction(): Bound1 + public final fun testLocalDeclarations(): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} + +public object Second : Bound1, Bound2 { + private constructor Second() + 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 +} diff --git a/compiler/testData/diagnostics/tests/inference/publicApproximation/intersectionAfterSmartCastInLambdaReturn.fir.kt b/compiler/testData/diagnostics/tests/inference/publicApproximation/intersectionAfterSmartCastInLambdaReturn.fir.kt new file mode 100644 index 00000000000..23cdcc38c3f --- /dev/null +++ b/compiler/testData/diagnostics/tests/inference/publicApproximation/intersectionAfterSmartCastInLambdaReturn.fir.kt @@ -0,0 +1,38 @@ +// !DIAGNOSTICS: -UNUSED_PARAMETER +// !WITH_NEW_INFERENCE +// NI_EXPECTED_FILE + +interface Base { + fun base() {} +} +interface Base2 +interface One : Base, Base2 +interface Two : Base, Base2 + +object O1 : One +object O2 : Two + +fun intersect(vararg elements: S): S = TODO() + +fun intersectAfterSmartCast(arg: Base, arg2: Base) = intersect( + run { + if (arg !is One) throw Exception() + arg + }, + run { + if (arg2 !is Two) throw Exception() + arg2 + } +) + +fun argOrFn(arg: S, fn: () -> S): S = TODO() + +fun intersectArgWithSmartCastFromLambda(arg: One, arg2: Base) = argOrFn(arg) { + if (arg2 !is Two) throw Exception() + arg2 +} + +fun test() { + intersectAfterSmartCast(O1, O2).base() + intersectArgWithSmartCastFromLambda(O1, O2).base() +} diff --git a/compiler/testData/diagnostics/tests/inference/publicApproximation/intersectionAfterSmartCastInLambdaReturn.kt b/compiler/testData/diagnostics/tests/inference/publicApproximation/intersectionAfterSmartCastInLambdaReturn.kt new file mode 100644 index 00000000000..c8c08df2c07 --- /dev/null +++ b/compiler/testData/diagnostics/tests/inference/publicApproximation/intersectionAfterSmartCastInLambdaReturn.kt @@ -0,0 +1,38 @@ +// !DIAGNOSTICS: -UNUSED_PARAMETER +// !WITH_NEW_INFERENCE +// NI_EXPECTED_FILE + +interface Base { + fun base() {} +} +interface Base2 +interface One : Base, Base2 +interface Two : Base, Base2 + +object O1 : One +object O2 : Two + +fun intersect(vararg elements: S): S = TODO() + +fun intersectAfterSmartCast(arg: Base, arg2: Base) = intersect( + run { + if (arg !is One) throw Exception() + arg + }, + run { + if (arg2 !is Two) throw Exception() + arg2 + } +) + +fun argOrFn(arg: S, fn: () -> S): S = TODO() + +fun intersectArgWithSmartCastFromLambda(arg: One, arg2: Base) = argOrFn(arg) { + if (arg2 !is Two) throw Exception() + arg2 +} + +fun test() { + intersectAfterSmartCast(O1, O2).base() + intersectArgWithSmartCastFromLambda(O1, O2).base() +} diff --git a/compiler/testData/diagnostics/tests/inference/publicApproximation/intersectionAfterSmartCastInLambdaReturn.ni.txt b/compiler/testData/diagnostics/tests/inference/publicApproximation/intersectionAfterSmartCastInLambdaReturn.ni.txt new file mode 100644 index 00000000000..a87e0df8457 --- /dev/null +++ b/compiler/testData/diagnostics/tests/inference/publicApproximation/intersectionAfterSmartCastInLambdaReturn.ni.txt @@ -0,0 +1,50 @@ +package + +public fun argOrFn(/*0*/ arg: S, /*1*/ fn: () -> S): S +public fun intersect(/*0*/ vararg elements: S /*kotlin.Array*/): S +public fun intersectAfterSmartCast(/*0*/ arg: Base, /*1*/ arg2: Base): kotlin.Any +public fun intersectArgWithSmartCastFromLambda(/*0*/ arg: One, /*1*/ arg2: Base): kotlin.Any +public fun test(): kotlin.Unit + +public interface Base { + public open fun base(): kotlin.Unit + 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 Base2 { + 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 O1 : One { + private constructor O1() + public open override /*1*/ /*fake_override*/ fun base(): kotlin.Unit + 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 O2 : Two { + private constructor O2() + public open override /*1*/ /*fake_override*/ fun base(): kotlin.Unit + 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 One : Base, Base2 { + public open override /*1*/ /*fake_override*/ fun base(): kotlin.Unit + 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 Two : Base, Base2 { + public open override /*1*/ /*fake_override*/ fun base(): kotlin.Unit + 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 +} diff --git a/compiler/testData/diagnostics/tests/inference/publicApproximation/intersectionAfterSmartCastInLambdaReturn.txt b/compiler/testData/diagnostics/tests/inference/publicApproximation/intersectionAfterSmartCastInLambdaReturn.txt new file mode 100644 index 00000000000..13c9db304f1 --- /dev/null +++ b/compiler/testData/diagnostics/tests/inference/publicApproximation/intersectionAfterSmartCastInLambdaReturn.txt @@ -0,0 +1,50 @@ +package + +public fun argOrFn(/*0*/ arg: S, /*1*/ fn: () -> S): S +public fun intersect(/*0*/ vararg elements: S /*kotlin.Array*/): S +public fun intersectAfterSmartCast(/*0*/ arg: Base, /*1*/ arg2: Base): Base +public fun intersectArgWithSmartCastFromLambda(/*0*/ arg: One, /*1*/ arg2: Base): Base +public fun test(): kotlin.Unit + +public interface Base { + public open fun base(): kotlin.Unit + 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 Base2 { + 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 O1 : One { + private constructor O1() + public open override /*1*/ /*fake_override*/ fun base(): kotlin.Unit + 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 O2 : Two { + private constructor O2() + public open override /*1*/ /*fake_override*/ fun base(): kotlin.Unit + 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 One : Base, Base2 { + public open override /*1*/ /*fake_override*/ fun base(): kotlin.Unit + 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 Two : Base, Base2 { + public open override /*1*/ /*fake_override*/ fun base(): kotlin.Unit + 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 +} diff --git a/compiler/testData/diagnostics/tests/inference/publicApproximation/intersectionAlternative.fir.kt b/compiler/testData/diagnostics/tests/inference/publicApproximation/intersectionAlternative.fir.kt new file mode 100644 index 00000000000..f138ece7b9b --- /dev/null +++ b/compiler/testData/diagnostics/tests/inference/publicApproximation/intersectionAlternative.fir.kt @@ -0,0 +1,17 @@ +// !LANGUAGE: +NewInference +// !DIAGNOSTICS: -UNUSED_PARAMETER + +interface Bound +interface Bound1 : Bound +interface Bound2 : Bound +interface Bound3 +object First : Bound1, Bound2, Bound3 +object Second : Bound1, Bound2, Bound3 + +fun intersect(vararg elements: S): S where S : Bound1, S : Bound2 = TODO() + +fun testIntersectionAlternative() = intersect(First, Second) + +fun test() { + testIntersectionAlternative() +} diff --git a/compiler/testData/diagnostics/tests/inference/publicApproximation/intersectionAlternative.kt b/compiler/testData/diagnostics/tests/inference/publicApproximation/intersectionAlternative.kt new file mode 100644 index 00000000000..3ff937e8d2f --- /dev/null +++ b/compiler/testData/diagnostics/tests/inference/publicApproximation/intersectionAlternative.kt @@ -0,0 +1,17 @@ +// !LANGUAGE: +NewInference +// !DIAGNOSTICS: -UNUSED_PARAMETER + +interface Bound +interface Bound1 : Bound +interface Bound2 : Bound +interface Bound3 +object First : Bound1, Bound2, Bound3 +object Second : Bound1, Bound2, Bound3 + +fun intersect(vararg elements: S): S where S : Bound1, S : Bound2 = TODO() + +fun testIntersectionAlternative() = intersect(First, Second) + +fun test() { + testIntersectionAlternative() +} diff --git a/compiler/testData/diagnostics/tests/inference/publicApproximation/intersectionAlternative.txt b/compiler/testData/diagnostics/tests/inference/publicApproximation/intersectionAlternative.txt new file mode 100644 index 00000000000..7cbc7b49dbe --- /dev/null +++ b/compiler/testData/diagnostics/tests/inference/publicApproximation/intersectionAlternative.txt @@ -0,0 +1,43 @@ +package + +public fun intersect(/*0*/ vararg elements: S /*kotlin.Array*/): S where S : Bound2 +public fun test(): kotlin.Unit +public fun testIntersectionAlternative(): Bound + +public interface Bound { + 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 Bound1 : Bound { + 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 Bound2 : Bound { + 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 Bound3 { + 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 First : Bound1, Bound2, Bound3 { + private constructor First() + public open override /*3*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*3*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*3*/ /*fake_override*/ fun toString(): kotlin.String +} + +public object Second : Bound1, Bound2, Bound3 { + private constructor Second() + public open override /*3*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*3*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*3*/ /*fake_override*/ fun toString(): kotlin.String +} diff --git a/compiler/testData/diagnostics/tests/inference/publicApproximation/intersectionLocations.fir.kt b/compiler/testData/diagnostics/tests/inference/publicApproximation/intersectionLocations.fir.kt new file mode 100644 index 00000000000..743999aa99e --- /dev/null +++ b/compiler/testData/diagnostics/tests/inference/publicApproximation/intersectionLocations.fir.kt @@ -0,0 +1,44 @@ +// !LANGUAGE: +NewInference +// !DIAGNOSTICS: -UNUSED_PARAMETER + +fun test() { + testInv() + testIn() + testOut() + testStarProjection() + testErrorType() + testInProjection() + testOutProjection() + testDeeplyNested() +} + +interface Bound1 +interface Bound2 +object First : Bound1, Bound2 +object Second : Bound1, Bound2 + +class Inv(val prop: T) +class Out(val prop: O) +class In(arg: I) +class BiParam(first: F, second: S) + +fun intersect(vararg elements: S): S = TODO() + +fun makeStarProjection(): Inv<*> = TODO() +fun makeInProjection(arg: I): Inv = TODO() +fun makeOutProjection(arg: O): Inv = TODO() +fun testInv() = Inv(intersect(First, Second)) +fun testOut() = Out(intersect(First, Second)) +fun testIn() = In(intersect(First, Second)) +fun testInProjection() = makeInProjection(intersect(First, Second)) +fun testOutProjection() = makeOutProjection(intersect(First, Second)) +fun testDeeplyNested() = Inv(Inv(Inv(intersect(First, Second)))) + +fun testStarProjection() = BiParam( + intersect(First, Second), + makeStarProjection() +) +fun testErrorType() = BiParam( + intersect(First, Second), + unresolved +) diff --git a/compiler/testData/diagnostics/tests/inference/publicApproximation/intersectionLocations.kt b/compiler/testData/diagnostics/tests/inference/publicApproximation/intersectionLocations.kt new file mode 100644 index 00000000000..62356758c2c --- /dev/null +++ b/compiler/testData/diagnostics/tests/inference/publicApproximation/intersectionLocations.kt @@ -0,0 +1,44 @@ +// !LANGUAGE: +NewInference +// !DIAGNOSTICS: -UNUSED_PARAMETER + +fun test() { + ")!>testInv() + ")!>testIn() + ")!>testOut() + >")!>testStarProjection() + testErrorType() + ")!>testInProjection() + ")!>testOutProjection() + >>")!>testDeeplyNested() +} + +interface Bound1 +interface Bound2 +object First : Bound1, Bound2 +object Second : Bound1, Bound2 + +class Inv(val prop: T) +class Out(val prop: O) +class In(arg: I) +class BiParam(first: F, second: S) + +fun intersect(vararg elements: S): S = TODO() + +fun makeStarProjection(): Inv<*> = TODO() +fun makeInProjection(arg: I): Inv = TODO() +fun makeOutProjection(arg: O): Inv = TODO() +fun testInv() = Inv(intersect(First, Second)) +fun testOut() = Out(intersect(First, Second)) +fun testIn() = In(intersect(First, Second)) +fun testInProjection() = makeInProjection(intersect(First, Second)) +fun testOutProjection() = makeOutProjection(intersect(First, Second)) +fun testDeeplyNested() = Inv(Inv(Inv(intersect(First, Second)))) + +fun testStarProjection() = BiParam( + intersect(First, Second), + makeStarProjection() +) +fun testErrorType() = BiParam( + intersect(First, Second), + unresolved +) diff --git a/compiler/testData/diagnostics/tests/inference/publicApproximation/intersectionLocations.txt b/compiler/testData/diagnostics/tests/inference/publicApproximation/intersectionLocations.txt new file mode 100644 index 00000000000..b69976ad150 --- /dev/null +++ b/compiler/testData/diagnostics/tests/inference/publicApproximation/intersectionLocations.txt @@ -0,0 +1,71 @@ +package + +public fun intersect(/*0*/ vararg elements: S /*kotlin.Array*/): S +public fun makeInProjection(/*0*/ arg: I): Inv +public fun makeOutProjection(/*0*/ arg: O): Inv +public fun makeStarProjection(): Inv<*> +public fun test(): kotlin.Unit +public fun testDeeplyNested(): Inv>> +public fun testErrorType(): [ERROR : Error function type] +public fun testIn(): In +public fun testInProjection(): Inv +public fun testInv(): Inv +public fun testOut(): Out +public fun testOutProjection(): Inv +public fun testStarProjection(): BiParam> + +public final class BiParam { + public constructor BiParam(/*0*/ first: F, /*1*/ second: S) + 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 Bound1 { + 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 Bound2 { + 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 First : Bound1, Bound2 { + private constructor First() + 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(/*0*/ arg: I) + 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(/*0*/ prop: T) + public final val prop: T + 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(/*0*/ prop: O) + public final val prop: O + 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 Second : Bound1, Bound2 { + private constructor Second() + 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 +} diff --git a/compiler/testData/diagnostics/tests/inference/publicApproximation/lambdaReturnArgumentCall.fir.kt b/compiler/testData/diagnostics/tests/inference/publicApproximation/lambdaReturnArgumentCall.fir.kt new file mode 100644 index 00000000000..7a64a766eea --- /dev/null +++ b/compiler/testData/diagnostics/tests/inference/publicApproximation/lambdaReturnArgumentCall.fir.kt @@ -0,0 +1,19 @@ +// !DIAGNOSTICS: -UNUSED_PARAMETER + +interface First +interface Second + +interface A : First, Second +interface B : First, Second + +fun intersect(vararg elements: S): S = TODO() + +fun runIntersect(arg: A, arg2: A) = run { + if (arg !is B) throw Exception() + if (arg2 !is B) throw Exception() + intersect(arg, arg2) +} + +fun test(arg: A) { + runIntersect(arg, arg) +} diff --git a/compiler/testData/diagnostics/tests/inference/publicApproximation/lambdaReturnArgumentCall.kt b/compiler/testData/diagnostics/tests/inference/publicApproximation/lambdaReturnArgumentCall.kt new file mode 100644 index 00000000000..efa5baf94d9 --- /dev/null +++ b/compiler/testData/diagnostics/tests/inference/publicApproximation/lambdaReturnArgumentCall.kt @@ -0,0 +1,19 @@ +// !DIAGNOSTICS: -UNUSED_PARAMETER + +interface First +interface Second + +interface A : First, Second +interface B : First, Second + +fun intersect(vararg elements: S): S = TODO() + +fun runIntersect(arg: A, arg2: A) = run { + if (arg !is B) throw Exception() + if (arg2 !is B) throw Exception() + intersect(arg, arg2) +} + +fun test(arg: A) { + runIntersect(arg, arg) +} diff --git a/compiler/testData/diagnostics/tests/inference/publicApproximation/lambdaReturnArgumentCall.txt b/compiler/testData/diagnostics/tests/inference/publicApproximation/lambdaReturnArgumentCall.txt new file mode 100644 index 00000000000..7bf2cf948d5 --- /dev/null +++ b/compiler/testData/diagnostics/tests/inference/publicApproximation/lambdaReturnArgumentCall.txt @@ -0,0 +1,29 @@ +package + +public fun intersect(/*0*/ vararg elements: S /*kotlin.Array*/): S +public fun runIntersect(/*0*/ arg: A, /*1*/ arg2: A): kotlin.Any +public fun test(/*0*/ arg: A): kotlin.Unit + +public interface A : First, Second { + 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 B : First, Second { + 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 First { + 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 Second { + 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/publicApproximation/lambdaReturnTypeApproximation.fir.kt b/compiler/testData/diagnostics/tests/inference/publicApproximation/lambdaReturnTypeApproximation.fir.kt new file mode 100644 index 00000000000..880560d6886 --- /dev/null +++ b/compiler/testData/diagnostics/tests/inference/publicApproximation/lambdaReturnTypeApproximation.fir.kt @@ -0,0 +1,20 @@ +// !LANGUAGE: +NewInference +// !DIAGNOSTICS: -UNUSED_PARAMETER + +interface Bound1 +interface Bound2 +object First : Bound1, Bound2 +object Second : Bound1, Bound2 + +fun intersect(vararg elements: S): S = TODO() + +fun run(fn: () -> R): R = TODO() + +fun topLevel() = run { + val local = intersect(First, Second) + local +} + +fun test() { + topLevel() +} diff --git a/compiler/testData/diagnostics/tests/inference/publicApproximation/lambdaReturnTypeApproximation.kt b/compiler/testData/diagnostics/tests/inference/publicApproximation/lambdaReturnTypeApproximation.kt new file mode 100644 index 00000000000..5f0119c0aca --- /dev/null +++ b/compiler/testData/diagnostics/tests/inference/publicApproximation/lambdaReturnTypeApproximation.kt @@ -0,0 +1,20 @@ +// !LANGUAGE: +NewInference +// !DIAGNOSTICS: -UNUSED_PARAMETER + +interface Bound1 +interface Bound2 +object First : Bound1, Bound2 +object Second : Bound1, Bound2 + +fun intersect(vararg elements: S): S = TODO() + +fun run(fn: () -> R): R = TODO() + +fun topLevel() = run { + val local = intersect(First, Second) + local +} + +fun test() { + topLevel() +} diff --git a/compiler/testData/diagnostics/tests/inference/publicApproximation/lambdaReturnTypeApproximation.txt b/compiler/testData/diagnostics/tests/inference/publicApproximation/lambdaReturnTypeApproximation.txt new file mode 100644 index 00000000000..1173652b426 --- /dev/null +++ b/compiler/testData/diagnostics/tests/inference/publicApproximation/lambdaReturnTypeApproximation.txt @@ -0,0 +1,32 @@ +package + +public fun intersect(/*0*/ vararg elements: S /*kotlin.Array*/): S +public fun run(/*0*/ fn: () -> R): R +public fun test(): kotlin.Unit +public fun topLevel(): Bound1 + +public interface Bound1 { + 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 Bound2 { + 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 First : Bound1, Bound2 { + private constructor First() + 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 object Second : Bound1, Bound2 { + private constructor Second() + 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 +} diff --git a/compiler/testData/diagnostics/tests/inference/publicApproximation/nonTrivialVariance.fir.kt b/compiler/testData/diagnostics/tests/inference/publicApproximation/nonTrivialVariance.fir.kt new file mode 100644 index 00000000000..eda387ce8bc --- /dev/null +++ b/compiler/testData/diagnostics/tests/inference/publicApproximation/nonTrivialVariance.fir.kt @@ -0,0 +1,54 @@ +// !DIAGNOSTICS: -UNUSED_PARAMETER + +fun test(first: First, second: Second) { + test1(first, second) + test2(first, second) + test3(first, second) + test4(first, second) + test5(first, second) + test6(first, second) + test7(first, second) + test8(first, second) + test9(first, second) + + test10(first, second) + test11(first, second) + test12(first, second) + test13(first, second) + test14(first, second) + test15(first, second) + test16(first, second) + test17(first, second) + test18(first, second) +} + +interface Bound1 +interface Bound2 +object First : Bound1, Bound2 +object Second : Bound1, Bound2 + +fun intersect(vararg elements: S): S = TODO() + +class Inv(val prop: T) +class In(arg: I) +class Out(val arg: O) + +fun test1(first: First, second: Second) = Inv(Inv(intersect(first, second))) +fun test2(first: First, second: Second) = Inv(In(intersect(first, second))) +fun test3(first: First, second: Second) = Inv(Out(intersect(first, second))) +fun test4(first: First, second: Second) = In(Inv(intersect(first, second))) +fun test5(first: First, second: Second) = In(In(intersect(first, second))) +fun test6(first: First, second: Second) = In(Out(intersect(first, second))) +fun test7(first: First, second: Second) = Out(Inv(intersect(first, second))) +fun test8(first: First, second: Second) = Out(In(intersect(first, second))) +fun test9(first: First, second: Second) = Out(Out(intersect(first, second))) + +fun test10(first: First, second: Second) = Out(Out(Out(intersect(first, second)))) +fun test11(first: First, second: Second) = Inv(Out(Out(intersect(first, second)))) +fun test12(first: First, second: Second) = Inv(Out(In(intersect(first, second)))) +fun test13(first: First, second: Second) = Inv(In(Out(intersect(first, second)))) +fun test14(first: First, second: Second) = Inv(In(In(intersect(first, second)))) +fun test15(first: First, second: Second) = Out(Inv(Out(intersect(first, second)))) +fun test16(first: First, second: Second) = Out(Out(In(intersect(first, second)))) +fun test17(first: First, second: Second) = Out(In(Out(intersect(first, second)))) +fun test18(first: First, second: Second) = In(Out(Out(intersect(first, second)))) diff --git a/compiler/testData/diagnostics/tests/inference/publicApproximation/nonTrivialVariance.kt b/compiler/testData/diagnostics/tests/inference/publicApproximation/nonTrivialVariance.kt new file mode 100644 index 00000000000..3b3428e74d7 --- /dev/null +++ b/compiler/testData/diagnostics/tests/inference/publicApproximation/nonTrivialVariance.kt @@ -0,0 +1,54 @@ +// !DIAGNOSTICS: -UNUSED_PARAMETER + +fun test(first: First, second: Second) { + >")!>test1(first, second) + >")!>test2(first, second) + >")!>test3(first, second) + >")!>test4(first, second) + >")!>test5(first, second) + >")!>test6(first, second) + >")!>test7(first, second) + >")!>test8(first, second) + >")!>test9(first, second) + + >>")!>test10(first, second) + >>")!>test11(first, second) + >>")!>test12(first, second) + >>")!>test13(first, second) + >>")!>test14(first, second) + >>")!>test15(first, second) + >>")!>test16(first, second) + >>")!>test17(first, second) + >>")!>test18(first, second) +} + +interface Bound1 +interface Bound2 +object First : Bound1, Bound2 +object Second : Bound1, Bound2 + +fun intersect(vararg elements: S): S = TODO() + +class Inv(val prop: T) +class In(arg: I) +class Out(val arg: O) + +fun test1(first: First, second: Second) = Inv(Inv(intersect(first, second))) +fun test2(first: First, second: Second) = Inv(In(intersect(first, second))) +fun test3(first: First, second: Second) = Inv(Out(intersect(first, second))) +fun test4(first: First, second: Second) = In(Inv(intersect(first, second))) +fun test5(first: First, second: Second) = In(In(intersect(first, second))) +fun test6(first: First, second: Second) = In(Out(intersect(first, second))) +fun test7(first: First, second: Second) = Out(Inv(intersect(first, second))) +fun test8(first: First, second: Second) = Out(In(intersect(first, second))) +fun test9(first: First, second: Second) = Out(Out(intersect(first, second))) + +fun test10(first: First, second: Second) = Out(Out(Out(intersect(first, second)))) +fun test11(first: First, second: Second) = Inv(Out(Out(intersect(first, second)))) +fun test12(first: First, second: Second) = Inv(Out(In(intersect(first, second)))) +fun test13(first: First, second: Second) = Inv(In(Out(intersect(first, second)))) +fun test14(first: First, second: Second) = Inv(In(In(intersect(first, second)))) +fun test15(first: First, second: Second) = Out(Inv(Out(intersect(first, second)))) +fun test16(first: First, second: Second) = Out(Out(In(intersect(first, second)))) +fun test17(first: First, second: Second) = Out(In(Out(intersect(first, second)))) +fun test18(first: First, second: Second) = In(Out(Out(intersect(first, second)))) diff --git a/compiler/testData/diagnostics/tests/inference/publicApproximation/nonTrivialVariance.txt b/compiler/testData/diagnostics/tests/inference/publicApproximation/nonTrivialVariance.txt new file mode 100644 index 00000000000..1db0a5b1490 --- /dev/null +++ b/compiler/testData/diagnostics/tests/inference/publicApproximation/nonTrivialVariance.txt @@ -0,0 +1,71 @@ +package + +public fun intersect(/*0*/ vararg elements: S /*kotlin.Array*/): S +public fun test(/*0*/ first: First, /*1*/ second: Second): kotlin.Unit +public fun test1(/*0*/ first: First, /*1*/ second: Second): Inv> +public fun test10(/*0*/ first: First, /*1*/ second: Second): Out>> +public fun test11(/*0*/ first: First, /*1*/ second: Second): Inv>> +public fun test12(/*0*/ first: First, /*1*/ second: Second): Inv>> +public fun test13(/*0*/ first: First, /*1*/ second: Second): Inv>> +public fun test14(/*0*/ first: First, /*1*/ second: Second): Inv>> +public fun test15(/*0*/ first: First, /*1*/ second: Second): Out>> +public fun test16(/*0*/ first: First, /*1*/ second: Second): Out>> +public fun test17(/*0*/ first: First, /*1*/ second: Second): Out>> +public fun test18(/*0*/ first: First, /*1*/ second: Second): In>> +public fun test2(/*0*/ first: First, /*1*/ second: Second): Inv> +public fun test3(/*0*/ first: First, /*1*/ second: Second): Inv> +public fun test4(/*0*/ first: First, /*1*/ second: Second): In> +public fun test5(/*0*/ first: First, /*1*/ second: Second): In> +public fun test6(/*0*/ first: First, /*1*/ second: Second): In> +public fun test7(/*0*/ first: First, /*1*/ second: Second): Out> +public fun test8(/*0*/ first: First, /*1*/ second: Second): Out> +public fun test9(/*0*/ first: First, /*1*/ second: Second): Out> + +public interface Bound1 { + 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 Bound2 { + 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 First : Bound1, Bound2 { + private constructor First() + 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(/*0*/ arg: I) + 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(/*0*/ prop: T) + public final val prop: T + 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(/*0*/ arg: O) + public final val arg: O + 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 Second : Bound1, Bound2 { + private constructor Second() + 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 +} diff --git a/compiler/testData/diagnostics/tests/inference/publicApproximation/parameterInBound.fir.kt b/compiler/testData/diagnostics/tests/inference/publicApproximation/parameterInBound.fir.kt new file mode 100644 index 00000000000..b07f41e784e --- /dev/null +++ b/compiler/testData/diagnostics/tests/inference/publicApproximation/parameterInBound.fir.kt @@ -0,0 +1,25 @@ +// !LANGUAGE: +NewInference +// !DIAGNOSTICS: -UNUSED_PARAMETER + +interface Bound1 +interface Bound2 +object First : Bound1, Bound2 +object Second : Bound1, Bound2 + +interface WithParam1 +interface WithParam2 +class ClsWithParam1 : WithParam1, WithParam2 +class ClsWithParam2 : WithParam1, WithParam2 + +fun intersect(vararg elements: S): S = TODO() +fun > combineParams(first: T, vararg args: P): P = TODO() + +fun topLevel() = combineParams( + intersect(First, Second), + ClsWithParam1(), + ClsWithParam2() +) + +fun test() { + topLevel() +} diff --git a/compiler/testData/diagnostics/tests/inference/publicApproximation/parameterInBound.kt b/compiler/testData/diagnostics/tests/inference/publicApproximation/parameterInBound.kt new file mode 100644 index 00000000000..8f18cb6376f --- /dev/null +++ b/compiler/testData/diagnostics/tests/inference/publicApproximation/parameterInBound.kt @@ -0,0 +1,25 @@ +// !LANGUAGE: +NewInference +// !DIAGNOSTICS: -UNUSED_PARAMETER + +interface Bound1 +interface Bound2 +object First : Bound1, Bound2 +object Second : Bound1, Bound2 + +interface WithParam1 +interface WithParam2 +class ClsWithParam1 : WithParam1, WithParam2 +class ClsWithParam2 : WithParam1, WithParam2 + +fun intersect(vararg elements: S): S = TODO() +fun > combineParams(first: T, vararg args: P): P = TODO() + +fun topLevel() = & WithParam2<{Bound1 & Bound2}>}")!>combineParams( + intersect(First, Second), + ClsWithParam1(), + ClsWithParam2() +) + +fun test() { + ")!>topLevel() +} diff --git a/compiler/testData/diagnostics/tests/inference/publicApproximation/parameterInBound.txt b/compiler/testData/diagnostics/tests/inference/publicApproximation/parameterInBound.txt new file mode 100644 index 00000000000..5db6b3159f7 --- /dev/null +++ b/compiler/testData/diagnostics/tests/inference/publicApproximation/parameterInBound.txt @@ -0,0 +1,58 @@ +package + +public fun > combineParams(/*0*/ first: T, /*1*/ vararg args: P /*kotlin.Array*/): P +public fun intersect(/*0*/ vararg elements: S /*kotlin.Array*/): S +public fun test(): kotlin.Unit +public fun topLevel(): WithParam1 + +public interface Bound1 { + 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 Bound2 { + 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 ClsWithParam1 : WithParam1, WithParam2 { + public constructor ClsWithParam1() + 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 ClsWithParam2 : WithParam1, WithParam2 { + public constructor ClsWithParam2() + 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 object First : Bound1, Bound2 { + private constructor First() + 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 object Second : Bound1, Bound2 { + private constructor Second() + 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 WithParam1 { + 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 WithParam2 { + 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/publicApproximation/projections.fir.kt b/compiler/testData/diagnostics/tests/inference/publicApproximation/projections.fir.kt new file mode 100644 index 00000000000..22aaed4058a --- /dev/null +++ b/compiler/testData/diagnostics/tests/inference/publicApproximation/projections.fir.kt @@ -0,0 +1,19 @@ +// !DIAGNOSTICS: -UNUSED_PARAMETER + +interface Bound1 +interface Bound2 +object First : Bound1, Bound2 +object Second : Bound1, Bound2 + +class Inv + +fun makeOut(vararg args: O): Inv = TODO() +fun makeIn(vararg args: I): Inv = TODO() + +fun testOut() = makeOut(First, Second) +fun testIn() = makeIn(First, Second) + +fun test() { + testOut() + testIn() +} diff --git a/compiler/testData/diagnostics/tests/inference/publicApproximation/projections.kt b/compiler/testData/diagnostics/tests/inference/publicApproximation/projections.kt new file mode 100644 index 00000000000..8f1856bd7c9 --- /dev/null +++ b/compiler/testData/diagnostics/tests/inference/publicApproximation/projections.kt @@ -0,0 +1,19 @@ +// !DIAGNOSTICS: -UNUSED_PARAMETER + +interface Bound1 +interface Bound2 +object First : Bound1, Bound2 +object Second : Bound1, Bound2 + +class Inv + +fun makeOut(vararg args: O): Inv = TODO() +fun makeIn(vararg args: I): Inv = TODO() + +fun testOut() = makeOut(First, Second) +fun testIn() = makeIn(First, Second) + +fun test() { + ")!>testOut() + ")!>testIn() +} diff --git a/compiler/testData/diagnostics/tests/inference/publicApproximation/projections.txt b/compiler/testData/diagnostics/tests/inference/publicApproximation/projections.txt new file mode 100644 index 00000000000..9c1c30d9887 --- /dev/null +++ b/compiler/testData/diagnostics/tests/inference/publicApproximation/projections.txt @@ -0,0 +1,40 @@ +package + +public fun makeIn(/*0*/ vararg args: I /*kotlin.Array*/): Inv +public fun makeOut(/*0*/ vararg args: O /*kotlin.Array*/): Inv +public fun test(): kotlin.Unit +public fun testIn(): Inv +public fun testOut(): Inv + +public interface Bound1 { + 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 Bound2 { + 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 First : Bound1, Bound2 { + private constructor First() + 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 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 object Second : Bound1, Bound2 { + private constructor Second() + 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 +} diff --git a/compiler/testData/diagnostics/tests/inference/publicApproximation/smartCastInLambdaReturnAfterIntersection.fir.kt b/compiler/testData/diagnostics/tests/inference/publicApproximation/smartCastInLambdaReturnAfterIntersection.fir.kt new file mode 100644 index 00000000000..e03f91c740c --- /dev/null +++ b/compiler/testData/diagnostics/tests/inference/publicApproximation/smartCastInLambdaReturnAfterIntersection.fir.kt @@ -0,0 +1,22 @@ +// !DIAGNOSTICS: -UNUSED_PARAMETER +// !WITH_NEW_INFERENCE +// NI_EXPECTED_FILE + +interface Base { + fun base() {} +} +interface Base2 +interface One : Base, Base2 +interface Two : Base, Base2 + +fun intersectNullable(vararg elements: S): S? = TODO() + +fun smartCastAfterIntersection(a: One, b: Two) = run { + val v = intersectNullable(a, b) + if (v == null) throw Exception() + v +} + +fun test(one: One, two: Two) { + smartCastAfterIntersection(one, two)?.base() +} diff --git a/compiler/testData/diagnostics/tests/inference/publicApproximation/smartCastInLambdaReturnAfterIntersection.kt b/compiler/testData/diagnostics/tests/inference/publicApproximation/smartCastInLambdaReturnAfterIntersection.kt new file mode 100644 index 00000000000..42665f9e35b --- /dev/null +++ b/compiler/testData/diagnostics/tests/inference/publicApproximation/smartCastInLambdaReturnAfterIntersection.kt @@ -0,0 +1,22 @@ +// !DIAGNOSTICS: -UNUSED_PARAMETER +// !WITH_NEW_INFERENCE +// NI_EXPECTED_FILE + +interface Base { + fun base() {} +} +interface Base2 +interface One : Base, Base2 +interface Two : Base, Base2 + +fun intersectNullable(vararg elements: S): S? = TODO() + +fun smartCastAfterIntersection(a: One, b: Two) = run { + val v = intersectNullable(a, b) + if (v == null) throw Exception() + v +} + +fun test(one: One, two: Two) { + smartCastAfterIntersection(one, two)?.base() +} diff --git a/compiler/testData/diagnostics/tests/inference/publicApproximation/smartCastInLambdaReturnAfterIntersection.ni.txt b/compiler/testData/diagnostics/tests/inference/publicApproximation/smartCastInLambdaReturnAfterIntersection.ni.txt new file mode 100644 index 00000000000..0b55f6a01bf --- /dev/null +++ b/compiler/testData/diagnostics/tests/inference/publicApproximation/smartCastInLambdaReturnAfterIntersection.ni.txt @@ -0,0 +1,32 @@ +package + +public fun intersectNullable(/*0*/ vararg elements: S /*kotlin.Array*/): S? +public fun smartCastAfterIntersection(/*0*/ a: One, /*1*/ b: Two): kotlin.Any +public fun test(/*0*/ one: One, /*1*/ two: Two): kotlin.Unit + +public interface Base { + public open fun base(): kotlin.Unit + 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 Base2 { + 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 One : Base, Base2 { + public open override /*1*/ /*fake_override*/ fun base(): kotlin.Unit + 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 Two : Base, Base2 { + public open override /*1*/ /*fake_override*/ fun base(): kotlin.Unit + 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 +} diff --git a/compiler/testData/diagnostics/tests/inference/publicApproximation/smartCastInLambdaReturnAfterIntersection.txt b/compiler/testData/diagnostics/tests/inference/publicApproximation/smartCastInLambdaReturnAfterIntersection.txt new file mode 100644 index 00000000000..727f67e6077 --- /dev/null +++ b/compiler/testData/diagnostics/tests/inference/publicApproximation/smartCastInLambdaReturnAfterIntersection.txt @@ -0,0 +1,32 @@ +package + +public fun intersectNullable(/*0*/ vararg elements: S /*kotlin.Array*/): S? +public fun smartCastAfterIntersection(/*0*/ a: One, /*1*/ b: Two): Base? +public fun test(/*0*/ one: One, /*1*/ two: Two): kotlin.Unit + +public interface Base { + public open fun base(): kotlin.Unit + 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 Base2 { + 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 One : Base, Base2 { + public open override /*1*/ /*fake_override*/ fun base(): kotlin.Unit + 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 Two : Base, Base2 { + public open override /*1*/ /*fake_override*/ fun base(): kotlin.Unit + 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 +} diff --git a/compiler/testData/diagnostics/tests/inference/publicApproximation/twoIntersections.fir.kt b/compiler/testData/diagnostics/tests/inference/publicApproximation/twoIntersections.fir.kt new file mode 100644 index 00000000000..61df54f8734 --- /dev/null +++ b/compiler/testData/diagnostics/tests/inference/publicApproximation/twoIntersections.fir.kt @@ -0,0 +1,25 @@ +// !DIAGNOSTICS: -UNUSED_PARAMETER +// !WITH_NEW_INFERENCE +// NI_EXPECTED_FILE + +interface Base { + fun base() {} +} +interface Base2 : Base3 +interface Base3 +interface One : Base, Base2 +interface Two : Base, Base2 +interface Three : Base, Base3 + +object O1 : One +object O2 : Two +object O3 : Three + +fun intersect(vararg elements: S): S = TODO() +fun intersectNoBound(vararg elements: S): S = TODO() + +fun some(a: One, b: Two, c: Three) = intersectNoBound(intersect(a, b), c) + +fun test(arg: Base, arg2: Base) { + some(O1, O2, O3).base() +} diff --git a/compiler/testData/diagnostics/tests/inference/publicApproximation/twoIntersections.kt b/compiler/testData/diagnostics/tests/inference/publicApproximation/twoIntersections.kt new file mode 100644 index 00000000000..c9260062a90 --- /dev/null +++ b/compiler/testData/diagnostics/tests/inference/publicApproximation/twoIntersections.kt @@ -0,0 +1,25 @@ +// !DIAGNOSTICS: -UNUSED_PARAMETER +// !WITH_NEW_INFERENCE +// NI_EXPECTED_FILE + +interface Base { + fun base() {} +} +interface Base2 : Base3 +interface Base3 +interface One : Base, Base2 +interface Two : Base, Base2 +interface Three : Base, Base3 + +object O1 : One +object O2 : Two +object O3 : Three + +fun intersect(vararg elements: S): S = TODO() +fun intersectNoBound(vararg elements: S): S = TODO() + +fun some(a: One, b: Two, c: Three) = intersectNoBound(intersect(a, b), c) + +fun test(arg: Base, arg2: Base) { + some(O1, O2, O3).base() +} diff --git a/compiler/testData/diagnostics/tests/inference/publicApproximation/twoIntersections.ni.txt b/compiler/testData/diagnostics/tests/inference/publicApproximation/twoIntersections.ni.txt new file mode 100644 index 00000000000..59a76520fa7 --- /dev/null +++ b/compiler/testData/diagnostics/tests/inference/publicApproximation/twoIntersections.ni.txt @@ -0,0 +1,70 @@ +package + +public fun intersect(/*0*/ vararg elements: S /*kotlin.Array*/): S +public fun intersectNoBound(/*0*/ vararg elements: S /*kotlin.Array*/): S +public fun some(/*0*/ a: One, /*1*/ b: Two, /*2*/ c: Three): kotlin.Any +public fun test(/*0*/ arg: Base, /*1*/ arg2: Base): kotlin.Unit + +public interface Base { + public open fun base(): kotlin.Unit + 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 Base2 : Base3 { + 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 Base3 { + 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 O1 : One { + private constructor O1() + public open override /*1*/ /*fake_override*/ fun base(): kotlin.Unit + 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 O2 : Two { + private constructor O2() + public open override /*1*/ /*fake_override*/ fun base(): kotlin.Unit + 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 O3 : Three { + private constructor O3() + public open override /*1*/ /*fake_override*/ fun base(): kotlin.Unit + 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 One : Base, Base2 { + public open override /*1*/ /*fake_override*/ fun base(): kotlin.Unit + 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 Three : Base, Base3 { + public open override /*1*/ /*fake_override*/ fun base(): kotlin.Unit + 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 Two : Base, Base2 { + public open override /*1*/ /*fake_override*/ fun base(): kotlin.Unit + 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 +} diff --git a/compiler/testData/diagnostics/tests/inference/publicApproximation/twoIntersections.txt b/compiler/testData/diagnostics/tests/inference/publicApproximation/twoIntersections.txt new file mode 100644 index 00000000000..6e6e7af89e9 --- /dev/null +++ b/compiler/testData/diagnostics/tests/inference/publicApproximation/twoIntersections.txt @@ -0,0 +1,70 @@ +package + +public fun intersect(/*0*/ vararg elements: S /*kotlin.Array*/): S +public fun intersectNoBound(/*0*/ vararg elements: S /*kotlin.Array*/): S +public fun some(/*0*/ a: One, /*1*/ b: Two, /*2*/ c: Three): Base +public fun test(/*0*/ arg: Base, /*1*/ arg2: Base): kotlin.Unit + +public interface Base { + public open fun base(): kotlin.Unit + 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 Base2 : Base3 { + 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 Base3 { + 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 O1 : One { + private constructor O1() + public open override /*1*/ /*fake_override*/ fun base(): kotlin.Unit + 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 O2 : Two { + private constructor O2() + public open override /*1*/ /*fake_override*/ fun base(): kotlin.Unit + 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 O3 : Three { + private constructor O3() + public open override /*1*/ /*fake_override*/ fun base(): kotlin.Unit + 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 One : Base, Base2 { + public open override /*1*/ /*fake_override*/ fun base(): kotlin.Unit + 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 Three : Base, Base3 { + public open override /*1*/ /*fake_override*/ fun base(): kotlin.Unit + 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 Two : Base, Base2 { + public open override /*1*/ /*fake_override*/ fun base(): kotlin.Unit + 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 +} diff --git a/compiler/testData/diagnostics/tests/inference/topLevelIntersection.fir.kt b/compiler/testData/diagnostics/tests/inference/topLevelIntersection.fir.kt new file mode 100644 index 00000000000..15fae639ee4 --- /dev/null +++ b/compiler/testData/diagnostics/tests/inference/topLevelIntersection.fir.kt @@ -0,0 +1,17 @@ +// !DIAGNOSTICS: -UNUSED_PARAMETER -UNUSED_VARIABLE -UNUSED_EXPRESSION + +interface Bound1 +interface Bound2 +object First : Bound1, Bound2 +object Second : Bound1, Bound2 + +fun select(vararg args: S): S = TODO() + +class Cls { + val property = select(First, Second) +} + +fun test() { + val v = Cls().property + v +} diff --git a/compiler/testData/diagnostics/tests/inference/topLevelIntersection.kt b/compiler/testData/diagnostics/tests/inference/topLevelIntersection.kt new file mode 100644 index 00000000000..20df5822ae4 --- /dev/null +++ b/compiler/testData/diagnostics/tests/inference/topLevelIntersection.kt @@ -0,0 +1,17 @@ +// !DIAGNOSTICS: -UNUSED_PARAMETER -UNUSED_VARIABLE -UNUSED_EXPRESSION + +interface Bound1 +interface Bound2 +object First : Bound1, Bound2 +object Second : Bound1, Bound2 + +fun select(vararg args: S): S = TODO() + +class Cls { + val property = select(First, Second) +} + +fun test() { + val v = Cls().property + v +} diff --git a/compiler/testData/diagnostics/tests/inference/topLevelIntersection.txt b/compiler/testData/diagnostics/tests/inference/topLevelIntersection.txt new file mode 100644 index 00000000000..60e99d2858c --- /dev/null +++ b/compiler/testData/diagnostics/tests/inference/topLevelIntersection.txt @@ -0,0 +1,38 @@ +package + +public fun select(/*0*/ vararg args: S /*kotlin.Array*/): S +public fun test(): kotlin.Unit + +public interface Bound1 { + 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 Bound2 { + 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 Cls { + public constructor Cls() + public final val property: Bound1 + 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 First : Bound1, Bound2 { + private constructor First() + 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 object Second : Bound1, Bound2 { + private constructor Second() + 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 +} diff --git a/compiler/testData/diagnostics/tests/typealias/typeAliasConstructorTypeArgumentsInferenceWithNestedCalls.ni.txt b/compiler/testData/diagnostics/tests/typealias/typeAliasConstructorTypeArgumentsInferenceWithNestedCalls.ni.txt index c09d0cb8f26..2b3f9d79b85 100644 --- a/compiler/testData/diagnostics/tests/typealias/typeAliasConstructorTypeArgumentsInferenceWithNestedCalls.ni.txt +++ b/compiler/testData/diagnostics/tests/typealias/typeAliasConstructorTypeArgumentsInferenceWithNestedCalls.ni.txt @@ -1,7 +1,7 @@ package public val test1: C /* = Cons */ -public val test2: Cons +public val test2: C /* = Cons */ public final class Cons { public constructor Cons(/*0*/ head: T, /*1*/ tail: Cons?) diff --git a/compiler/testData/diagnostics/testsWithStdLib/inference/kt36249.fir.kt b/compiler/testData/diagnostics/testsWithStdLib/inference/kt36249.fir.kt new file mode 100644 index 00000000000..933682a0710 --- /dev/null +++ b/compiler/testData/diagnostics/testsWithStdLib/inference/kt36249.fir.kt @@ -0,0 +1,18 @@ +// !DIAGNOSTICS: -UNUSED_PARAMETER UNUSED_VARIABLE -UNUSED_EXPRESSION + +import kotlin.reflect.KClass +fun select(vararg classes: KClass): T? { + return null +} +interface PomRenameableTarget +interface PsiElement +interface PsiMethod : PsiElement, PomRenameableTarget +interface PsiClass : PsiElement, PomRenameableTarget + +class A { + val inv get() = select(PsiMethod::class, PsiClass::class) +} + +fun main() { + A().inv +} diff --git a/compiler/testData/diagnostics/testsWithStdLib/inference/kt36249.kt b/compiler/testData/diagnostics/testsWithStdLib/inference/kt36249.kt new file mode 100644 index 00000000000..67227acfb08 --- /dev/null +++ b/compiler/testData/diagnostics/testsWithStdLib/inference/kt36249.kt @@ -0,0 +1,18 @@ +// !DIAGNOSTICS: -UNUSED_PARAMETER UNUSED_VARIABLE -UNUSED_EXPRESSION + +import kotlin.reflect.KClass +fun select(vararg classes: KClass): T? { + return null +} +interface PomRenameableTarget +interface PsiElement +interface PsiMethod : PsiElement, PomRenameableTarget +interface PsiClass : PsiElement, PomRenameableTarget + +class A { + val inv get() = select(PsiMethod::class, PsiClass::class) +} + +fun main() { + A().inv +} diff --git a/compiler/testData/diagnostics/testsWithStdLib/inference/kt36249.txt b/compiler/testData/diagnostics/testsWithStdLib/inference/kt36249.txt new file mode 100644 index 00000000000..d474325c4b4 --- /dev/null +++ b/compiler/testData/diagnostics/testsWithStdLib/inference/kt36249.txt @@ -0,0 +1,36 @@ +package + +public fun main(): kotlin.Unit +public fun select(/*0*/ vararg classes: kotlin.reflect.KClass /*kotlin.Array>*/): T? + +public final class A { + public constructor A() + public final val inv: PsiElement? + 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 PomRenameableTarget { + 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 PsiClass : PsiElement, PomRenameableTarget { + 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 PsiElement { + 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 PsiMethod : PsiElement, PomRenameableTarget { + 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 +} diff --git a/compiler/testData/ir/irText/expressions/implicitCastToTypeParameter.txt b/compiler/testData/ir/irText/expressions/implicitCastToTypeParameter.txt index 0ffed6ae349..fff76479eb2 100644 --- a/compiler/testData/ir/irText/expressions/implicitCastToTypeParameter.txt +++ b/compiler/testData/ir/irText/expressions/implicitCastToTypeParameter.txt @@ -36,15 +36,15 @@ FILE fqName: fileName:/implicitCastToTypeParameter.kt $receiver: VALUE_PARAMETER name: type:.Foo.> BLOCK_BODY RETURN type=kotlin.Nothing from='public final fun (): T of .? [inline] declared in ' - TYPE_OP type=T of .? origin=IMPLICIT_CAST typeOperand=T of .? - WHEN type=kotlin.Any? origin=IF - BRANCH - if: TYPE_OP type=kotlin.Boolean origin=INSTANCEOF typeOperand=T of . - GET_VAR ': .Foo.> declared in .' type=.Foo.> origin=null - then: GET_VAR ': .Foo.> declared in .' type=.Foo.> origin=null - BRANCH - if: CONST Boolean type=kotlin.Boolean value=true - then: CONST Null type=kotlin.Nothing? value=null + WHEN type=T of .? origin=IF + BRANCH + if: TYPE_OP type=kotlin.Boolean origin=INSTANCEOF typeOperand=T of . + GET_VAR ': .Foo.> declared in .' type=.Foo.> origin=null + then: TYPE_OP type=T of . origin=IMPLICIT_CAST typeOperand=T of . + GET_VAR ': .Foo.> declared in .' type=.Foo.> origin=null + BRANCH + if: CONST Boolean type=kotlin.Boolean value=true + then: CONST Null type=kotlin.Nothing? value=null CLASS CLASS name:Bar modality:FINAL visibility:public superTypes:[kotlin.Any] $this: VALUE_PARAMETER INSTANCE_RECEIVER name: type:.Bar.Bar> TYPE_PARAMETER name:T index:0 variance: superTypes:[kotlin.Any?] diff --git a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java index b7b924b69e6..9aa24574e2c 100644 --- a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java @@ -10233,6 +10233,11 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTestWithFirVali runTest("compiler/testData/diagnostics/tests/inference/tooEagerSmartcast.kt"); } + @TestMetadata("topLevelIntersection.kt") + public void testTopLevelIntersection() throws Exception { + runTest("compiler/testData/diagnostics/tests/inference/topLevelIntersection.kt"); + } + @TestMetadata("tryNumberLowerBoundsBeforeUpperBounds.kt") public void testTryNumberLowerBoundsBeforeUpperBounds() throws Exception { runTest("compiler/testData/diagnostics/tests/inference/tryNumberLowerBoundsBeforeUpperBounds.kt"); @@ -11029,6 +11034,84 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTestWithFirVali } } + @TestMetadata("compiler/testData/diagnostics/tests/inference/publicApproximation") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class PublicApproximation extends AbstractDiagnosticsTestWithFirValidation { + private void runTest(String testDataFilePath) throws Exception { + KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); + } + + public void testAllFilesPresentInPublicApproximation() throws Exception { + KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/diagnostics/tests/inference/publicApproximation"), Pattern.compile("^(.*)\\.kts?$"), Pattern.compile("^(.+)\\.fir\\.kts?$"), true); + } + + @TestMetadata("approximatedIntersectionMorePreciseThanBound.kt") + public void testApproximatedIntersectionMorePreciseThanBound() throws Exception { + runTest("compiler/testData/diagnostics/tests/inference/publicApproximation/approximatedIntersectionMorePreciseThanBound.kt"); + } + + @TestMetadata("chainedLambdas.kt") + public void testChainedLambdas() throws Exception { + runTest("compiler/testData/diagnostics/tests/inference/publicApproximation/chainedLambdas.kt"); + } + + @TestMetadata("declarationTypes.kt") + public void testDeclarationTypes() throws Exception { + runTest("compiler/testData/diagnostics/tests/inference/publicApproximation/declarationTypes.kt"); + } + + @TestMetadata("intersectionAfterSmartCastInLambdaReturn.kt") + public void testIntersectionAfterSmartCastInLambdaReturn() throws Exception { + runTest("compiler/testData/diagnostics/tests/inference/publicApproximation/intersectionAfterSmartCastInLambdaReturn.kt"); + } + + @TestMetadata("intersectionAlternative.kt") + public void testIntersectionAlternative() throws Exception { + runTest("compiler/testData/diagnostics/tests/inference/publicApproximation/intersectionAlternative.kt"); + } + + @TestMetadata("intersectionLocations.kt") + public void testIntersectionLocations() throws Exception { + runTest("compiler/testData/diagnostics/tests/inference/publicApproximation/intersectionLocations.kt"); + } + + @TestMetadata("lambdaReturnArgumentCall.kt") + public void testLambdaReturnArgumentCall() throws Exception { + runTest("compiler/testData/diagnostics/tests/inference/publicApproximation/lambdaReturnArgumentCall.kt"); + } + + @TestMetadata("lambdaReturnTypeApproximation.kt") + public void testLambdaReturnTypeApproximation() throws Exception { + runTest("compiler/testData/diagnostics/tests/inference/publicApproximation/lambdaReturnTypeApproximation.kt"); + } + + @TestMetadata("nonTrivialVariance.kt") + public void testNonTrivialVariance() throws Exception { + runTest("compiler/testData/diagnostics/tests/inference/publicApproximation/nonTrivialVariance.kt"); + } + + @TestMetadata("parameterInBound.kt") + public void testParameterInBound() throws Exception { + runTest("compiler/testData/diagnostics/tests/inference/publicApproximation/parameterInBound.kt"); + } + + @TestMetadata("projections.kt") + public void testProjections() throws Exception { + runTest("compiler/testData/diagnostics/tests/inference/publicApproximation/projections.kt"); + } + + @TestMetadata("smartCastInLambdaReturnAfterIntersection.kt") + public void testSmartCastInLambdaReturnAfterIntersection() throws Exception { + runTest("compiler/testData/diagnostics/tests/inference/publicApproximation/smartCastInLambdaReturnAfterIntersection.kt"); + } + + @TestMetadata("twoIntersections.kt") + public void testTwoIntersections() throws Exception { + runTest("compiler/testData/diagnostics/tests/inference/publicApproximation/twoIntersections.kt"); + } + } + @TestMetadata("compiler/testData/diagnostics/tests/inference/recursiveCalls") @TestDataPath("$PROJECT_ROOT") @RunWith(JUnit3RunnerWithInners.class) diff --git a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestWithStdLibGenerated.java b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestWithStdLibGenerated.java index 95427eef8ae..10ffbe731cd 100644 --- a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestWithStdLibGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestWithStdLibGenerated.java @@ -2881,6 +2881,11 @@ public class DiagnosticsTestWithStdLibGenerated extends AbstractDiagnosticsTestW runTest("compiler/testData/diagnostics/testsWithStdLib/inference/kt35847.kt"); } + @TestMetadata("kt36249.kt") + public void testKt36249() throws Exception { + runTest("compiler/testData/diagnostics/testsWithStdLib/inference/kt36249.kt"); + } + @TestMetadata("kt4975.kt") public void testKt4975() throws Exception { runTest("compiler/testData/diagnostics/testsWithStdLib/inference/kt4975.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsTestWithStdLibUsingJavacGenerated.java b/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsTestWithStdLibUsingJavacGenerated.java index 38735cc15fe..eda919f8a67 100644 --- a/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsTestWithStdLibUsingJavacGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsTestWithStdLibUsingJavacGenerated.java @@ -2881,6 +2881,11 @@ public class DiagnosticsTestWithStdLibUsingJavacGenerated extends AbstractDiagno runTest("compiler/testData/diagnostics/testsWithStdLib/inference/kt35847.kt"); } + @TestMetadata("kt36249.kt") + public void testKt36249() throws Exception { + runTest("compiler/testData/diagnostics/testsWithStdLib/inference/kt36249.kt"); + } + @TestMetadata("kt4975.kt") public void testKt4975() throws Exception { runTest("compiler/testData/diagnostics/testsWithStdLib/inference/kt4975.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsUsingJavacTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsUsingJavacTestGenerated.java index 59132defe83..30f30d15932 100644 --- a/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsUsingJavacTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsUsingJavacTestGenerated.java @@ -10228,6 +10228,11 @@ public class DiagnosticsUsingJavacTestGenerated extends AbstractDiagnosticsUsing runTest("compiler/testData/diagnostics/tests/inference/tooEagerSmartcast.kt"); } + @TestMetadata("topLevelIntersection.kt") + public void testTopLevelIntersection() throws Exception { + runTest("compiler/testData/diagnostics/tests/inference/topLevelIntersection.kt"); + } + @TestMetadata("tryNumberLowerBoundsBeforeUpperBounds.kt") public void testTryNumberLowerBoundsBeforeUpperBounds() throws Exception { runTest("compiler/testData/diagnostics/tests/inference/tryNumberLowerBoundsBeforeUpperBounds.kt"); @@ -11024,6 +11029,84 @@ public class DiagnosticsUsingJavacTestGenerated extends AbstractDiagnosticsUsing } } + @TestMetadata("compiler/testData/diagnostics/tests/inference/publicApproximation") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class PublicApproximation extends AbstractDiagnosticsUsingJavacTest { + private void runTest(String testDataFilePath) throws Exception { + KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); + } + + public void testAllFilesPresentInPublicApproximation() throws Exception { + KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/diagnostics/tests/inference/publicApproximation"), Pattern.compile("^(.+)\\.kt$"), Pattern.compile("^(.+)\\.fir\\.kts?$"), true); + } + + @TestMetadata("approximatedIntersectionMorePreciseThanBound.kt") + public void testApproximatedIntersectionMorePreciseThanBound() throws Exception { + runTest("compiler/testData/diagnostics/tests/inference/publicApproximation/approximatedIntersectionMorePreciseThanBound.kt"); + } + + @TestMetadata("chainedLambdas.kt") + public void testChainedLambdas() throws Exception { + runTest("compiler/testData/diagnostics/tests/inference/publicApproximation/chainedLambdas.kt"); + } + + @TestMetadata("declarationTypes.kt") + public void testDeclarationTypes() throws Exception { + runTest("compiler/testData/diagnostics/tests/inference/publicApproximation/declarationTypes.kt"); + } + + @TestMetadata("intersectionAfterSmartCastInLambdaReturn.kt") + public void testIntersectionAfterSmartCastInLambdaReturn() throws Exception { + runTest("compiler/testData/diagnostics/tests/inference/publicApproximation/intersectionAfterSmartCastInLambdaReturn.kt"); + } + + @TestMetadata("intersectionAlternative.kt") + public void testIntersectionAlternative() throws Exception { + runTest("compiler/testData/diagnostics/tests/inference/publicApproximation/intersectionAlternative.kt"); + } + + @TestMetadata("intersectionLocations.kt") + public void testIntersectionLocations() throws Exception { + runTest("compiler/testData/diagnostics/tests/inference/publicApproximation/intersectionLocations.kt"); + } + + @TestMetadata("lambdaReturnArgumentCall.kt") + public void testLambdaReturnArgumentCall() throws Exception { + runTest("compiler/testData/diagnostics/tests/inference/publicApproximation/lambdaReturnArgumentCall.kt"); + } + + @TestMetadata("lambdaReturnTypeApproximation.kt") + public void testLambdaReturnTypeApproximation() throws Exception { + runTest("compiler/testData/diagnostics/tests/inference/publicApproximation/lambdaReturnTypeApproximation.kt"); + } + + @TestMetadata("nonTrivialVariance.kt") + public void testNonTrivialVariance() throws Exception { + runTest("compiler/testData/diagnostics/tests/inference/publicApproximation/nonTrivialVariance.kt"); + } + + @TestMetadata("parameterInBound.kt") + public void testParameterInBound() throws Exception { + runTest("compiler/testData/diagnostics/tests/inference/publicApproximation/parameterInBound.kt"); + } + + @TestMetadata("projections.kt") + public void testProjections() throws Exception { + runTest("compiler/testData/diagnostics/tests/inference/publicApproximation/projections.kt"); + } + + @TestMetadata("smartCastInLambdaReturnAfterIntersection.kt") + public void testSmartCastInLambdaReturnAfterIntersection() throws Exception { + runTest("compiler/testData/diagnostics/tests/inference/publicApproximation/smartCastInLambdaReturnAfterIntersection.kt"); + } + + @TestMetadata("twoIntersections.kt") + public void testTwoIntersections() throws Exception { + runTest("compiler/testData/diagnostics/tests/inference/publicApproximation/twoIntersections.kt"); + } + } + @TestMetadata("compiler/testData/diagnostics/tests/inference/recursiveCalls") @TestDataPath("$PROJECT_ROOT") @RunWith(JUnit3RunnerWithInners.class) diff --git a/core/descriptors/src/org/jetbrains/kotlin/types/IntersectionTypeConstructor.kt b/core/descriptors/src/org/jetbrains/kotlin/types/IntersectionTypeConstructor.kt index a5871b9b762..a80a40ab20b 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/types/IntersectionTypeConstructor.kt +++ b/core/descriptors/src/org/jetbrains/kotlin/types/IntersectionTypeConstructor.kt @@ -27,6 +27,15 @@ import org.jetbrains.kotlin.types.refinement.TypeRefinement import java.util.* class IntersectionTypeConstructor(typesToIntersect: Collection) : TypeConstructor { + private var alternative: KotlinType? = null + + private constructor( + typesToIntersect: Collection, + alternative: KotlinType?, + ) : this(typesToIntersect) { + this.alternative = alternative + } + init { assert(!typesToIntersect.isEmpty()) { "Attempt to create an empty intersection" } } @@ -75,7 +84,13 @@ class IntersectionTypeConstructor(typesToIntersect: Collection) : Ty @TypeRefinement override fun refine(kotlinTypeRefiner: KotlinTypeRefiner) = - IntersectionTypeConstructor(intersectedTypes.map { it.refine(kotlinTypeRefiner) }) + transformComponents { it.refine(kotlinTypeRefiner) } ?: this + + fun setAlternative(alternative: KotlinType?): IntersectionTypeConstructor { + return IntersectionTypeConstructor(intersectedTypes, alternative) + } + + fun getAlternativeType(): KotlinType? = alternative } inline fun IntersectionTypeConstructor.transformComponents( @@ -94,5 +109,9 @@ inline fun IntersectionTypeConstructor.transformComponents( if (!changed) return null - return IntersectionTypeConstructor(newSupertypes) + val updatedAlternative = getAlternativeType()?.let { alternative -> + if (predicate(alternative)) transform(alternative) else alternative + } + + return IntersectionTypeConstructor(newSupertypes).setAlternative(updatedAlternative) } diff --git a/core/descriptors/src/org/jetbrains/kotlin/types/checker/ClassicTypeSystemContext.kt b/core/descriptors/src/org/jetbrains/kotlin/types/checker/ClassicTypeSystemContext.kt index 6a8140ed99d..406396a66cf 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/types/checker/ClassicTypeSystemContext.kt +++ b/core/descriptors/src/org/jetbrains/kotlin/types/checker/ClassicTypeSystemContext.kt @@ -27,6 +27,7 @@ import org.jetbrains.kotlin.types.model.* import org.jetbrains.kotlin.types.typeUtil.asTypeProjection import org.jetbrains.kotlin.types.typeUtil.contains import org.jetbrains.kotlin.types.typeUtil.representativeUpperBound +import org.jetbrains.kotlin.utils.addToStdlib.safeAs import kotlin.contracts.ExperimentalContracts import kotlin.contracts.contract @@ -606,6 +607,21 @@ interface ClassicTypeSystemContext : TypeSystemInferenceExtensionContext, TypeSy val descriptor = constructor.declarationDescriptor return descriptor is ClassDescriptor && (descriptor.kind == ClassKind.INTERFACE || descriptor.kind == ClassKind.ANNOTATION_CLASS) } + + override fun createTypeWithAlternativeForIntersectionResult( + firstCandidate: KotlinTypeMarker, + secondCandidate: KotlinTypeMarker, + ): KotlinTypeMarker { + require(firstCandidate is KotlinType, this::errorMessage) + require(secondCandidate is KotlinType, this::errorMessage) + + firstCandidate.constructor.safeAs()?.let { intersectionConstructor -> + val intersectionTypeWithAlternative = intersectionConstructor.setAlternative(secondCandidate).createType() + return if (firstCandidate.isMarkedNullable) intersectionTypeWithAlternative.makeNullableAsSpecified(true) + else intersectionTypeWithAlternative + + } ?: error("Expected intersection type, found $firstCandidate") + } } fun TypeVariance.convertVariance(): Variance { diff --git a/core/type-system/src/org/jetbrains/kotlin/types/model/TypeSystemContext.kt b/core/type-system/src/org/jetbrains/kotlin/types/model/TypeSystemContext.kt index 831cf847684..c39abedd766 100644 --- a/core/type-system/src/org/jetbrains/kotlin/types/model/TypeSystemContext.kt +++ b/core/type-system/src/org/jetbrains/kotlin/types/model/TypeSystemContext.kt @@ -164,6 +164,11 @@ interface TypeSystemInferenceExtensionContext : TypeSystemContext, TypeSystemBui fun TypeVariableMarker.defaultType(): SimpleTypeMarker + + fun createTypeWithAlternativeForIntersectionResult( + firstCandidate: KotlinTypeMarker, + secondCandidate: KotlinTypeMarker + ): KotlinTypeMarker }