diff --git a/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/codegen/ir/FirBlackBoxCodegenTestGenerated.java b/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/codegen/ir/FirBlackBoxCodegenTestGenerated.java index 7a091b5d944..ad1a4baf135 100644 --- a/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/codegen/ir/FirBlackBoxCodegenTestGenerated.java +++ b/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/codegen/ir/FirBlackBoxCodegenTestGenerated.java @@ -13459,6 +13459,11 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT runTest("compiler/testData/codegen/box/inference/referenceToCatchParameterFromLambdaExpression.kt"); } + @TestMetadata("specialCallsWithCallableReferences.kt") + public void testSpecialCallsWithCallableReferences() throws Exception { + runTest("compiler/testData/codegen/box/inference/specialCallsWithCallableReferences.kt"); + } + @TestMetadata("subtypingOfIntersectionIltInsideFlexible.kt") public void testSubtypingOfIntersectionIltInsideFlexible() throws Exception { runTest("compiler/testData/codegen/box/inference/subtypingOfIntersectionIltInsideFlexible.kt"); diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/DiagnosticReporterByTrackingStrategy.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/DiagnosticReporterByTrackingStrategy.kt index 3ff54236166..d104284d0ee 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/DiagnosticReporterByTrackingStrategy.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/DiagnosticReporterByTrackingStrategy.kt @@ -31,13 +31,21 @@ import org.jetbrains.kotlin.resolve.constants.evaluate.ConstantExpressionEvaluat import org.jetbrains.kotlin.resolve.descriptorUtil.module import org.jetbrains.kotlin.resolve.scopes.receivers.ExpressionReceiver import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedCallableMemberDescriptor +import org.jetbrains.kotlin.types.ErrorUtils import org.jetbrains.kotlin.types.KotlinType +import org.jetbrains.kotlin.types.TypeUtils import org.jetbrains.kotlin.types.checker.intersectWrappedTypes import org.jetbrains.kotlin.types.expressions.ControlStructureTypingUtils +import org.jetbrains.kotlin.types.model.TypeSystemInferenceExtensionContextDelegate +import org.jetbrains.kotlin.types.model.TypeVariableMarker +import org.jetbrains.kotlin.types.model.freshTypeConstructor +import org.jetbrains.kotlin.types.typeUtil.contains import org.jetbrains.kotlin.types.typeUtil.isNullableNothing import org.jetbrains.kotlin.types.typeUtil.makeNullable import org.jetbrains.kotlin.utils.addToStdlib.cast import org.jetbrains.kotlin.utils.addToStdlib.safeAs +import kotlin.contracts.ExperimentalContracts +import kotlin.contracts.contract class DiagnosticReporterByTrackingStrategy( val constantExpressionEvaluator: ConstantExpressionEvaluator, @@ -45,7 +53,8 @@ class DiagnosticReporterByTrackingStrategy( val psiKotlinCall: PSIKotlinCall, val dataFlowValueFactory: DataFlowValueFactory, val allDiagnostics: List, - private val smartCastManager: SmartCastManager + private val smartCastManager: SmartCastManager, + private val typeSystemContext: TypeSystemInferenceExtensionContextDelegate ) : DiagnosticReporter { private val trace = context.trace as TrackingBindingTrace private val tracingStrategy: TracingStrategy get() = psiKotlinCall.tracingStrategy @@ -421,21 +430,21 @@ class DiagnosticReporterByTrackingStrategy( NotEnoughInformationForTypeParameterImpl::class.java -> { error as NotEnoughInformationForTypeParameterImpl - if (allDiagnostics.any { - when (it) { - is WrongCountOfTypeArguments -> true - is KotlinConstraintSystemDiagnostic -> { - val otherError = it.error - (otherError is ConstrainingTypeIsError && otherError.typeVariable == error.typeVariable) - || otherError is NewConstraintError - } - else -> false - } - } - ) return - if (isSpecialFunction(error.resolvedAtom)) - return + val resolvedAtom = error.resolvedAtom + val isDiagnosticRedundant = !isSpecialFunction(resolvedAtom) && allDiagnostics.any { + when (it) { + is WrongCountOfTypeArguments -> true + is KotlinConstraintSystemDiagnostic -> { + val otherError = it.error + (otherError is ConstrainingTypeIsError && otherError.typeVariable == error.typeVariable) + || otherError is NewConstraintError + } + else -> false + } + } + + if (isDiagnosticRedundant) return val expression = when (val atom = error.resolvedAtom.atom) { is PSIKotlinCallForInvoke -> (atom.psiCall as? CallTransformer.CallForImplicitInvoke)?.outerCall?.calleeExpression is PSIKotlinCall -> atom.psiCall.calleeExpression @@ -443,12 +452,17 @@ class DiagnosticReporterByTrackingStrategy( else -> call.calleeExpression } ?: return - val typeVariableName = when (val typeVariable = error.typeVariable) { - is TypeVariableFromCallableDescriptor -> typeVariable.originalTypeParameter.name.asString() - is TypeVariableForLambdaReturnType -> "return type of lambda" - else -> error("Unsupported type variable: $typeVariable") + if (isSpecialFunction(resolvedAtom)) { + // We locally report errors on some arguments of special calls, on which the error may not be reported directly + reportNotEnoughInformationForTypeParameterForSpecialCall(resolvedAtom, error) + } else { + val typeVariableName = when (val typeVariable = error.typeVariable) { + is TypeVariableFromCallableDescriptor -> typeVariable.originalTypeParameter.name.asString() + is TypeVariableForLambdaReturnType -> "return type of lambda" + else -> error("Unsupported type variable: $typeVariable") + } + trace.reportDiagnosticOnce(NEW_INFERENCE_NO_INFORMATION_FOR_PARAMETER.on(expression, typeVariableName)) } - trace.reportDiagnosticOnce(NEW_INFERENCE_NO_INFORMATION_FOR_PARAMETER.on(expression, typeVariableName)) } OnlyInputTypesDiagnostic::class.java -> { @@ -463,7 +477,77 @@ class DiagnosticReporterByTrackingStrategy( } } + private fun reportNotEnoughInformationForTypeParameterForSpecialCall( + resolvedAtom: ResolvedCallAtom, + error: NotEnoughInformationForTypeParameterImpl + ) { + val subResolvedAtomsToReportError = + getSubResolvedAtomsOfSpecialCallToReportUninferredTypeParameter(resolvedAtom, error.typeVariable) + + if (subResolvedAtomsToReportError.isEmpty()) return + + for (subResolvedAtom in subResolvedAtomsToReportError) { + val atom = subResolvedAtom.atom as? PSIKotlinCallArgument ?: continue + val argumentsExpression = getArgumentsExpressionOrLastExpressionInBlock(atom) + + if (argumentsExpression != null) { + val specialFunctionName = requireNotNull( + ControlStructureTypingUtils.ResolveConstruct.values().find { specialFunction -> + specialFunction.specialFunctionName == resolvedAtom.candidateDescriptor.name + } + ) { "Unsupported special construct: ${resolvedAtom.candidateDescriptor.name} not found in special construct names" } + + trace.reportDiagnosticOnce( + NEW_INFERENCE_NO_INFORMATION_FOR_PARAMETER.on( + argumentsExpression, " for subcalls of ${specialFunctionName.getName()} expression" + ) + ) + } + } + } + + private fun getArgumentsExpressionOrLastExpressionInBlock(atom: PSIKotlinCallArgument): KtExpression? { + val valueArgumentExpression = atom.valueArgument.getArgumentExpression() + + return if (valueArgumentExpression is KtBlockExpression) valueArgumentExpression.statements.lastOrNull() else valueArgumentExpression + } + + private fun KotlinType.containsUninferredTypeParameter(uninferredTypeVariable: TypeVariableMarker) = contains { + ErrorUtils.isUninferredParameter(it) || it == TypeUtils.DONT_CARE + || it.constructor == uninferredTypeVariable.freshTypeConstructor(typeSystemContext) + } + + @OptIn(ExperimentalStdlibApi::class) + private fun getSubResolvedAtomsOfSpecialCallToReportUninferredTypeParameter( + resolvedAtom: ResolvedAtom, + uninferredTypeVariable: TypeVariableMarker + ): Set = + buildSet { + for (subResolvedAtom in resolvedAtom.subResolvedAtoms ?: return@buildSet) { + val atom = subResolvedAtom.atom + val typeToCheck = when { + subResolvedAtom is PostponedResolvedAtom -> subResolvedAtom.expectedType ?: return@buildSet + atom is SimpleKotlinCallArgument -> atom.receiver.receiverValue.type + else -> return@buildSet + } + + if (typeToCheck.containsUninferredTypeParameter(uninferredTypeVariable)) { + add(subResolvedAtom) + } + + if (!subResolvedAtom.subResolvedAtoms.isNullOrEmpty()) { + addAll( + getSubResolvedAtomsOfSpecialCallToReportUninferredTypeParameter(subResolvedAtom, uninferredTypeVariable) + ) + } + } + } + + @OptIn(ExperimentalContracts::class) private fun isSpecialFunction(atom: ResolvedAtom): Boolean { + contract { + returns(true) implies (atom is ResolvedCallAtom) + } if (atom !is ResolvedCallAtom) return false return ControlStructureTypingUtils.ResolveConstruct.values().any { specialFunction -> diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/KotlinToResolvedCallTransformer.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/KotlinToResolvedCallTransformer.kt index 76bc3ee411f..fd143748cf1 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/KotlinToResolvedCallTransformer.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/KotlinToResolvedCallTransformer.kt @@ -519,6 +519,7 @@ class KotlinToResolvedCallTransformer( context.dataFlowValueFactory, allDiagnostics, smartCastManager, + typeSystemContext ) for (diagnostic in allDiagnostics) { diff --git a/compiler/resolution.common/src/org/jetbrains/kotlin/resolve/calls/inference/components/VariableFixationFinder.kt b/compiler/resolution.common/src/org/jetbrains/kotlin/resolve/calls/inference/components/VariableFixationFinder.kt index 618b29e8d6d..27ec88c4f39 100644 --- a/compiler/resolution.common/src/org/jetbrains/kotlin/resolve/calls/inference/components/VariableFixationFinder.kt +++ b/compiler/resolution.common/src/org/jetbrains/kotlin/resolve/calls/inference/components/VariableFixationFinder.kt @@ -167,7 +167,7 @@ inline fun TypeSystemInferenceExtensionContext.isProperTypeForFixation( type: KotlinTypeMarker, isProper: (KotlinTypeMarker) -> Boolean ): Boolean { - if (!isProper(type)) return false + if (!isProper(type) || type.contains { it.isUninferredParameter() }) return false if (type.isCapturedType()) { val projection = (type as? SimpleTypeMarker)?.asCapturedType()?.typeConstructorProjection() ?: return true if (projection.isStarProjection()) return true diff --git a/compiler/testData/codegen/box/inference/specialCallsWithCallableReferences.kt b/compiler/testData/codegen/box/inference/specialCallsWithCallableReferences.kt new file mode 100644 index 00000000000..be48cfab68d --- /dev/null +++ b/compiler/testData/codegen/box/inference/specialCallsWithCallableReferences.kt @@ -0,0 +1,154 @@ +// WITH_RUNTIME +// SKIP_TXT + +import kotlin.experimental.ExperimentalTypeInference + +fun K.bar3(): K = null as K +fun K.foo3(): K = null as K + +fun bar2(): Int = 1 +fun foo2(): Float = 1f + +fun bar4(): K = null as K +fun foo4(): K = null as K + +class Foo6 + +class Foo7 +fun foo7() = null as Foo7 + +fun poll1(flag: Boolean): Any? { + val inv = if (flag) { ::bar2 } else { ::foo2 } + return inv() +} + +fun poll11(flag: Boolean): Any? { + val inv = if (flag) { ::bar2 } else { ::foo2 } + return inv() +} + +fun poll16(flag: Boolean): Any? { + val inv = if (flag) { ::Foo6 } else { ::Foo6 } + return inv() +} + +// TODO +//fun poll17(flag: Boolean): Any? { +// val inv = if (flag) { foo7() } else { ::Foo7 } +// return inv +//} + +fun poll21(flag: Boolean): Any? { + val inv = when (flag) { true -> ::bar2 else -> ::foo2 } + return inv() +} + +fun poll25(flag: Boolean): Any? { + val inv = when (flag) { true -> ::Foo6 else -> ::Foo6 } + return inv +} + +// TODO +//fun poll26(flag: Boolean): Any? { +// val inv = when (flag) { true -> ::Foo7 false -> foo7() else -> ::Foo7 } +// return inv +//} + +fun poll31(flag: Boolean): Any? { + val inv = when (flag) { true -> ::bar2 false -> ::foo2 } + return inv() +} + +fun poll35(flag: Boolean): Any? { + val inv = when (flag) { true -> ::Foo6 false -> ::Foo6 } + return inv +} + +// TODO +//fun poll36(flag: Boolean): Any? { +// val inv = when (flag) { true -> ::Foo7 false -> foo7() } +// return inv +//} + +fun poll41(): Any? { + val inv = try { ::bar2 } finally { ::foo2 } + return inv() +} + +fun poll45(): Any? { + val inv = try { ::Foo6 } finally { ::Foo6 } + return inv() +} + +fun poll51(): Any? { + val inv = try { ::bar2 } catch (e: Exception) { ::foo2 } finally { ::foo2 } + return inv() +} + +fun poll55(): Any? { + val inv = try { ::Foo6 } catch (e: Exception) { ::Foo6 } finally { ::Foo6 } + return inv() +} + +// TODO +//fun poll56(): Any? { +// val inv = try { ::Foo7 } catch (e: Exception) { foo7() } finally { foo7() } +// return inv +//} + +fun poll61(): Any? { + val inv = ::bar2 + return inv +} + +fun poll65(): Any? { + val inv = ::Foo6 + return inv +} + +fun poll71(): Any? { + val inv = ::bar2!! + return inv() +} + +fun poll75(): Any? { + val inv = ::Foo6!! + return inv +} + +fun poll81(): Any? { + val inv = ::bar2 in setOf(::foo2) + return inv +} + + +fun poll85(): Any? { + val inv = ::Foo6 in setOf(::Foo6) + return inv +} + +fun box(): String { + poll1(true) + poll11(true) + poll16(true) +// poll17(true) + poll21(true) + poll25(true) +// poll26(true) + poll31(true) + poll35(true) +// poll36(true) + poll41() + poll45() + poll51() + poll55() +// poll56() + poll61() + poll65() + poll71() + poll75() + poll81() + poll85() + return "OK" +} + diff --git a/compiler/testData/diagnostics/tests/callableReference/withQuestionMarks.kt b/compiler/testData/diagnostics/tests/callableReference/withQuestionMarks.kt index f02e92b22f5..3a4f2f898a2 100644 --- a/compiler/testData/diagnostics/tests/callableReference/withQuestionMarks.kt +++ b/compiler/testData/diagnostics/tests/callableReference/withQuestionMarks.kt @@ -10,18 +10,18 @@ fun main() { val x4 = logger?::info?::print?::print?::print?::print?::print?::print?::print?::print?::print?::print val x5 = logger::info?::print?::print?::print?::print?::print?::print?::print?::print?::print?::print val x6 = logger!!::info?::print?::print - val x7 = logger::info!!::print?::print - val x8 = logger?::info!!::print?::print + val x7 = logger::info!!::print?::print + val x8 = logger?::info!!::print?::print val x9 = logger!!::info?::print?::print - val x10 = logger::info?::print!!::print - val x11 = logger!!::info!!::print!!::print - val x12 = logger?::info!!::print!!::print + val x10 = logger::info?::print!!::print + val x11 = logger!!::info!!::print!!::print + val x12 = logger?::info!!::print!!::print val x13 = 42?::unresolved?::print val x14 = logger?!!::info?::print?::print val x15 = logger::info?!!::print?::print val x16 = logger!!?::info?::print?::print - val x17 = logger::info!!?::print?::print + val x17 = logger::info!!?::print?::print // It must be OK val x18 = String?::hashCode ?: ::foo diff --git a/compiler/testData/diagnostics/tests/inference/reportingImprovements/kt42620.kt b/compiler/testData/diagnostics/tests/inference/reportingImprovements/kt42620.kt index bab8432d108..66cd0c6cbae 100644 --- a/compiler/testData/diagnostics/tests/inference/reportingImprovements/kt42620.kt +++ b/compiler/testData/diagnostics/tests/inference/reportingImprovements/kt42620.kt @@ -12,4 +12,4 @@ fun main3() = if (true) { Foo::minus } else { Foo::minus } finally { Foo::times } -fun main5() = Foo::minus ?: Foo::times +fun main5() = Foo::minus ?: Foo::times diff --git a/compiler/testData/diagnostics/tests/inference/specialCallsWithCallableReferences.fir.kt b/compiler/testData/diagnostics/tests/inference/specialCallsWithCallableReferences.fir.kt new file mode 100644 index 00000000000..662faa580a9 --- /dev/null +++ b/compiler/testData/diagnostics/tests/inference/specialCallsWithCallableReferences.fir.kt @@ -0,0 +1,318 @@ +// WITH_RUNTIME +// SKIP_TXT +// !DIAGNOSTICS: -CAST_NEVER_SUCCEEDS -UNCHECKED_CAST -UNUSED_PARAMETER -UNUSED_VARIABLE -EXPERIMENTAL_API_USAGE_ERROR -UNUSED_EXPRESSION + +import kotlin.experimental.ExperimentalTypeInference + +fun K.bar3(): K = null as K +fun K.foo3(): K = null as K + +fun bar2(): Int = 1 +fun foo2(): Float = 1f + +val bar4: Int + get() = 1 + +var foo4: Float + get() = 1f + set(value) {} + +class Foo6 + +class Foo7 +fun foo7() = null as Foo7 + +fun poll1(flag: Boolean) { + val inv = if (flag) { ::bar2 } else { ::foo2 } + inv() +} + +fun poll11(flag: Boolean) { + val inv = if (flag) { ::bar2 } else { ::foo2 } + inv() +} + +fun poll12(flag: Boolean) { + val inv = if (flag) { ::bar3 } else { ::foo3 } + inv() +} + +fun poll13(flag: Boolean) { + val inv = if (flag) { ::bar2 } else { ::foo3 } + inv() +} + +fun poll14(flag: Boolean) { + val inv = if (flag) { ::bar4 } else { ::foo4 } + inv() +} + +fun poll15(flag: Boolean) { + val inv = if (flag) { ::bar5 } else { ::foo5 } + inv() +} + +fun poll16(flag: Boolean) { + val inv = if (flag) { ::Foo6 } else { ::Foo6 } + inv() +} + +fun poll17(flag: Boolean) { + val inv = if (flag) { foo7() } else { ::Foo7 } + inv +} + +fun poll2(flag: Boolean) { + val inv = when (flag) { true -> ::bar else -> ::foo } + inv() +} + +fun poll21(flag: Boolean) { + val inv = when (flag) { true -> ::bar2 else -> ::foo2 } + inv() +} + +fun poll22(flag: Boolean) { + val inv = when (flag) { true -> ::bar3 else -> ::foo3 } + inv() +} + +fun poll23(flag: Boolean) { + val inv = when (flag) { true -> ::bar4 else -> ::foo4 } + inv() +} + +fun poll24(flag: Boolean) { + val inv = when (flag) { true -> ::bar5 else -> ::foo5 } + inv +} + +fun poll25(flag: Boolean) { + val inv = when (flag) { true -> ::Foo6 else -> ::Foo6 } + inv +} + +fun poll26(flag: Boolean) { + val inv = when (flag) { true -> ::Foo7 false -> foo7() else -> ::Foo7 } + inv +} + +fun poll3(flag: Boolean) { + val inv = when (flag) { true -> ::bar false -> ::foo } + inv() +} + +fun poll31(flag: Boolean) { + val inv = when (flag) { true -> ::bar2 false -> ::foo2 } + inv() +} + +fun poll32(flag: Boolean) { + val inv = when (flag) { true -> ::bar3 false -> ::foo3 } + inv() +} + +fun poll33(flag: Boolean) { + val inv = when (flag) { true -> ::bar4 false -> ::foo4 } + inv() +} + +fun poll34(flag: Boolean) { + val inv = when (flag) { true -> ::bar5 false -> ::foo5 } + inv +} + +fun poll35(flag: Boolean) { + val inv = when (flag) { true -> ::Foo6 false -> ::Foo6 } + inv +} + +fun poll36(flag: Boolean) { + val inv = when (flag) { true -> ::Foo7 false -> foo7() } + inv +} + +fun poll4() { + val inv = try { ::bar } finally { ::foo } + inv() +} + +fun poll41() { + val inv = try { ::bar2 } finally { ::foo2 } + inv() +} + +fun poll42() { + val inv = try { ::bar3 } finally { ::foo3 } + inv() +} + +fun poll43() { + val inv = try { ::bar4 } finally { ::foo4 } + inv() +} + +fun poll44() { + val inv = try { ::bar5 } finally { ::foo5 } + inv() +} + +fun poll45() { + val inv = try { ::Foo6 } finally { ::Foo6 } + inv() +} + +fun poll46() { + val inv = try { foo7() } finally { ::Foo7 } + inv +} + +fun poll5() { + val inv = try { ::bar } catch (e: Exception) { ::foo } finally { ::foo } + inv() +} + +fun poll51() { + val inv = try { ::bar2 } catch (e: Exception) { ::foo2 } finally { ::foo2 } + inv() +} + +fun poll52() { + val inv = try { ::bar3 } catch (e: Exception) { ::foo3 } finally { ::foo3 } + inv() +} + +fun poll53() { + val inv = try { ::bar4 } catch (e: Exception) { ::foo4 } finally { ::foo4 } + inv() +} + +fun poll54() { + val inv = try { ::bar5 } catch (e: Exception) { ::foo5 } finally { ::foo5 } + inv() +} + +fun poll55() { + val inv = try { ::Foo6 } catch (e: Exception) { ::Foo6 } finally { ::Foo6 } + inv() +} + +fun poll56() { + val inv = try { ::Foo7 } catch (e: Exception) { foo7() } finally { foo7() } + inv +} + +fun poll6() { + val inv = ::bar + inv +} + +fun poll61() { + val inv = ::bar2 + inv +} + +fun poll62() { + val inv = ::bar3 + inv +} + +fun poll63() { + val inv = ::bar4 + inv +} + +fun poll64() { + val inv = ::bar5 + inv +} + +fun poll65() { + val inv = ::Foo6 + inv +} + +fun poll66() { + val inv = ::Foo7 + inv +} + +fun poll7() { + val inv = ::bar!! + inv() +} + +fun poll71() { + val inv = ::bar2!! + inv() +} + +fun poll72() { + val inv = ::bar3!! + inv() +} + +fun poll73() { + val inv = ::bar4!! + inv +} + +fun poll74() { + val inv = ::bar5!! + inv +} + +fun poll75() { + val inv = ::Foo6!! + inv +} + +fun poll76() { + val inv = ::Foo7!! + inv +} + +fun poll8() { + val inv = ::bar in setOf(::foo) + inv() +} + +fun poll81() { + val inv = ::bar2 in setOf(::foo2) + inv() +} + +fun poll82() { + val inv = ::bar3 in setOf(::foo3) + inv() +} + +fun poll83() { + val inv = ::bar4 in setOf(::foo4) + inv +} + +fun poll84() { + val inv = ::bar5 in setOf(::foo5) + inv +} + +fun poll85() { + val inv = ::Foo6 in setOf(::Foo6) + inv +} + +fun poll86() { + val inv = ::Foo7 in setOf(::Foo7) + inv +} + +fun poll87() { + val inv = ::Foo7 in setOf(foo7()) + inv +} + +fun poll88() { + val inv = foo7() in setOf(::Foo7) + inv +} diff --git a/compiler/testData/diagnostics/tests/inference/specialCallsWithCallableReferences.kt b/compiler/testData/diagnostics/tests/inference/specialCallsWithCallableReferences.kt new file mode 100644 index 00000000000..dc153a98e5b --- /dev/null +++ b/compiler/testData/diagnostics/tests/inference/specialCallsWithCallableReferences.kt @@ -0,0 +1,314 @@ +// WITH_RUNTIME +// SKIP_TXT +// !DIAGNOSTICS: -CAST_NEVER_SUCCEEDS -UNCHECKED_CAST -UNUSED_PARAMETER -UNUSED_VARIABLE -EXPERIMENTAL_API_USAGE_ERROR -UNUSED_EXPRESSION + +import kotlin.experimental.ExperimentalTypeInference + +fun K.bar3(): K = null as K +fun K.foo3(): K = null as K + +fun bar2(): Int = 1 +fun foo2(): Float = 1f + +fun bar4(): K = null as K +fun foo4(): K = null as K + +class Foo6 + +class Foo7 +fun foo7() = null as Foo7 + +fun poll1(flag: Boolean) { + val inv = if (flag) { ::bar2 } else { ::foo2 } + inv() +} + +fun poll11(flag: Boolean) { + val inv = if (flag) { ::bar2 } else { ::foo2 } + inv() +} + +fun poll12(flag: Boolean) { + val inv = if (flag) { ::bar3 } else { ::foo3 } + inv() +} + +fun poll13(flag: Boolean) { + val inv = if (flag) { ::bar2 } else { ::foo3 } + inv() +} + +fun poll14(flag: Boolean) { + val inv = if (flag) { ::bar4 } else { ::foo4 } + inv() +} + +fun poll15(flag: Boolean) { + val inv = if (flag) { ::bar5 } else { ::foo5 } + inv() +} + +fun poll16(flag: Boolean) { + val inv = if (flag) { ::Foo6 } else { ::Foo6 } + inv() +} + +fun poll17(flag: Boolean) { + val inv = if (flag) { foo7() } else { ::Foo7 } + inv +} + +fun poll2(flag: Boolean) { + val inv = when (flag) { true -> ::bar else -> ::foo } + inv() +} + +fun poll21(flag: Boolean) { + val inv = when (flag) { true -> ::bar2 else -> ::foo2 } + inv() +} + +fun poll22(flag: Boolean) { + val inv = when (flag) { true -> ::bar3 else -> ::foo3 } + inv() +} + +fun poll23(flag: Boolean) { + val inv = when (flag) { true -> ::bar4 else -> ::foo4 } + inv() +} + +fun poll24(flag: Boolean) { + val inv = when (flag) { true -> ::bar5 else -> ::foo5 } + inv +} + +fun poll25(flag: Boolean) { + val inv = when (flag) { true -> ::Foo6 else -> ::Foo6 } + inv +} + +fun poll26(flag: Boolean) { + val inv = when (flag) { true -> ::Foo7 false -> foo7() else -> ::Foo7 } + inv +} + +fun poll3(flag: Boolean) { + val inv = when (flag) { true -> ::bar false -> ::foo } + inv() +} + +fun poll31(flag: Boolean) { + val inv = when (flag) { true -> ::bar2 false -> ::foo2 } + inv() +} + +fun poll32(flag: Boolean) { + val inv = when (flag) { true -> ::bar3 false -> ::foo3 } + inv() +} + +fun poll33(flag: Boolean) { + val inv = when (flag) { true -> ::bar4 false -> ::foo4 } + inv() +} + +fun poll34(flag: Boolean) { + val inv = when (flag) { true -> ::bar5 false -> ::foo5 } + inv +} + +fun poll35(flag: Boolean) { + val inv = when (flag) { true -> ::Foo6 false -> ::Foo6 } + inv +} + +fun poll36(flag: Boolean) { + val inv = when (flag) { true -> ::Foo7 false -> foo7() } + inv +} + +fun poll4() { + val inv = try { ::bar } finally { ::foo } + inv() +} + +fun poll41() { + val inv = try { ::bar2 } finally { ::foo2 } + inv() +} + +fun poll42() { + val inv = try { ::bar3 } finally { ::foo3 } + inv() +} + +fun poll43() { + val inv = try { ::bar4 } finally { ::foo4 } + inv() +} + +fun poll44() { + val inv = try { ::bar5 } finally { ::foo5 } + inv() +} + +fun poll45() { + val inv = try { ::Foo6 } finally { ::Foo6 } + inv() +} + +fun poll46() { + val inv = try { foo7() } finally { ::Foo7 } + inv +} + +fun poll5() { + val inv = try { ::bar } catch (e: Exception) { ::foo } finally { ::foo } + inv() +} + +fun poll51() { + val inv = try { ::bar2 } catch (e: Exception) { ::foo2 } finally { ::foo2 } + inv() +} + +fun poll52() { + val inv = try { ::bar3 } catch (e: Exception) { ::foo3 } finally { ::foo3 } + inv() +} + +fun poll53() { + val inv = try { ::bar4 } catch (e: Exception) { ::foo4 } finally { ::foo4 } + inv() +} + +fun poll54() { + val inv = try { ::bar5 } catch (e: Exception) { ::foo5 } finally { ::foo5 } + inv() +} + +fun poll55() { + val inv = try { ::Foo6 } catch (e: Exception) { ::Foo6 } finally { ::Foo6 } + inv() +} + +fun poll56() { + val inv = try { ::Foo7 } catch (e: Exception) { foo7() } finally { foo7() } + inv +} + +fun poll6() { + val inv = ::bar + inv +} + +fun poll61() { + val inv = ::bar2 + inv +} + +fun poll62() { + val inv = ::bar3 + inv +} + +fun poll63() { + val inv = ::bar4 + inv +} + +fun poll64() { + val inv = ::bar5 + inv +} + +fun poll65() { + val inv = ::Foo6 + inv +} + +fun poll66() { + val inv = ::Foo7 + inv +} + +fun poll7() { + val inv = ::bar!! + inv() +} + +fun poll71() { + val inv = ::bar2!! + inv() +} + +fun poll72() { + val inv = ::bar3!! + inv() +} + +fun poll73() { + val inv = ::bar4!! + inv +} + +fun poll74() { + val inv = ::bar5!! + inv +} + +fun poll75() { + val inv = ::Foo6!! + inv +} + +fun poll76() { + val inv = ::Foo7!! + inv +} + +fun poll8() { + val inv = ::bar in setOf(::foo) + inv() +} + +fun poll81() { + val inv = ::bar2 in setOf(::foo2) + inv() +} + +fun poll82() { + val inv = ::bar3 in setOf(::foo3) + inv() +} + +fun poll83() { + val inv = ::bar4 in setOf(::foo4) + inv +} + +fun poll84() { + val inv = ::bar5 in setOf(::foo5) + inv +} + +fun poll85() { + val inv = ::Foo6 in setOf(::Foo6) + inv +} + +fun poll86() { + val inv = ::Foo7 in setOf(::Foo7) + inv +} + +fun poll87() { + val inv = ::Foo7 in setOf(foo7()) + inv +} + +fun poll88() { + val inv = foo7() in setOf(::Foo7) + inv +} diff --git a/compiler/testData/diagnostics/tests/regressions/kt10843.kt b/compiler/testData/diagnostics/tests/regressions/kt10843.kt index 60be57a47a0..e589349688c 100644 --- a/compiler/testData/diagnostics/tests/regressions/kt10843.kt +++ b/compiler/testData/diagnostics/tests/regressions/kt10843.kt @@ -1,8 +1,8 @@ // !WITH_NEW_INFERENCE // NI_EXPECTED_FILE // See EA-76890 / KT-10843: NPE during analysis -fun lambda(x : Int?) = x?.let l { - y -> - if (y > 0) return@l x +fun lambda(x : Int?) = x?.let l { + y -> + if (y > 0) return@l x y }!! diff --git a/compiler/testData/diagnostics/tests/resolve/callableReferenceInCST.kt b/compiler/testData/diagnostics/tests/resolve/callableReferenceInCST.kt index 6152c6d22c4..a95f2b3796c 100644 --- a/compiler/testData/diagnostics/tests/resolve/callableReferenceInCST.kt +++ b/compiler/testData/diagnostics/tests/resolve/callableReferenceInCST.kt @@ -28,7 +28,7 @@ fun testElvis(x: Any?) { } fun testExclExcl() { - val y = :: unresolved!! + val y = :: unresolved!! } fun testTry() { diff --git a/compiler/testData/diagnostics/testsWithStdLib/coroutines/inference/applyInsideCoroutine.kt b/compiler/testData/diagnostics/testsWithStdLib/coroutines/inference/applyInsideCoroutine.kt index 8aee3020c07..91158d041a1 100644 --- a/compiler/testData/diagnostics/testsWithStdLib/coroutines/inference/applyInsideCoroutine.kt +++ b/compiler/testData/diagnostics/testsWithStdLib/coroutines/inference/applyInsideCoroutine.kt @@ -10,25 +10,25 @@ class Controller { fun generate(g: suspend Controller.() -> Unit): S = TODO() val test1 = generate { - apply { - yield(4) + apply { + yield(4) } } val test2 = generate { yield(B) - apply { - yield(C) + apply { + yield(C) } } -val test3 = generate { - this.let { +val test3 = generate { + this.let { yield(B) } - apply { - yield(C) + apply { + yield(C) } } diff --git a/compiler/testData/diagnostics/testsWithStdLib/coroutines/inference/recursiveGenerators2.kt b/compiler/testData/diagnostics/testsWithStdLib/coroutines/inference/recursiveGenerators2.kt index 343ff7160d9..4e8073cf5c4 100644 --- a/compiler/testData/diagnostics/testsWithStdLib/coroutines/inference/recursiveGenerators2.kt +++ b/compiler/testData/diagnostics/testsWithStdLib/coroutines/inference/recursiveGenerators2.kt @@ -16,7 +16,7 @@ fun generate(@BuilderInference g: suspend GenericController.() -> Unit): @BuilderInference suspend fun GenericController>.yieldGenerate(g: suspend GenericController.() -> Unit): Unit = TODO() -val test1 = generate { +val test1 = generate { // TODO: KT-15185 yieldGenerate { yield(4) diff --git a/compiler/testData/diagnostics/testsWithStdLib/inference/kt42620.kt b/compiler/testData/diagnostics/testsWithStdLib/inference/kt42620.kt index abc8c0bb545..f8322ec29ff 100644 --- a/compiler/testData/diagnostics/testsWithStdLib/inference/kt42620.kt +++ b/compiler/testData/diagnostics/testsWithStdLib/inference/kt42620.kt @@ -3,13 +3,13 @@ class Foo fun main1() = when { - else -> Foo::plus + else -> Foo::plus } -fun main2() = if (true) Foo::minus else Foo::times +fun main2() = if (true) Foo::minus else Foo::times fun main3() = if (true) { Foo::minus } else { Foo::times } fun main4() = try { Foo::minus } finally { Foo::times } -fun main5() = Foo::minus ?: Foo::times +fun main5() = Foo::minus ?: Foo::times diff --git a/compiler/tests-gen/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java b/compiler/tests-gen/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java index 67f51d3591b..3dfe5b02214 100644 --- a/compiler/tests-gen/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java +++ b/compiler/tests-gen/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java @@ -13459,6 +13459,11 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest { runTest("compiler/testData/codegen/box/inference/referenceToCatchParameterFromLambdaExpression.kt"); } + @TestMetadata("specialCallsWithCallableReferences.kt") + public void testSpecialCallsWithCallableReferences() throws Exception { + runTest("compiler/testData/codegen/box/inference/specialCallsWithCallableReferences.kt"); + } + @TestMetadata("subtypingOfIntersectionIltInsideFlexible.kt") public void testSubtypingOfIntersectionIltInsideFlexible() throws Exception { runTest("compiler/testData/codegen/box/inference/subtypingOfIntersectionIltInsideFlexible.kt"); diff --git a/compiler/tests-gen/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java b/compiler/tests-gen/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java index 8b20c4f470d..b8a86ff5c86 100644 --- a/compiler/tests-gen/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java +++ b/compiler/tests-gen/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java @@ -13459,6 +13459,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes runTest("compiler/testData/codegen/box/inference/referenceToCatchParameterFromLambdaExpression.kt"); } + @TestMetadata("specialCallsWithCallableReferences.kt") + public void testSpecialCallsWithCallableReferences() throws Exception { + runTest("compiler/testData/codegen/box/inference/specialCallsWithCallableReferences.kt"); + } + @TestMetadata("subtypingOfIntersectionIltInsideFlexible.kt") public void testSubtypingOfIntersectionIltInsideFlexible() throws Exception { runTest("compiler/testData/codegen/box/inference/subtypingOfIntersectionIltInsideFlexible.kt"); diff --git a/compiler/tests-gen/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java b/compiler/tests-gen/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java index fa87bda514f..4588267417d 100644 --- a/compiler/tests-gen/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java +++ b/compiler/tests-gen/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java @@ -13459,6 +13459,11 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes runTest("compiler/testData/codegen/box/inference/referenceToCatchParameterFromLambdaExpression.kt"); } + @TestMetadata("specialCallsWithCallableReferences.kt") + public void testSpecialCallsWithCallableReferences() throws Exception { + runTest("compiler/testData/codegen/box/inference/specialCallsWithCallableReferences.kt"); + } + @TestMetadata("subtypingOfIntersectionIltInsideFlexible.kt") public void testSubtypingOfIntersectionIltInsideFlexible() throws Exception { runTest("compiler/testData/codegen/box/inference/subtypingOfIntersectionIltInsideFlexible.kt"); diff --git a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/es6/semantics/IrJsCodegenBoxES6TestGenerated.java b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/es6/semantics/IrJsCodegenBoxES6TestGenerated.java index 6cc2a216b30..6ba5c5909cb 100644 --- a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/es6/semantics/IrJsCodegenBoxES6TestGenerated.java +++ b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/es6/semantics/IrJsCodegenBoxES6TestGenerated.java @@ -11519,6 +11519,11 @@ public class IrJsCodegenBoxES6TestGenerated extends AbstractIrJsCodegenBoxES6Tes runTest("compiler/testData/codegen/box/inference/referenceToCatchParameterFromLambdaExpression.kt"); } + @TestMetadata("specialCallsWithCallableReferences.kt") + public void testSpecialCallsWithCallableReferences() throws Exception { + runTest("compiler/testData/codegen/box/inference/specialCallsWithCallableReferences.kt"); + } + @TestMetadata("suspendExtensionRecevierFromConstraint.kt") public void testSuspendExtensionRecevierFromConstraint() throws Exception { runTest("compiler/testData/codegen/box/inference/suspendExtensionRecevierFromConstraint.kt"); diff --git a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/ir/semantics/IrJsCodegenBoxTestGenerated.java b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/ir/semantics/IrJsCodegenBoxTestGenerated.java index 691a3b91b69..e1365ff0467 100644 --- a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/ir/semantics/IrJsCodegenBoxTestGenerated.java +++ b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/ir/semantics/IrJsCodegenBoxTestGenerated.java @@ -11519,6 +11519,11 @@ public class IrJsCodegenBoxTestGenerated extends AbstractIrJsCodegenBoxTest { runTest("compiler/testData/codegen/box/inference/referenceToCatchParameterFromLambdaExpression.kt"); } + @TestMetadata("specialCallsWithCallableReferences.kt") + public void testSpecialCallsWithCallableReferences() throws Exception { + runTest("compiler/testData/codegen/box/inference/specialCallsWithCallableReferences.kt"); + } + @TestMetadata("suspendExtensionRecevierFromConstraint.kt") public void testSuspendExtensionRecevierFromConstraint() throws Exception { runTest("compiler/testData/codegen/box/inference/suspendExtensionRecevierFromConstraint.kt"); diff --git a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java index caebaf29af3..7e7edf79cb9 100644 --- a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java +++ b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java @@ -11584,6 +11584,11 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest { runTest("compiler/testData/codegen/box/inference/referenceToCatchParameterFromLambdaExpression.kt"); } + @TestMetadata("specialCallsWithCallableReferences.kt") + public void testSpecialCallsWithCallableReferences() throws Exception { + runTest("compiler/testData/codegen/box/inference/specialCallsWithCallableReferences.kt"); + } + @TestMetadata("suspendExtensionRecevierFromConstraint.kt") public void testSuspendExtensionRecevierFromConstraint() throws Exception { runTest("compiler/testData/codegen/box/inference/suspendExtensionRecevierFromConstraint.kt"); diff --git a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/wasm/semantics/IrCodegenBoxWasmTestGenerated.java b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/wasm/semantics/IrCodegenBoxWasmTestGenerated.java index 372687e0cb8..fe48e4b774b 100644 --- a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/wasm/semantics/IrCodegenBoxWasmTestGenerated.java +++ b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/wasm/semantics/IrCodegenBoxWasmTestGenerated.java @@ -6170,6 +6170,11 @@ public class IrCodegenBoxWasmTestGenerated extends AbstractIrCodegenBoxWasmTest runTest("compiler/testData/codegen/box/inference/recursiveConstraintInsideTypeArgumentWithStarProjection.kt"); } + @TestMetadata("specialCallsWithCallableReferences.kt") + public void testSpecialCallsWithCallableReferences() throws Exception { + runTest("compiler/testData/codegen/box/inference/specialCallsWithCallableReferences.kt"); + } + @TestMetadata("unsafeVarianceCodegen.kt") public void testUnsafeVarianceCodegen() throws Exception { runTest("compiler/testData/codegen/box/inference/unsafeVarianceCodegen.kt");