From c5893913f33d96f816ea1cc2d7dfa180a9ea55c6 Mon Sep 17 00:00:00 2001 From: Pavel Kirpichenkov Date: Mon, 20 Jan 2020 19:25:35 +0300 Subject: [PATCH] [NI] Remove lambda coersion to Unit in case of error return type(s) Coersion to Unit from error type leads to misleading type mismatches: "expected found Unit", despite no user-provided Unit / empty lambda. These diagnostics were collected, but not reported before, and that had been disguising the issue for a while. KT-34729 Fixed --- ...irOldFrontendDiagnosticsTestGenerated.java | 5 ++ .../tower/KotlinResolutionCallbacksImpl.kt | 12 +-- .../calls/tower/ResolvedAtomCompleter.kt | 6 +- .../calls/components/ExternalComponents.kt | 13 +++- .../components/PostponedArgumentsAnalyzer.kt | 10 +-- .../resolve/calls/model/ResolutionAtoms.kt | 7 +- .../diagnostics/tests/AutoCreatedIt.kt | 2 +- .../extensionMemberInClassObject.fir.kt | 1 + .../extensionMemberInClassObject.kt | 3 +- .../extensionReceiverTypeMismatch.kt | 4 +- ...WithAnonymousFunctionsAndUnresolved.fir.kt | 74 +++++++++++++++++++ ...sionWithAnonymousFunctionsAndUnresolved.kt | 74 +++++++++++++++++++ ...ionWithAnonymousFunctionsAndUnresolved.txt | 8 ++ .../diagnostics/tests/inference/kt28654.kt | 2 +- .../tests/inference/recursiveCalls/kt23531.kt | 8 +- .../tests/inference/regressions/kt2741.fir.kt | 2 + .../tests/inference/regressions/kt2741.kt | 4 +- .../tests/inference/regressions/kt2841.fir.kt | 2 + .../tests/inference/regressions/kt2841.kt | 4 +- .../inference/regressions/kt2841_it.fir.kt | 2 + .../tests/inference/regressions/kt2841_it.kt | 4 +- .../regressions/kt2841_it_this.fir.kt | 2 + .../inference/regressions/kt2841_it_this.kt | 4 +- .../inference/regressions/kt2841_this.fir.kt | 2 + .../inference/regressions/kt2841_this.kt | 4 +- ...oAmbiguityForDifferentFunctionTypes.fir.kt | 2 + .../NoAmbiguityForDifferentFunctionTypes.kt | 4 +- .../diagnostics/tests/regressions/kt30245.kt | 2 +- .../invoke/wrongInvokeExtension.fir.kt | 2 + .../resolve/invoke/wrongInvokeExtension.kt | 4 +- .../tests/resolve/newLineLambda.kt | 4 +- .../resolve/hidesMembers.fir.kt | 1 + .../testsWithStdLib/resolve/hidesMembers.kt | 3 +- .../resolve/hidesMembers2.fir.kt | 2 + .../testsWithStdLib/resolve/hidesMembers2.kt | 4 +- .../checkers/DiagnosticsTestGenerated.java | 5 ++ .../DiagnosticsUsingJavacTestGenerated.java | 5 ++ .../LightAnalysisModeTestGenerated.java | 10 +-- .../inspections/collections/FunctionUtils.kt | 2 +- 39 files changed, 263 insertions(+), 46 deletions(-) create mode 100644 compiler/testData/diagnostics/tests/inference/coercionToUnit/coersionWithAnonymousFunctionsAndUnresolved.fir.kt create mode 100644 compiler/testData/diagnostics/tests/inference/coercionToUnit/coersionWithAnonymousFunctionsAndUnresolved.kt create mode 100644 compiler/testData/diagnostics/tests/inference/coercionToUnit/coersionWithAnonymousFunctionsAndUnresolved.txt diff --git a/compiler/fir/resolve/tests/org/jetbrains/kotlin/fir/FirOldFrontendDiagnosticsTestGenerated.java b/compiler/fir/resolve/tests/org/jetbrains/kotlin/fir/FirOldFrontendDiagnosticsTestGenerated.java index fc77efafad8..5d14a817eaa 100644 --- a/compiler/fir/resolve/tests/org/jetbrains/kotlin/fir/FirOldFrontendDiagnosticsTestGenerated.java +++ b/compiler/fir/resolve/tests/org/jetbrains/kotlin/fir/FirOldFrontendDiagnosticsTestGenerated.java @@ -10371,6 +10371,11 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirOldFronte runTest("compiler/testData/diagnostics/tests/inference/coercionToUnit/coercionWithoutExpectedType.kt"); } + @TestMetadata("coersionWithAnonymousFunctionsAndUnresolved.kt") + public void testCoersionWithAnonymousFunctionsAndUnresolved() throws Exception { + runTest("compiler/testData/diagnostics/tests/inference/coercionToUnit/coersionWithAnonymousFunctionsAndUnresolved.kt"); + } + @TestMetadata("indirectCoercionWithExpectedType.kt") public void testIndirectCoercionWithExpectedType() throws Exception { runTest("compiler/testData/diagnostics/tests/inference/coercionToUnit/indirectCoercionWithExpectedType.kt"); diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/KotlinResolutionCallbacksImpl.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/KotlinResolutionCallbacksImpl.kt index bf1725adc5a..e6671fba972 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/KotlinResolutionCallbacksImpl.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/KotlinResolutionCallbacksImpl.kt @@ -23,10 +23,7 @@ import org.jetbrains.kotlin.psi.psiUtil.getBinaryWithTypeParent import org.jetbrains.kotlin.psi.psiUtil.lastBlockStatementOrThis import org.jetbrains.kotlin.resolve.* import org.jetbrains.kotlin.resolve.calls.ArgumentTypeResolver -import org.jetbrains.kotlin.resolve.calls.SPECIAL_FUNCTION_NAMES -import org.jetbrains.kotlin.resolve.calls.components.InferenceSession -import org.jetbrains.kotlin.resolve.calls.components.KotlinResolutionCallbacks -import org.jetbrains.kotlin.resolve.calls.components.PostponedArgumentsAnalyzer +import org.jetbrains.kotlin.resolve.calls.components.* import org.jetbrains.kotlin.resolve.calls.context.BasicCallResolutionContext import org.jetbrains.kotlin.resolve.calls.context.ContextDependency import org.jetbrains.kotlin.resolve.calls.inference.CoroutineInferenceSession @@ -95,7 +92,7 @@ class KotlinResolutionCallbacksImpl( expectedReturnType: UnwrappedType?, annotations: Annotations, stubsForPostponedVariables: Map - ): Pair, InferenceSession?> { + ): ReturnArgumentsAnalysisResult { val psiCallArgument = lambdaArgument.psiCallArgument as PSIFunctionKotlinCallArgument val outerCallContext = psiCallArgument.outerCallContext @@ -191,7 +188,9 @@ class KotlinResolutionCallbacksImpl( trace.record(BindingContext.NEW_INFERENCE_LAMBDA_INFO, psiCallArgument.ktFunction, LambdaInfo.STUB_EMPTY) var hasReturnWithoutExpression = false + var returnArgumentFound = false val returnArguments = lambdaInfo.returnStatements.mapNotNullTo(ArrayList()) { (expression, contextInfo) -> + returnArgumentFound = true val returnedExpression = expression.returnedExpression if (returnedExpression != null) { createCallArgument( @@ -210,6 +209,7 @@ class KotlinResolutionCallbacksImpl( if (expectedReturnType?.isUnit() == true || hasReturnWithoutExpression) return@let null // coercion to Unit // todo lastExpression can be if without else + returnArgumentFound = true val lastExpressionType = trace.getType(lastExpression) val contextInfo = lambdaInfo.lastExpressionInfo val lastExpressionTypeInfo = KotlinTypeInfo(lastExpressionType, contextInfo.dataFlowInfoAfter ?: functionTypeInfo.dataFlowInfo) @@ -218,7 +218,7 @@ class KotlinResolutionCallbacksImpl( returnArguments.addIfNotNull(lastExpressionArgument) - return Pair(returnArguments, coroutineSession) + return ReturnArgumentsAnalysisResult(ReturnArgumentsInfo(returnArguments, returnArgumentFound), coroutineSession) } private fun getLastDeparentesizedExpression(psiCallArgument: PSIKotlinCallArgument): KtExpression? { diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/ResolvedAtomCompleter.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/ResolvedAtomCompleter.kt index 18a56e90f77..3793a1c40fc 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/ResolvedAtomCompleter.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/ResolvedAtomCompleter.kt @@ -153,7 +153,7 @@ class ResolvedAtomCompleter( private val ResolvedLambdaAtom.isCoercedToUnit: Boolean get() { val returnTypes = - resultArguments.map { + resultArgumentsInfo.nonErrorArguments.map { val type = it.safeAs()?.receiver?.receiverValue?.type ?: return@map null val unwrappedType = when (type) { is WrappedType -> type.unwrap() @@ -161,7 +161,7 @@ class ResolvedAtomCompleter( } resultSubstitutor.safeSubstitute(unwrappedType) } - if (returnTypes.isEmpty()) return true + if (returnTypes.isEmpty() && !resultArgumentsInfo.returnArgumentsExist) return true val substitutedTypes = returnTypes.filterNotNull() // we have some unsubstituted types if (substitutedTypes.isEmpty()) return false @@ -184,7 +184,7 @@ class ResolvedAtomCompleter( ) updateTraceForLambda(lambda, topLevelTrace, approximatedReturnType) - for (lambdaResult in lambda.resultArguments) { + for (lambdaResult in lambda.resultArgumentsInfo.nonErrorArguments) { val resultValueArgument = lambdaResult as? PSIKotlinCallArgument ?: continue val newContext = topLevelCallContext.replaceDataFlowInfo(resultValueArgument.dataFlowInfoAfterThisArgument) diff --git a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/ExternalComponents.kt b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/ExternalComponents.kt index c2bfecd723e..cc95d191ffc 100644 --- a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/ExternalComponents.kt +++ b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/ExternalComponents.kt @@ -12,7 +12,6 @@ import org.jetbrains.kotlin.descriptors.CallableDescriptor import org.jetbrains.kotlin.descriptors.DeclarationDescriptor import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor import org.jetbrains.kotlin.descriptors.annotations.Annotations -import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.resolve.calls.inference.components.ConstraintInjector import org.jetbrains.kotlin.resolve.calls.inference.model.NewTypeVariable import org.jetbrains.kotlin.resolve.calls.model.* @@ -42,6 +41,16 @@ interface KotlinResolutionStatelessCallbacks { ): SimpleConstraintSystem } +data class ReturnArgumentsInfo( + val nonErrorArguments: List, + val returnArgumentsExist: Boolean +) + +data class ReturnArgumentsAnalysisResult( + val returnArgumentsInfo: ReturnArgumentsInfo, + val inferenceSession: InferenceSession? +) + // This components hold state (trace). Work with this carefully. interface KotlinResolutionCallbacks { fun analyzeAndGetLambdaReturnArguments( @@ -52,7 +61,7 @@ interface KotlinResolutionCallbacks { expectedReturnType: UnwrappedType?, // null means, that return type is not proper i.e. it depends on some type variables annotations: Annotations, stubsForPostponedVariables: Map - ): Pair, InferenceSession?> + ): ReturnArgumentsAnalysisResult fun bindStubResolvedCallForCandidate(candidate: ResolvedCallAtom) diff --git a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/PostponedArgumentsAnalyzer.kt b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/PostponedArgumentsAnalyzer.kt index 1729daabf11..b31a2df94bc 100644 --- a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/PostponedArgumentsAnalyzer.kt +++ b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/PostponedArgumentsAnalyzer.kt @@ -118,7 +118,7 @@ class PostponedArgumentsAnalyzer( else FilteredAnnotations(annotations, true) { it != KotlinBuiltIns.FQ_NAMES.extensionFunctionType } } - val (returnArguments, inferenceSession) = resolutionCallbacks.analyzeAndGetLambdaReturnArguments( + val (returnArgumentsInfo, inferenceSession) = resolutionCallbacks.analyzeAndGetLambdaReturnArguments( lambda.atom, lambda.isSuspend, receiver, @@ -128,21 +128,21 @@ class PostponedArgumentsAnalyzer( stubsForPostponedVariables.cast() ) - returnArguments.forEach { c.addSubsystemFromArgument(it) } + returnArgumentsInfo.nonErrorArguments.forEach { c.addSubsystemFromArgument(it) } - val subResolvedKtPrimitives = returnArguments.map { + val subResolvedKtPrimitives = returnArgumentsInfo.nonErrorArguments.map { resolveKtPrimitive( c.getBuilder(), it, lambda.returnType.let(::substitute), diagnosticHolder, isReceiver = false ) } - if (returnArguments.isEmpty()) { + if (!returnArgumentsInfo.returnArgumentsExist) { val unitType = lambda.returnType.builtIns.unitType val lambdaReturnType = lambda.returnType.let(::substitute) c.getBuilder().addSubtypeConstraint(unitType, lambdaReturnType, LambdaArgumentConstraintPosition(lambda)) } - lambda.setAnalyzedResults(returnArguments, subResolvedKtPrimitives) + lambda.setAnalyzedResults(returnArgumentsInfo, subResolvedKtPrimitives) if (inferenceSession != null) { val storageSnapshot = c.getBuilder().currentStorage() diff --git a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/model/ResolutionAtoms.kt b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/model/ResolutionAtoms.kt index 354892f318e..43685179196 100644 --- a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/model/ResolutionAtoms.kt +++ b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/model/ResolutionAtoms.kt @@ -8,6 +8,7 @@ package org.jetbrains.kotlin.resolve.calls.model import org.jetbrains.kotlin.descriptors.CallableDescriptor import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor import org.jetbrains.kotlin.resolve.calls.components.CallableReferenceCandidate +import org.jetbrains.kotlin.resolve.calls.components.ReturnArgumentsInfo import org.jetbrains.kotlin.resolve.calls.components.TypeArgumentsToParametersMapper import org.jetbrains.kotlin.resolve.calls.components.extractInputOutputTypesFromCallableReferenceExpectedType import org.jetbrains.kotlin.resolve.calls.inference.components.FreshVariableNewTypeSubstitutor @@ -115,14 +116,14 @@ class ResolvedLambdaAtom( val typeVariableForLambdaReturnType: TypeVariableForLambdaReturnType?, override val expectedType: UnwrappedType? ) : PostponedResolvedAtom() { - lateinit var resultArguments: List + lateinit var resultArgumentsInfo: ReturnArgumentsInfo private set fun setAnalyzedResults( - resultArguments: List, + resultArguments: ReturnArgumentsInfo, subResolvedAtoms: List ) { - this.resultArguments = resultArguments + this.resultArgumentsInfo = resultArguments setAnalyzedResults(subResolvedAtoms) } diff --git a/compiler/testData/diagnostics/tests/AutoCreatedIt.kt b/compiler/testData/diagnostics/tests/AutoCreatedIt.kt index e012e7a9eee..2bce3143a50 100644 --- a/compiler/testData/diagnostics/tests/AutoCreatedIt.kt +++ b/compiler/testData/diagnostics/tests/AutoCreatedIt.kt @@ -10,7 +10,7 @@ fun text() { bar1 {1} bar1 {it + 1} - bar2 {} + bar2 {} bar2 {1} bar2 {it} bar2 {it -> it} diff --git a/compiler/testData/diagnostics/tests/extensions/extensionMemberInClassObject.fir.kt b/compiler/testData/diagnostics/tests/extensions/extensionMemberInClassObject.fir.kt index 5b5862e9dae..46f5bc1c2f0 100644 --- a/compiler/testData/diagnostics/tests/extensions/extensionMemberInClassObject.fir.kt +++ b/compiler/testData/diagnostics/tests/extensions/extensionMemberInClassObject.fir.kt @@ -1,4 +1,5 @@ // !DIAGNOSTICS: -UNUSED_PARAMETER +// !WITH_NEW_INFERENCE interface JPAEntityClass { fun T.findByName(s: String): D {null!!} diff --git a/compiler/testData/diagnostics/tests/extensions/extensionMemberInClassObject.kt b/compiler/testData/diagnostics/tests/extensions/extensionMemberInClassObject.kt index 5b5862e9dae..5c47ae920f3 100644 --- a/compiler/testData/diagnostics/tests/extensions/extensionMemberInClassObject.kt +++ b/compiler/testData/diagnostics/tests/extensions/extensionMemberInClassObject.kt @@ -1,4 +1,5 @@ // !DIAGNOSTICS: -UNUSED_PARAMETER +// !WITH_NEW_INFERENCE interface JPAEntityClass { fun T.findByName(s: String): D {null!!} @@ -9,7 +10,7 @@ class Foo { } fun main() { - with("", { + with("", { Foo.findByName("") }) with(Foo) { diff --git a/compiler/testData/diagnostics/tests/generics/projectionsScope/extensionReceiverTypeMismatch.kt b/compiler/testData/diagnostics/tests/generics/projectionsScope/extensionReceiverTypeMismatch.kt index a8ef0bc1f95..6332cbb4b9c 100644 --- a/compiler/testData/diagnostics/tests/generics/projectionsScope/extensionReceiverTypeMismatch.kt +++ b/compiler/testData/diagnostics/tests/generics/projectionsScope/extensionReceiverTypeMismatch.kt @@ -6,12 +6,12 @@ class A { class Out fun test(x: A, y: Out) { - with(x) { + with(x) { // TODO: this diagnostic could be replaced with TYPE_MISMATCH_DUE_TO_TYPE_PROJECTION "".foo() y.bar() - with(y) { + with(y) { bar() } } diff --git a/compiler/testData/diagnostics/tests/inference/coercionToUnit/coersionWithAnonymousFunctionsAndUnresolved.fir.kt b/compiler/testData/diagnostics/tests/inference/coercionToUnit/coersionWithAnonymousFunctionsAndUnresolved.fir.kt new file mode 100644 index 00000000000..2dc485f8c82 --- /dev/null +++ b/compiler/testData/diagnostics/tests/inference/coercionToUnit/coersionWithAnonymousFunctionsAndUnresolved.fir.kt @@ -0,0 +1,74 @@ +// !DIAGNOSTICS: -UNUSED_PARAMETER +// !WITH_NEW_INFERENCE + +fun takeFnToAny(fn: () -> Any) {} +fun takeFnToUnit(fn: () -> Unit) {} +fun

takeFnToParameter(fn: () -> P) {} + +fun testAny() { + takeFnToAny { } + takeFnToAny { Unit } + takeFnToAny { unresolved() } + takeFnToAny { if (true) unresolved() } + takeFnToAny { if (true) unresolved() else unresolved() } + takeFnToAny(fun() = Unit) + takeFnToAny(fun() {}) + takeFnToAny(fun() { return }) + takeFnToAny(fun() { return Unit }) + takeFnToAny(fun(): Unit {}) + takeFnToAny(fun(): Unit { return }) + takeFnToAny(fun(): Unit { return Unit }) + takeFnToAny(fun() { if (true) return }) + takeFnToAny(fun() { if (true) return Unit }) + takeFnToAny(fun() = unresolved()) + takeFnToAny(fun() { unresolved() }) + takeFnToAny(fun(): Unit { unresolved() }) + takeFnToAny(fun() { return unresolved() }) + takeFnToAny(fun() { if (true ) return unresolved() }) +} + +fun testUnit() { + takeFnToUnit { } + takeFnToUnit { Unit } + takeFnToUnit { unresolved() } + takeFnToUnit { if (true) unresolved() } + takeFnToUnit { if (true) unresolved() else unresolved() } + takeFnToUnit(fun() = Unit) + takeFnToUnit(fun() {}) + takeFnToUnit(fun() { return }) + takeFnToUnit(fun() { return Unit }) + takeFnToUnit(fun(): Unit {}) + takeFnToUnit(fun(): Unit { return }) + takeFnToUnit(fun(): Unit { return Unit }) + takeFnToUnit(fun() { if (true) return }) + takeFnToUnit(fun() { if (true) return Unit }) + takeFnToUnit(fun() = unresolved()) + takeFnToUnit(fun() { unresolved() }) + takeFnToUnit(fun(): Unit { unresolved() }) + takeFnToUnit(fun() { return unresolved() }) + takeFnToUnit(fun() { if (true ) return unresolved() }) +} + +fun testParameter() { + takeFnToParameter { } + takeFnToParameter { Unit } + takeFnToParameter { unresolved() } + takeFnToParameter { if (true) unresolved() } + takeFnToParameter { + if (true) unresolved() else unresolved() + } + takeFnToParameter(fun() = Unit) + takeFnToParameter(fun() {}) + takeFnToParameter(fun() { return }) + takeFnToParameter(fun() { return Unit }) + takeFnToParameter(fun(): Unit {}) + takeFnToParameter(fun(): Unit { return }) + takeFnToParameter(fun(): Unit { return Unit }) + takeFnToParameter(fun() { if (true) return }) + takeFnToParameter(fun() { if (true) return Unit }) + takeFnToParameter(fun() = unresolved()) + takeFnToParameter(fun() { unresolved() }) + takeFnToParameter(fun(): Unit { unresolved() }) + takeFnToParameter(fun() { return unresolved() }) + takeFnToParameter(fun() { if (true ) return unresolved() }) +} diff --git a/compiler/testData/diagnostics/tests/inference/coercionToUnit/coersionWithAnonymousFunctionsAndUnresolved.kt b/compiler/testData/diagnostics/tests/inference/coercionToUnit/coersionWithAnonymousFunctionsAndUnresolved.kt new file mode 100644 index 00000000000..58f47c156fd --- /dev/null +++ b/compiler/testData/diagnostics/tests/inference/coercionToUnit/coersionWithAnonymousFunctionsAndUnresolved.kt @@ -0,0 +1,74 @@ +// !DIAGNOSTICS: -UNUSED_PARAMETER +// !WITH_NEW_INFERENCE + +fun takeFnToAny(fn: () -> Any) {} +fun takeFnToUnit(fn: () -> Unit) {} +fun

takeFnToParameter(fn: () -> P) {} + +fun testAny() { + takeFnToAny { } + takeFnToAny { Unit } + takeFnToAny { unresolved() } + takeFnToAny { if (true) unresolved() } + takeFnToAny { if (true) unresolved() else unresolved() } + takeFnToAny(fun() = Unit) + takeFnToAny(fun() {}) + takeFnToAny(fun() { return }) + takeFnToAny(fun() { return Unit }) + takeFnToAny(fun(): Unit {}) + takeFnToAny(fun(): Unit { return }) + takeFnToAny(fun(): Unit { return Unit }) + takeFnToAny(fun() { if (true) return }) + takeFnToAny(fun() { if (true) return Unit }) + takeFnToAny(fun() = unresolved()) + takeFnToAny(fun() { unresolved() }) + takeFnToAny(fun(): Unit { unresolved() }) + takeFnToAny(fun() { return unresolved() }) + takeFnToAny(fun() { if (true ) return unresolved() }) +} + +fun testUnit() { + takeFnToUnit { } + takeFnToUnit { Unit } + takeFnToUnit { unresolved() } + takeFnToUnit { if (true) unresolved() } + takeFnToUnit { if (true) unresolved() else unresolved() } + takeFnToUnit(fun() = Unit) + takeFnToUnit(fun() {}) + takeFnToUnit(fun() { return }) + takeFnToUnit(fun() { return Unit }) + takeFnToUnit(fun(): Unit {}) + takeFnToUnit(fun(): Unit { return }) + takeFnToUnit(fun(): Unit { return Unit }) + takeFnToUnit(fun() { if (true) return }) + takeFnToUnit(fun() { if (true) return Unit }) + takeFnToUnit(fun() = unresolved()) + takeFnToUnit(fun() { unresolved() }) + takeFnToUnit(fun(): Unit { unresolved() }) + takeFnToUnit(fun() { return unresolved() }) + takeFnToUnit(fun() { if (true ) return unresolved() }) +} + +fun testParameter() { + takeFnToParameter { } + takeFnToParameter { Unit } + takeFnToParameter { unresolved() } + takeFnToParameter { if (true) unresolved() } + takeFnToParameter { + if (true) unresolved() else unresolved() + } + takeFnToParameter(fun() = Unit) + takeFnToParameter(fun() {}) + takeFnToParameter(fun() { return }) + takeFnToParameter(fun() { return Unit }) + takeFnToParameter(fun(): Unit {}) + takeFnToParameter(fun(): Unit { return }) + takeFnToParameter(fun(): Unit { return Unit }) + takeFnToParameter(fun() { if (true) return }) + takeFnToParameter(fun() { if (true) return Unit }) + takeFnToParameter(fun() = unresolved()) + takeFnToParameter(fun() { unresolved() }) + takeFnToParameter(fun(): Unit { unresolved() }) + takeFnToParameter(fun() { return unresolved() }) + takeFnToParameter(fun() { if (true ) return unresolved() }) +} diff --git a/compiler/testData/diagnostics/tests/inference/coercionToUnit/coersionWithAnonymousFunctionsAndUnresolved.txt b/compiler/testData/diagnostics/tests/inference/coercionToUnit/coersionWithAnonymousFunctionsAndUnresolved.txt new file mode 100644 index 00000000000..99c8b182b8d --- /dev/null +++ b/compiler/testData/diagnostics/tests/inference/coercionToUnit/coersionWithAnonymousFunctionsAndUnresolved.txt @@ -0,0 +1,8 @@ +package + +public fun takeFnToAny(/*0*/ fn: () -> kotlin.Any): kotlin.Unit +public fun takeFnToParameter(/*0*/ fn: () -> P): kotlin.Unit +public fun takeFnToUnit(/*0*/ fn: () -> kotlin.Unit): kotlin.Unit +public fun testAny(): kotlin.Unit +public fun testParameter(): kotlin.Unit +public fun testUnit(): kotlin.Unit diff --git a/compiler/testData/diagnostics/tests/inference/kt28654.kt b/compiler/testData/diagnostics/tests/inference/kt28654.kt index 46e7e16afb2..fd601d32661 100644 --- a/compiler/testData/diagnostics/tests/inference/kt28654.kt +++ b/compiler/testData/diagnostics/tests/inference/kt28654.kt @@ -2,7 +2,7 @@ // !DIAGNOSTICS: -UNUSED_VARIABLE // Related issue: KT-28654 -fun select(): K = run { } +fun select(): K = run { } fun test() { val x: Int = select() diff --git a/compiler/testData/diagnostics/tests/inference/recursiveCalls/kt23531.kt b/compiler/testData/diagnostics/tests/inference/recursiveCalls/kt23531.kt index 68eeafcea57..d95cba78e04 100644 --- a/compiler/testData/diagnostics/tests/inference/recursiveCalls/kt23531.kt +++ b/compiler/testData/diagnostics/tests/inference/recursiveCalls/kt23531.kt @@ -13,7 +13,7 @@ fun insideJob1() = doTheJob1() suspend fun insideJob2() = doTheJob2() suspend fun insideJob3() = doTheJob3() -fun doTheJob0() = simpleAsync0 { insideJob0() } -fun doTheJob1() = simpleAsync1 { insideJob1() } -suspend fun doTheJob2() = simpleAsync2 { insideJob2() } -suspend fun doTheJob3() = simpleAsync3 { insideJob3() } +fun doTheJob0() = simpleAsync0 { insideJob0() } +fun doTheJob1() = simpleAsync1 { insideJob1() } +suspend fun doTheJob2() = simpleAsync2 { insideJob2() } +suspend fun doTheJob3() = simpleAsync3 { insideJob3() } diff --git a/compiler/testData/diagnostics/tests/inference/regressions/kt2741.fir.kt b/compiler/testData/diagnostics/tests/inference/regressions/kt2741.fir.kt index f08cf948b9b..6528c36d735 100644 --- a/compiler/testData/diagnostics/tests/inference/regressions/kt2741.fir.kt +++ b/compiler/testData/diagnostics/tests/inference/regressions/kt2741.fir.kt @@ -1,4 +1,6 @@ //KT-2741 Compiler can't infer a type of a function literal parameter when its body contains errors +// !WITH_NEW_INFERENCE + package a fun > Iterable._sortBy(f: (T) -> R): List = throw Exception() diff --git a/compiler/testData/diagnostics/tests/inference/regressions/kt2741.kt b/compiler/testData/diagnostics/tests/inference/regressions/kt2741.kt index 3134d451006..2a0ce85fd4b 100644 --- a/compiler/testData/diagnostics/tests/inference/regressions/kt2741.kt +++ b/compiler/testData/diagnostics/tests/inference/regressions/kt2741.kt @@ -1,4 +1,6 @@ //KT-2741 Compiler can't infer a type of a function literal parameter when its body contains errors +// !WITH_NEW_INFERENCE + package a fun > Iterable._sortBy(f: (T) -> R): List = throw Exception() @@ -7,5 +9,5 @@ fun _arrayList(vararg values: T) : List = throw Ex class _Pair(val a: A) fun test() { - _arrayList(_Pair(1))._sortBy { it -> xxx } + _arrayList(_Pair(1))._sortBy { it -> xxx } } diff --git a/compiler/testData/diagnostics/tests/inference/regressions/kt2841.fir.kt b/compiler/testData/diagnostics/tests/inference/regressions/kt2841.fir.kt index 1864a243328..8fe0c9ffc98 100644 --- a/compiler/testData/diagnostics/tests/inference/regressions/kt2841.fir.kt +++ b/compiler/testData/diagnostics/tests/inference/regressions/kt2841.fir.kt @@ -1,3 +1,5 @@ +// !WITH_NEW_INFERENCE + package a interface Closeable {} diff --git a/compiler/testData/diagnostics/tests/inference/regressions/kt2841.kt b/compiler/testData/diagnostics/tests/inference/regressions/kt2841.kt index a0a226dd8a7..f90b960a5d3 100644 --- a/compiler/testData/diagnostics/tests/inference/regressions/kt2841.kt +++ b/compiler/testData/diagnostics/tests/inference/regressions/kt2841.kt @@ -1,3 +1,5 @@ +// !WITH_NEW_INFERENCE + package a interface Closeable {} @@ -8,7 +10,7 @@ public inline fun T.use1(block: (T)-> R) : R { } fun main() { - C().use1 { + C().use1 { w -> // ERROR here x } diff --git a/compiler/testData/diagnostics/tests/inference/regressions/kt2841_it.fir.kt b/compiler/testData/diagnostics/tests/inference/regressions/kt2841_it.fir.kt index 71a2754783b..1e406e58d0d 100644 --- a/compiler/testData/diagnostics/tests/inference/regressions/kt2841_it.fir.kt +++ b/compiler/testData/diagnostics/tests/inference/regressions/kt2841_it.fir.kt @@ -1,3 +1,5 @@ +// !WITH_NEW_INFERENCE + package a interface Closeable { diff --git a/compiler/testData/diagnostics/tests/inference/regressions/kt2841_it.kt b/compiler/testData/diagnostics/tests/inference/regressions/kt2841_it.kt index 71a2754783b..ea9c0fdbe08 100644 --- a/compiler/testData/diagnostics/tests/inference/regressions/kt2841_it.kt +++ b/compiler/testData/diagnostics/tests/inference/regressions/kt2841_it.kt @@ -1,3 +1,5 @@ +// !WITH_NEW_INFERENCE + package a interface Closeable { @@ -11,7 +13,7 @@ public inline fun T.use(block: (t: T)-> R) : R { } fun test() { - C().use { + C().use { it.close() x } diff --git a/compiler/testData/diagnostics/tests/inference/regressions/kt2841_it_this.fir.kt b/compiler/testData/diagnostics/tests/inference/regressions/kt2841_it_this.fir.kt index 0ddd3367e39..6c635f87ad7 100644 --- a/compiler/testData/diagnostics/tests/inference/regressions/kt2841_it_this.fir.kt +++ b/compiler/testData/diagnostics/tests/inference/regressions/kt2841_it_this.fir.kt @@ -1,3 +1,5 @@ +// !WITH_NEW_INFERENCE + package a interface Closeable { diff --git a/compiler/testData/diagnostics/tests/inference/regressions/kt2841_it_this.kt b/compiler/testData/diagnostics/tests/inference/regressions/kt2841_it_this.kt index 0ddd3367e39..fdc07d55efa 100644 --- a/compiler/testData/diagnostics/tests/inference/regressions/kt2841_it_this.kt +++ b/compiler/testData/diagnostics/tests/inference/regressions/kt2841_it_this.kt @@ -1,3 +1,5 @@ +// !WITH_NEW_INFERENCE + package a interface Closeable { @@ -11,7 +13,7 @@ public inline fun use(t: T, block: T.(T)-> R) : R { } fun test() { - use(C()) { + use(C()) { this.close() it.close() xx diff --git a/compiler/testData/diagnostics/tests/inference/regressions/kt2841_this.fir.kt b/compiler/testData/diagnostics/tests/inference/regressions/kt2841_this.fir.kt index ad85125cb40..116a2269643 100644 --- a/compiler/testData/diagnostics/tests/inference/regressions/kt2841_this.fir.kt +++ b/compiler/testData/diagnostics/tests/inference/regressions/kt2841_this.fir.kt @@ -1,3 +1,5 @@ +// !WITH_NEW_INFERENCE + package a interface Closeable { diff --git a/compiler/testData/diagnostics/tests/inference/regressions/kt2841_this.kt b/compiler/testData/diagnostics/tests/inference/regressions/kt2841_this.kt index ad85125cb40..95c45ed9824 100644 --- a/compiler/testData/diagnostics/tests/inference/regressions/kt2841_this.kt +++ b/compiler/testData/diagnostics/tests/inference/regressions/kt2841_this.kt @@ -1,3 +1,5 @@ +// !WITH_NEW_INFERENCE + package a interface Closeable { @@ -11,7 +13,7 @@ public inline fun T.use(block: T.()-> R) : R { } fun test() { - C().use { + C().use { this.close() x } diff --git a/compiler/testData/diagnostics/tests/inference/reportingImprovements/NoAmbiguityForDifferentFunctionTypes.fir.kt b/compiler/testData/diagnostics/tests/inference/reportingImprovements/NoAmbiguityForDifferentFunctionTypes.fir.kt index 1a875004b90..ef8f4514c20 100644 --- a/compiler/testData/diagnostics/tests/inference/reportingImprovements/NoAmbiguityForDifferentFunctionTypes.fir.kt +++ b/compiler/testData/diagnostics/tests/inference/reportingImprovements/NoAmbiguityForDifferentFunctionTypes.fir.kt @@ -1,3 +1,5 @@ +// !WITH_NEW_INFERENCE + package a interface Closeable {} diff --git a/compiler/testData/diagnostics/tests/inference/reportingImprovements/NoAmbiguityForDifferentFunctionTypes.kt b/compiler/testData/diagnostics/tests/inference/reportingImprovements/NoAmbiguityForDifferentFunctionTypes.kt index fef171d9fb0..2754ed2d2c0 100644 --- a/compiler/testData/diagnostics/tests/inference/reportingImprovements/NoAmbiguityForDifferentFunctionTypes.kt +++ b/compiler/testData/diagnostics/tests/inference/reportingImprovements/NoAmbiguityForDifferentFunctionTypes.kt @@ -1,3 +1,5 @@ +// !WITH_NEW_INFERENCE + package a interface Closeable {} @@ -8,7 +10,7 @@ fun T.foo(block: (T)-> R) = block fun T.foo(block: (T, T)-> R) = block fun main() { - C().foo { // no ambiguity here + C().foo { // no ambiguity here www -> xs } diff --git a/compiler/testData/diagnostics/tests/regressions/kt30245.kt b/compiler/testData/diagnostics/tests/regressions/kt30245.kt index 3cb29c2483b..4eaa2e67876 100644 --- a/compiler/testData/diagnostics/tests/regressions/kt30245.kt +++ b/compiler/testData/diagnostics/tests/regressions/kt30245.kt @@ -79,7 +79,7 @@ fun test2() { // to extension lambda 1 // val i27: E1 = id { i, s: String -> i + s.length } // overload oi- ni- val w28 = W2 { i: Int, s -> i + s.length } // oi- ni- - val i28: E1 = id { i: Int, s -> i + s.length } // oi- ni- + val i28: E1 = id { i: Int, s -> i + s.length } // oi- ni- val w29 = W2 { i: Int, s: String -> i + s.length } // oi- ni- val i29: E1 = id { i: Int, s: String -> i + s.length } // oi+ ni+ diff --git a/compiler/testData/diagnostics/tests/resolve/invoke/wrongInvokeExtension.fir.kt b/compiler/testData/diagnostics/tests/resolve/invoke/wrongInvokeExtension.fir.kt index 710bd3fb7ba..840f30c16fe 100644 --- a/compiler/testData/diagnostics/tests/resolve/invoke/wrongInvokeExtension.fir.kt +++ b/compiler/testData/diagnostics/tests/resolve/invoke/wrongInvokeExtension.fir.kt @@ -1,3 +1,5 @@ +// !WITH_NEW_INFERENCE + class B class A { diff --git a/compiler/testData/diagnostics/tests/resolve/invoke/wrongInvokeExtension.kt b/compiler/testData/diagnostics/tests/resolve/invoke/wrongInvokeExtension.kt index 86df9c03ce8..ef06d8b9456 100644 --- a/compiler/testData/diagnostics/tests/resolve/invoke/wrongInvokeExtension.kt +++ b/compiler/testData/diagnostics/tests/resolve/invoke/wrongInvokeExtension.kt @@ -1,3 +1,5 @@ +// !WITH_NEW_INFERENCE + class B class A { @@ -11,7 +13,7 @@ fun test(a: A, b: B) { b.(a)() - with(b) { + with(b) { val y: Int = a() (a)() } diff --git a/compiler/testData/diagnostics/tests/resolve/newLineLambda.kt b/compiler/testData/diagnostics/tests/resolve/newLineLambda.kt index ce7aabeeee6..6636c894309 100644 --- a/compiler/testData/diagnostics/tests/resolve/newLineLambda.kt +++ b/compiler/testData/diagnostics/tests/resolve/newLineLambda.kt @@ -104,9 +104,9 @@ fun testTwoLambdas() { twoLambdaArgs({}) {} {} - } else { + } else { {} - } + } } } diff --git a/compiler/testData/diagnostics/testsWithStdLib/resolve/hidesMembers.fir.kt b/compiler/testData/diagnostics/testsWithStdLib/resolve/hidesMembers.fir.kt index db29f51110a..17ace407e31 100644 --- a/compiler/testData/diagnostics/testsWithStdLib/resolve/hidesMembers.fir.kt +++ b/compiler/testData/diagnostics/testsWithStdLib/resolve/hidesMembers.fir.kt @@ -1,5 +1,6 @@ // !CHECK_TYPE // !DIAGNOSTICS: -UNUSED_EXPRESSION -UNUSED_PARAMETER -UNUSED_VARIABLE +// !WITH_NEW_INFERENCE // FILE: 2.kt package b diff --git a/compiler/testData/diagnostics/testsWithStdLib/resolve/hidesMembers.kt b/compiler/testData/diagnostics/testsWithStdLib/resolve/hidesMembers.kt index a7a2c731369..40b8ed86d6b 100644 --- a/compiler/testData/diagnostics/testsWithStdLib/resolve/hidesMembers.kt +++ b/compiler/testData/diagnostics/testsWithStdLib/resolve/hidesMembers.kt @@ -1,5 +1,6 @@ // !CHECK_TYPE // !DIAGNOSTICS: -UNUSED_EXPRESSION -UNUSED_PARAMETER -UNUSED_VARIABLE +// !WITH_NEW_INFERENCE // FILE: 2.kt package b @@ -41,7 +42,7 @@ fun test(a: A) { a.forEach("") - with(a) { + with(a) { forEach() checkType { _() } forEach(1) checkType { _() } diff --git a/compiler/testData/diagnostics/testsWithStdLib/resolve/hidesMembers2.fir.kt b/compiler/testData/diagnostics/testsWithStdLib/resolve/hidesMembers2.fir.kt index 6d0bf09ce25..09624f556de 100644 --- a/compiler/testData/diagnostics/testsWithStdLib/resolve/hidesMembers2.fir.kt +++ b/compiler/testData/diagnostics/testsWithStdLib/resolve/hidesMembers2.fir.kt @@ -1,5 +1,7 @@ // !CHECK_TYPE // !DIAGNOSTICS: -UNUSED_EXPRESSION -UNUSED_PARAMETER -UNUSED_VARIABLE +// !WITH_NEW_INFERENCE + class A { fun forEach() = this fun forEach(i: Int) = this diff --git a/compiler/testData/diagnostics/testsWithStdLib/resolve/hidesMembers2.kt b/compiler/testData/diagnostics/testsWithStdLib/resolve/hidesMembers2.kt index f32a50b10df..7569b320870 100644 --- a/compiler/testData/diagnostics/testsWithStdLib/resolve/hidesMembers2.kt +++ b/compiler/testData/diagnostics/testsWithStdLib/resolve/hidesMembers2.kt @@ -1,5 +1,7 @@ // !CHECK_TYPE // !DIAGNOSTICS: -UNUSED_EXPRESSION -UNUSED_PARAMETER -UNUSED_VARIABLE +// !WITH_NEW_INFERENCE + class A { fun forEach() = this fun forEach(i: Int) = this @@ -35,7 +37,7 @@ fun test2(a: A) { a.forEach() checkType { _() } a.forEach(1) - with(a) { + with(a) { forEach() checkType { _() } forEach(1) } diff --git a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java index f91b807dda1..1939d432f3b 100644 --- a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java @@ -10378,6 +10378,11 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTest { runTest("compiler/testData/diagnostics/tests/inference/coercionToUnit/coercionWithoutExpectedType.kt"); } + @TestMetadata("coersionWithAnonymousFunctionsAndUnresolved.kt") + public void testCoersionWithAnonymousFunctionsAndUnresolved() throws Exception { + runTest("compiler/testData/diagnostics/tests/inference/coercionToUnit/coersionWithAnonymousFunctionsAndUnresolved.kt"); + } + @TestMetadata("indirectCoercionWithExpectedType.kt") public void testIndirectCoercionWithExpectedType() throws Exception { runTest("compiler/testData/diagnostics/tests/inference/coercionToUnit/indirectCoercionWithExpectedType.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsUsingJavacTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsUsingJavacTestGenerated.java index d189eb5be74..f30ce340fbd 100644 --- a/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsUsingJavacTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsUsingJavacTestGenerated.java @@ -10373,6 +10373,11 @@ public class DiagnosticsUsingJavacTestGenerated extends AbstractDiagnosticsUsing runTest("compiler/testData/diagnostics/tests/inference/coercionToUnit/coercionWithoutExpectedType.kt"); } + @TestMetadata("coersionWithAnonymousFunctionsAndUnresolved.kt") + public void testCoersionWithAnonymousFunctionsAndUnresolved() throws Exception { + runTest("compiler/testData/diagnostics/tests/inference/coercionToUnit/coersionWithAnonymousFunctionsAndUnresolved.kt"); + } + @TestMetadata("indirectCoercionWithExpectedType.kt") public void testIndirectCoercionWithExpectedType() throws Exception { runTest("compiler/testData/diagnostics/tests/inference/coercionToUnit/indirectCoercionWithExpectedType.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java index 97caa7c9b40..b1343881a2e 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java @@ -14715,11 +14715,6 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes @TestDataPath("$PROJECT_ROOT") @RunWith(JUnit3RunnerWithInners.class) public static class NotNullAssertions extends AbstractLightAnalysisModeTest { - @TestMetadata("paramAssertionMessage.kt") - public void ignoreParamAssertionMessage() throws Exception { - runTest("compiler/testData/codegen/box/javaInterop/notNullAssertions/paramAssertionMessage.kt"); - } - private void runTest(String testDataFilePath) throws Exception { KotlinTestUtils.runTest(this::doTest, TargetBackend.JVM, testDataFilePath); } @@ -14808,6 +14803,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes runTest("compiler/testData/codegen/box/javaInterop/notNullAssertions/nullableTypeParameter.kt"); } + @TestMetadata("paramAssertionMessage.kt") + public void testParamAssertionMessage() throws Exception { + runTest("compiler/testData/codegen/box/javaInterop/notNullAssertions/paramAssertionMessage.kt"); + } + @TestMetadata("staticCallErrorMessage.kt") public void testStaticCallErrorMessage() throws Exception { runTest("compiler/testData/codegen/box/javaInterop/notNullAssertions/staticCallErrorMessage.kt"); diff --git a/idea/src/org/jetbrains/kotlin/idea/inspections/collections/FunctionUtils.kt b/idea/src/org/jetbrains/kotlin/idea/inspections/collections/FunctionUtils.kt index 366f9483224..07a1a29b938 100644 --- a/idea/src/org/jetbrains/kotlin/idea/inspections/collections/FunctionUtils.kt +++ b/idea/src/org/jetbrains/kotlin/idea/inspections/collections/FunctionUtils.kt @@ -73,7 +73,7 @@ fun ResolvedCall<*>.hasLastFunctionalParameterWithResult(context: BindingContext if (this is NewResolvedCallImpl<*>) { // TODO: looks like hack resolvedCallAtom.subResolvedAtoms?.firstOrNull { it is ResolvedLambdaAtom }.safeAs()?.let { lambdaAtom -> - return lambdaAtom.resultArguments.filterIsInstance().all { + return lambdaAtom.resultArgumentsInfo.nonErrorArguments.filterIsInstance().all { val type = it.receiverValue?.type ?: return@all false predicate(type) }