From 4c56962678bc4678403cb65d561a684a79ec3a9e Mon Sep 17 00:00:00 2001 From: Victor Petukhov Date: Thu, 24 Dec 2020 12:43:41 +0300 Subject: [PATCH] Report errors on callable references which contains postponed type variables in the receiver type --- .../jetbrains/kotlin/diagnostics/Errors.java | 1 + .../rendering/DefaultErrorMessages.java | 1 + .../calls/tower/ResolvedAtomCompleter.kt | 10 + .../DoubleColonExpressionResolver.kt | 19 +- .../specialCallsWithCallableReferences.kt | 113 ++++ .../specialCallsWithLambdas.kt | 208 ++++++++ .../specialCallsWithCallableReferences.fir.kt | 499 ++++++++++++++++++ .../specialCallsWithCallableReferences.kt | 499 ++++++++++++++++++ .../specialCallsWithLambdas.fir.kt | 195 +++++++ .../specialCallsWithLambdas.kt | 195 +++++++ .../specialCallsWithCallableReferences.fir.kt | 18 +- .../codegen/BlackBoxCodegenTestGenerated.java | 10 + 12 files changed, 1753 insertions(+), 15 deletions(-) create mode 100644 compiler/testData/codegen/box/inference/builderInference/specialCallsWithCallableReferences.kt create mode 100644 compiler/testData/codegen/box/inference/builderInference/specialCallsWithLambdas.kt create mode 100644 compiler/testData/diagnostics/tests/inference/builderInference/specialCallsWithCallableReferences.fir.kt create mode 100644 compiler/testData/diagnostics/tests/inference/builderInference/specialCallsWithCallableReferences.kt create mode 100644 compiler/testData/diagnostics/tests/inference/builderInference/specialCallsWithLambdas.fir.kt create mode 100644 compiler/testData/diagnostics/tests/inference/builderInference/specialCallsWithLambdas.kt diff --git a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java index 9a935e80ece..6c449bc8fc9 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java @@ -803,6 +803,7 @@ public interface Errors { DiagnosticFactory1 TYPE_INFERENCE_UPPER_BOUND_VIOLATED = DiagnosticFactory1.create(ERROR); DiagnosticFactory2 TYPE_INFERENCE_EXPECTED_TYPE_MISMATCH = DiagnosticFactory2.create(ERROR); DiagnosticFactory0 TYPE_INFERENCE_CANDIDATE_WITH_SAM_AND_VARARG = DiagnosticFactory0.create(WARNING); + DiagnosticFactory0 TYPE_INFERENCE_POSTPONED_VARIABLE_IN_RECEIVER_TYPE = DiagnosticFactory0.create(ERROR); DiagnosticFactory0 TYPE_INFERENCE_FAILED_ON_SPECIAL_CONSTRUCT = DiagnosticFactory0.create(ERROR, SPECIAL_CONSTRUCT_TOKEN); diff --git a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/rendering/DefaultErrorMessages.java b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/rendering/DefaultErrorMessages.java index 6f93022f687..4d5c0410f94 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/rendering/DefaultErrorMessages.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/rendering/DefaultErrorMessages.java @@ -899,6 +899,7 @@ public class DefaultErrorMessages { MAP.put(TYPE_INFERENCE_UPPER_BOUND_VIOLATED, "{0}", TYPE_INFERENCE_UPPER_BOUND_VIOLATED_RENDERER); MAP.put(TYPE_INFERENCE_EXPECTED_TYPE_MISMATCH, "Type inference failed. Expected type mismatch: inferred type is {1} but {0} was expected", RENDER_TYPE, RENDER_TYPE); MAP.put(TYPE_INFERENCE_CANDIDATE_WITH_SAM_AND_VARARG, "Please use spread operator to pass an array as vararg. It will be an error in 1.5."); + MAP.put(TYPE_INFERENCE_POSTPONED_VARIABLE_IN_RECEIVER_TYPE, "Postponed type variable (type variable of the builder inference) can't be used in the receiver type. Use a member function instead of extension one or specify type arguments of a function which uses the builder inference, explicitly."); MAP.put(TYPE_INFERENCE_FAILED_ON_SPECIAL_CONSTRUCT, "Type inference for control flow expression failed. Please specify its type explicitly."); 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 8cad98480c8..08569c1d1f5 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 @@ -11,6 +11,8 @@ import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.descriptors.impl.FunctionDescriptorImpl import org.jetbrains.kotlin.descriptors.impl.ReceiverParameterDescriptorImpl import org.jetbrains.kotlin.descriptors.impl.ValueParameterDescriptorImpl +import org.jetbrains.kotlin.diagnostics.Errors +import org.jetbrains.kotlin.diagnostics.reportDiagnosticOnce import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.resolve.BindingTrace @@ -44,6 +46,7 @@ import org.jetbrains.kotlin.types.expressions.DoubleColonExpressionResolver import org.jetbrains.kotlin.types.expressions.ExpressionTypingServices import org.jetbrains.kotlin.types.expressions.typeInfoFactory.createTypeInfo import org.jetbrains.kotlin.types.typeUtil.asTypeProjection +import org.jetbrains.kotlin.types.typeUtil.contains import org.jetbrains.kotlin.types.typeUtil.isUnit import org.jetbrains.kotlin.types.typeUtil.shouldBeSubstituted import org.jetbrains.kotlin.utils.addToStdlib.safeAs @@ -423,6 +426,13 @@ class ResolvedAtomCompleter( else -> null } + val rawExtensionReceiver = callableCandidate.extensionReceiver + + if (rawExtensionReceiver != null && rawExtensionReceiver.receiver.receiverValue.type.contains { it is StubType }) { + topLevelTrace.reportDiagnosticOnce(Errors.TYPE_INFERENCE_POSTPONED_VARIABLE_IN_RECEIVER_TYPE.on(callableReferenceExpression)) + return + } + // For some callable references we can already have recorder descriptor (see `DoubleColonExpressionResolver.getCallableReferenceType`) val resultTypeInfo = if (recorderDescriptor != null) { extractCallableReferenceResultTypeInfoFromDescriptor(callableCandidate, recorderDescriptor) diff --git a/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/DoubleColonExpressionResolver.kt b/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/DoubleColonExpressionResolver.kt index 2f2a5942567..604a8d18588 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/DoubleColonExpressionResolver.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/DoubleColonExpressionResolver.kt @@ -15,8 +15,8 @@ import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.descriptors.annotations.Annotations import org.jetbrains.kotlin.descriptors.impl.AnonymousFunctionDescriptor import org.jetbrains.kotlin.descriptors.impl.LocalVariableDescriptor -import org.jetbrains.kotlin.diagnostics.Errors import org.jetbrains.kotlin.diagnostics.Errors.* +import org.jetbrains.kotlin.diagnostics.reportDiagnosticOnce import org.jetbrains.kotlin.lexer.KtTokens import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.psi.* @@ -49,6 +49,7 @@ import org.jetbrains.kotlin.types.TypeUtils.NO_EXPECTED_TYPE import org.jetbrains.kotlin.types.checker.KotlinTypeRefiner import org.jetbrains.kotlin.types.expressions.FunctionWithBigAritySupport.LanguageVersionDependent import org.jetbrains.kotlin.types.expressions.typeInfoFactory.createTypeInfo +import org.jetbrains.kotlin.types.expressions.typeInfoFactory.noTypeInfo import org.jetbrains.kotlin.types.refinement.TypeRefinement import org.jetbrains.kotlin.types.typeUtil.* import org.jetbrains.kotlin.utils.yieldIfNotNull @@ -540,6 +541,16 @@ class DoubleColonExpressionResolver( val (lhs, resolutionResults) = resolveCallableReference(expression, c, ResolveArgumentsMode.RESOLVE_FUNCTION_ARGUMENTS) val result = getCallableReferenceType(expression, lhs, resolutionResults, c) + val doesSomeExtensionReceiverContainsStubType = + resolutionResults != null && resolutionResults.resultingCalls.any { resolvedCall -> + resolvedCall.extensionReceiver?.type?.contains { it is StubType } == true + } + + if (doesSomeExtensionReceiverContainsStubType) { + c.trace.reportDiagnosticOnce(TYPE_INFERENCE_POSTPONED_VARIABLE_IN_RECEIVER_TYPE.on(expression)) + return noTypeInfo(c) + } + val dataFlowInfo = (lhs as? DoubleColonLHS.Expression)?.dataFlowInfo ?: c.dataFlowInfo if (c.inferenceSession is CoroutineInferenceSession && result?.contains { it is StubType } == true) { @@ -637,9 +648,9 @@ class DoubleColonExpressionResolver( bigAritySupport.shouldCheckLanguageVersionSettings && !languageVersionSettings.supportsFeature(LanguageFeature.FunctionTypesWithBigArity) ) { - context.trace.report(Errors.UNSUPPORTED_FEATURE.on( - expression, LanguageFeature.FunctionTypesWithBigArity to languageVersionSettings - )) + context.trace.report( + UNSUPPORTED_FEATURE.on(expression, LanguageFeature.FunctionTypesWithBigArity to languageVersionSettings) + ) } } diff --git a/compiler/testData/codegen/box/inference/builderInference/specialCallsWithCallableReferences.kt b/compiler/testData/codegen/box/inference/builderInference/specialCallsWithCallableReferences.kt new file mode 100644 index 00000000000..343601db436 --- /dev/null +++ b/compiler/testData/codegen/box/inference/builderInference/specialCallsWithCallableReferences.kt @@ -0,0 +1,113 @@ +// WITH_RUNTIME + +import kotlin.experimental.ExperimentalTypeInference + +fun FlowCollector.bar(): K = null as K +fun FlowCollector.foo(): K = null as K + +fun bar2(): Int = 1 +fun foo2(): Float = 1f + +fun materialize() = null as T + +interface FlowCollector {} + +@Suppress("EXPERIMENTAL_API_USAGE_ERROR") +fun flow(@BuilderInference block: suspend FlowCollector.() -> Unit) = Flow(block) + +class Flow(private val block: suspend FlowCollector.() -> Unit) + +fun select(vararg x: R) = x[0] + +fun poll01(): Flow { + return flow { + val inv = select(::bar2, ::foo2) + inv() + } +} + +fun poll1(flag: Boolean): Flow { + return flow { + val inv = if (flag) { ::bar2 } else { ::foo2 } + inv() + } +} + +fun poll11(flag: Boolean): Flow { + return flow { + val inv = if (flag) { ::bar2 } else { ::foo2 } + inv() + } +} + + +fun poll21(flag: Boolean): Flow { + return flow { + val inv = when (flag) { true -> ::bar2 else -> ::foo2 } + inv() + } +} + +fun poll31(flag: Boolean): Flow { + return flow { + val inv = when (flag) { true -> ::bar2 false -> ::foo2 } + inv() + } +} + +fun poll41(): Flow { + return flow { + val inv = try { ::bar2 } finally { ::foo2 } + inv() + } +} + +fun poll51(): Flow { + return flow { + val inv = try { ::bar2 } catch (e: Exception) { ::foo2 } finally { ::foo2 } + inv() + } +} + +fun poll61(): Flow { + return flow { + val inv = ::bar2 + inv + } +} + +fun poll71(): Flow { + return flow { + val inv = ::bar2!! + inv() + } +} + +fun poll81(): Flow { + return flow { + val inv = ::bar2 in setOf(::foo2) + inv + } +} + +fun poll91(): Flow { + return flow { + val inv = ::foo2 in setOf(::foo2) + inv + } +} + +fun box(): String { + poll01() + poll1(true) + poll11(true) + poll21(true) + poll31(true) + poll41() + poll51() + poll61() + poll71() + poll81() + poll91() + return "OK" +} \ No newline at end of file diff --git a/compiler/testData/codegen/box/inference/builderInference/specialCallsWithLambdas.kt b/compiler/testData/codegen/box/inference/builderInference/specialCallsWithLambdas.kt new file mode 100644 index 00000000000..c9a7f6ff984 --- /dev/null +++ b/compiler/testData/codegen/box/inference/builderInference/specialCallsWithLambdas.kt @@ -0,0 +1,208 @@ +// WITH_RUNTIME + +import kotlin.experimental.ExperimentalTypeInference + +interface FlowCollector {} + +@Suppress("EXPERIMENTAL_API_USAGE_ERROR") +fun flow(@BuilderInference block: suspend FlowCollector.() -> Unit) = Flow(block) + +class Flow(private val block: suspend FlowCollector.() -> Unit) + +fun select(vararg x: R) = x[0] + +fun poll0(): Flow { + return flow { + val inv = select({}, {}) + inv() + } +} + +fun poll01(): Flow { + return flow { + val inv = select({ 1 }, { 1f }) + inv() + } +} + +fun poll1(flag: Boolean): Flow { + return flow { + val inv = if (flag) { {} } else { {} } + inv() + } +} + +fun poll11(flag: Boolean): Flow { + return flow { + val inv = if (flag) { { 1 } } else { { 1f } } + inv() + } +} + +fun poll12(flag: Boolean): Flow { + return flow { + val inv = if (flag) ({ }) else ({ }) + inv() + } +} + +fun poll13(flag: Boolean): Flow { + return flow { + val inv = if (flag) ({ 1 }) else ({ 1f }) + inv() + } +} + +fun poll2(flag: Boolean): Flow { + return flow { + val inv = when (flag) { true -> {{}} else -> {{}} } + inv() + } +} + +fun poll21(flag: Boolean): Flow { + return flow { + val inv = when (flag) { true -> {{1}} else -> {{1f}} } + inv() + } +} + +fun poll22(flag: Boolean): Flow { + return flow { + val inv = when (flag) { true -> ({}) else -> ({}) } + inv() + } +} + +fun poll23(flag: Boolean): Flow { + return flow { + val inv = when (flag) { true -> ({1}) else -> ({1f}) } + inv() + } +} + +fun poll4(): Flow { + return flow { + val inv = try { {} } finally { {} } + inv() + } +} + +fun poll41(): Flow { + return flow { + val inv = try { {1} } finally { {1f} } + inv() + } +} + +fun poll42(): Flow { + return flow { + val inv = try { ({1}) } finally { ({1f}) } + inv() + } +} + +fun poll43(): Flow { + return flow { + val inv = try { ({}) } finally { ({}) } + inv() + } +} + +fun poll5(): Flow { + return flow { + val inv = try { {1} } catch (e: Exception) { {1f} } finally { {} } + inv() + } +} + +fun poll7(): Flow { + return flow { + val inv = {}!! + inv() + } +} + +fun poll71(): Flow { + return flow { + val inv = {1f}!! + inv() + } +} + +fun poll72(): Flow { + return flow { + val inv = {{}}!! + inv() + } +} + +fun poll73(): Flow { + return flow { + val inv = ({})!! + inv + } +} + +fun poll81(): Flow { + return flow { + val inv = {} in setOf({}) + inv + } +} + +fun poll82(): Flow { + return flow { + val inv = {{}} in setOf({{}}) + inv + } +} + +fun poll83(): Flow { + return flow { + val inv = {({})} in setOf({({})}) + inv + } +} + +fun poll85(): Flow { + return flow { + val inv = {({"1"})} in setOf({({"1f"})}) + inv + } +} + +fun poll86(): Flow { + return flow { + val inv = {({"1"})}!! in setOf({({"1f"})})!! + inv + } +} + +fun box(): String { + poll0() + poll01() + poll1(true) + poll11(true) + poll12(true) + poll13(true) + poll2(true) + poll21(true) + poll22(true) + poll23(true) + poll4() + poll41() + poll42() + poll43() + poll5() + poll7() + poll71() + poll72() + poll73() + poll81() + poll82() + poll83() + poll85() + poll86() + return "OK" +} diff --git a/compiler/testData/diagnostics/tests/inference/builderInference/specialCallsWithCallableReferences.fir.kt b/compiler/testData/diagnostics/tests/inference/builderInference/specialCallsWithCallableReferences.fir.kt new file mode 100644 index 00000000000..c74674862dc --- /dev/null +++ b/compiler/testData/diagnostics/tests/inference/builderInference/specialCallsWithCallableReferences.fir.kt @@ -0,0 +1,499 @@ +// 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 FlowCollector.bar(): K = null as K +fun FlowCollector.foo(): K = null as K + +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) {} + +val FlowCollector.bar5: K get() = null as K +val FlowCollector.foo5: K get() = null as K + +class Foo6 + +class Foo7 +fun foo7() = null as Foo7 + +interface FlowCollector {} + +fun flow(@BuilderInference block: suspend FlowCollector.() -> Unit) = Flow(block) + +class Flow(private val block: suspend FlowCollector.() -> Unit) + +fun select(vararg x: R) = x[0] + +fun poll0(): Flow { + return flow { + val inv = select(::bar, ::foo) + inv() + } +} + +fun poll01(): Flow { + return flow { + val inv = select(::bar2, ::foo2) + inv() + } +} + +fun poll02(): Flow { + return flow { + val inv = select(::bar3, ::foo3) + inv() + } +} + +fun poll03(): Flow { + return flow { + val inv = select(::bar4, ::foo4) + inv() + } +} + +fun poll04(): Flow { + return flow { + val inv = select(::bar5, ::foo5) + inv + } +} + +fun poll05(): Flow { + return flow { + val inv = select(::Foo6, ::Foo6) + inv + } +} + +fun poll06(): Flow { + return flow { + val inv = select(foo7(), ::Foo7) + inv + } +} + +fun poll1(flag: Boolean): Flow { + return flow { + val inv = if (flag) { ::bar2 } else { ::foo2 } + inv() + } +} + +fun poll11(flag: Boolean): Flow { + return flow { + val inv = if (flag) { ::bar2 } else { ::foo2 } + inv() + } +} + +fun poll12(flag: Boolean): Flow { + return flow { + val inv = if (flag) { ::bar3 } else { ::foo3 } + inv() + } +} + +fun poll13(flag: Boolean): Flow { + return flow { + val inv = if (flag) { ::bar2 } else { ::foo3 } + inv() + } +} + +fun poll14(flag: Boolean): Flow { + return flow { + val inv = if (flag) { ::bar4 } else { ::foo4 } + inv() + } +} + +fun poll15(flag: Boolean): Flow { + return flow { + val inv = if (flag) { ::bar5 } else { ::foo5 } + inv() + } +} + +fun poll16(flag: Boolean): Flow { + return flow { + val inv = if (flag) { ::Foo6 } else { ::Foo6 } + inv() + } +} + +fun poll17(flag: Boolean): Flow { + return flow { + val inv = if (flag) { foo7() } else { ::Foo7 } + inv + } +} + +fun poll2(flag: Boolean): Flow { + return flow { + val inv = when (flag) { true -> ::bar else -> ::foo } + inv() + } +} + +fun poll21(flag: Boolean): Flow { + return flow { + val inv = when (flag) { true -> ::bar2 else -> ::foo2 } + inv() + } +} + +fun poll22(flag: Boolean): Flow { + return flow { + val inv = when (flag) { true -> ::bar3 else -> ::foo3 } + inv() + } +} + +fun poll23(flag: Boolean): Flow { + return flow { + val inv = when (flag) { true -> ::bar4 else -> ::foo4 } + inv() + } +} + +fun poll24(flag: Boolean): Flow { + return flow { + val inv = when (flag) { true -> ::bar5 else -> ::foo5 } + inv + } +} + +fun poll25(flag: Boolean): Flow { + return flow { + val inv = when (flag) { true -> ::Foo6 else -> ::Foo6 } + inv + } +} + +fun poll26(flag: Boolean): Flow { + return flow { + val inv = when (flag) { true -> ::Foo7 false -> foo7() else -> ::Foo7 } + inv + } +} + +fun poll3(flag: Boolean): Flow { + return flow { + val inv = when (flag) { true -> ::bar false -> ::foo } + inv() + } +} + +fun poll31(flag: Boolean): Flow { + return flow { + val inv = when (flag) { true -> ::bar2 false -> ::foo2 } + inv() + } +} + +fun poll32(flag: Boolean): Flow { + return flow { + val inv = when (flag) { true -> ::bar3 false -> ::foo3 } + inv() + } +} + +fun poll33(flag: Boolean): Flow { + return flow { + val inv = when (flag) { true -> ::bar4 false -> ::foo4 } + inv() + } +} + +fun poll34(flag: Boolean): Flow { + return flow { + val inv = when (flag) { true -> ::bar5 false -> ::foo5 } + inv + } +} + +fun poll35(flag: Boolean): Flow { + return flow { + val inv = when (flag) { true -> ::Foo6 false -> ::Foo6 } + inv + } +} + +fun poll36(flag: Boolean): Flow { + return flow { + val inv = when (flag) { true -> ::Foo7 false -> foo7() } + inv + } +} + +fun poll4(): Flow { + return flow { + val inv = try { ::bar } finally { ::foo } + inv() + } +} + +fun poll41(): Flow { + return flow { + val inv = try { ::bar2 } finally { ::foo2 } + inv() + } +} + +fun poll42(): Flow { + return flow { + val inv = try { ::bar3 } finally { ::foo3 } + inv() + } +} + +fun poll43(): Flow { + return flow { + val inv = try { ::bar4 } finally { ::foo4 } + inv() + } +} + +fun poll44(): Flow { + return flow { + val inv = try { ::bar5 } finally { ::foo5 } + inv() + } +} + +fun poll45(): Flow { + return flow { + val inv = try { ::Foo6 } finally { ::Foo6 } + inv() + } +} + +fun poll46(): Flow { + return flow { + val inv = try { foo7() } finally { ::Foo7 } + inv + } +} + +fun poll5(): Flow { + return flow { + val inv = try { ::bar } catch (e: Exception) { ::foo } finally { ::foo } + inv() + } +} + +fun poll51(): Flow { + return flow { + val inv = try { ::bar2 } catch (e: Exception) { ::foo2 } finally { ::foo2 } + inv() + } +} + +fun poll52(): Flow { + return flow { + val inv = try { ::bar3 } catch (e: Exception) { ::foo3 } finally { ::foo3 } + inv() + } +} + +fun poll53(): Flow { + return flow { + val inv = try { ::bar4 } catch (e: Exception) { ::foo4 } finally { ::foo4 } + inv() + } +} + +fun poll54(): Flow { + return flow { + val inv = try { ::bar5 } catch (e: Exception) { ::foo5 } finally { ::foo5 } + inv() + } +} + +fun poll55(): Flow { + return flow { + val inv = try { ::Foo6 } catch (e: Exception) { ::Foo6 } finally { ::Foo6 } + inv() + } +} + +fun poll56(): Flow { + return flow { + val inv = try { ::Foo7 } catch (e: Exception) { foo7() } finally { foo7() } + inv + } +} + +fun poll6(): Flow { + return flow { + val inv = ::bar + inv + } +} + +fun poll61(): Flow { + return flow { + val inv = ::bar2 + inv + } +} + +fun poll62(): Flow { + return flow { + val inv = ::bar3 + inv + } +} + +fun poll63(): Flow { + return flow { + val inv = ::bar4 + inv + } +} + +fun poll64(): Flow { + return flow { + val inv = ::bar5 + inv + } +} + +fun poll65(): Flow { + return flow { + val inv = ::Foo6 + inv + } +} + +fun poll66(): Flow { + return flow { + val inv = ::Foo7 + inv + } +} + +fun poll7(): Flow { + return flow { + val inv = ::bar!! + inv() + } +} + +fun poll71(): Flow { + return flow { + val inv = ::bar2!! + inv() + } +} + +fun poll72(): Flow { + return flow { + val inv = ::bar3!! + inv() + } +} + +fun poll73(): Flow { + return flow { + val inv = ::bar4!! + inv + } +} + +fun poll74(): Flow { + return flow { + val inv = ::bar5!! + inv + } +} + +fun poll75(): Flow { + return flow { + val inv = ::Foo6!! + inv + } +} + +fun poll76(): Flow { + return flow { + val inv = ::Foo7!! + inv + } +} + +fun poll8(): Flow { + return flow { + val inv = ::bar in setOf(::foo) + inv() + } +} + +fun poll81(): Flow { + return flow { + val inv = ::bar2 in setOf(::foo2) + inv() + } +} + +fun poll82(): Flow { + return flow { + val inv = ::bar3 in setOf(::foo3) + inv() + } +} + +fun poll83(): Flow { + return flow { + val inv = ::bar4 in setOf(::foo4) + inv + } +} + +fun poll84(): Flow { + return flow { + val inv = ::bar5 in setOf(::foo5) + inv + } +} + +fun poll85(): Flow { + return flow { + val inv = ::Foo6 in setOf(::Foo6) + inv + } +} + +fun poll86(): Flow { + return flow { + val inv = ::Foo7 in setOf(::Foo7) + inv + } +} + +fun poll87(): Flow { + return flow { + val inv = ::Foo7 in setOf(foo7()) + inv + } +} + +fun poll88(): Flow { + return flow { + val inv = foo7() in setOf(::Foo7) + inv + } +} diff --git a/compiler/testData/diagnostics/tests/inference/builderInference/specialCallsWithCallableReferences.kt b/compiler/testData/diagnostics/tests/inference/builderInference/specialCallsWithCallableReferences.kt new file mode 100644 index 00000000000..1bf84cc30a8 --- /dev/null +++ b/compiler/testData/diagnostics/tests/inference/builderInference/specialCallsWithCallableReferences.kt @@ -0,0 +1,499 @@ +// 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 FlowCollector.bar(): K = null as K +fun FlowCollector.foo(): K = null as K + +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) {} + +val FlowCollector.bar5: K get() = null as K +val FlowCollector.foo5: K get() = null as K + +class Foo6 + +class Foo7 +fun foo7() = null as Foo7 + +interface FlowCollector {} + +fun flow(@BuilderInference block: suspend FlowCollector.() -> Unit) = Flow(block) + +class Flow(private val block: suspend FlowCollector.() -> Unit) + +fun select(vararg x: R) = x[0] + +fun poll0(): Flow { + return flow { + val inv = select(::bar, ::foo) + inv() + } +} + +fun poll01(): Flow { + return flow { + val inv = select(::bar2, ::foo2) + inv() + } +} + +fun poll02(): Flow { + return flow { + val inv = select(::bar3, ::foo3) + inv() + } +} + +fun poll03(): Flow { + return flow { + val inv = select(::bar4, ::foo4) + inv() + } +} + +fun poll04(): Flow { + return flow { + val inv = select(::bar5, ::foo5) + inv + } +} + +fun poll05(): Flow { + return flow { + val inv = select(::Foo6, ::Foo6) + inv + } +} + +fun poll06(): Flow { + return flow { + val inv = select(foo7(), ::Foo7) + inv + } +} + +fun poll1(flag: Boolean): Flow { + return flow { + val inv = if (flag) { ::bar2 } else { ::foo2 } + inv() + } +} + +fun poll11(flag: Boolean): Flow { + return flow { + val inv = if (flag) { ::bar2 } else { ::foo2 } + inv() + } +} + +fun poll12(flag: Boolean): Flow { + return flow { + val inv = if (flag) { ::bar3 } else { ::foo3 } + inv() + } +} + +fun poll13(flag: Boolean): Flow { + return flow { + val inv = if (flag) { ::bar2 } else { ::foo3 } + inv() + } +} + +fun poll14(flag: Boolean): Flow { + return flow { + val inv = if (flag) { ::bar4 } else { ::foo4 } + inv() + } +} + +fun poll15(flag: Boolean): Flow { + return flow { + val inv = if (flag) { ::bar5 } else { ::foo5 } + inv() + } +} + +fun poll16(flag: Boolean): Flow { + return flow { + val inv = if (flag) { ::Foo6 } else { ::Foo6 } + inv() + } +} + +fun poll17(flag: Boolean): Flow { + return flow { + val inv = if (flag) { foo7() } else { ::Foo7 } + inv + } +} + +fun poll2(flag: Boolean): Flow { + return flow { + val inv = when (flag) { true -> ::bar else -> ::foo } + inv() + } +} + +fun poll21(flag: Boolean): Flow { + return flow { + val inv = when (flag) { true -> ::bar2 else -> ::foo2 } + inv() + } +} + +fun poll22(flag: Boolean): Flow { + return flow { + val inv = when (flag) { true -> ::bar3 else -> ::foo3 } + inv() + } +} + +fun poll23(flag: Boolean): Flow { + return flow { + val inv = when (flag) { true -> ::bar4 else -> ::foo4 } + inv() + } +} + +fun poll24(flag: Boolean): Flow { + return flow { + val inv = when (flag) { true -> ::bar5 else -> ::foo5 } + inv + } +} + +fun poll25(flag: Boolean): Flow { + return flow { + val inv = when (flag) { true -> ::Foo6 else -> ::Foo6 } + inv + } +} + +fun poll26(flag: Boolean): Flow { + return flow { + val inv = when (flag) { true -> ::Foo7 false -> foo7() else -> ::Foo7 } + inv + } +} + +fun poll3(flag: Boolean): Flow { + return flow { + val inv = when (flag) { true -> ::bar false -> ::foo } + inv() + } +} + +fun poll31(flag: Boolean): Flow { + return flow { + val inv = when (flag) { true -> ::bar2 false -> ::foo2 } + inv() + } +} + +fun poll32(flag: Boolean): Flow { + return flow { + val inv = when (flag) { true -> ::bar3 false -> ::foo3 } + inv() + } +} + +fun poll33(flag: Boolean): Flow { + return flow { + val inv = when (flag) { true -> ::bar4 false -> ::foo4 } + inv() + } +} + +fun poll34(flag: Boolean): Flow { + return flow { + val inv = when (flag) { true -> ::bar5 false -> ::foo5 } + inv + } +} + +fun poll35(flag: Boolean): Flow { + return flow { + val inv = when (flag) { true -> ::Foo6 false -> ::Foo6 } + inv + } +} + +fun poll36(flag: Boolean): Flow { + return flow { + val inv = when (flag) { true -> ::Foo7 false -> foo7() } + inv + } +} + +fun poll4(): Flow { + return flow { + val inv = try { ::bar } finally { ::foo } + inv() + } +} + +fun poll41(): Flow { + return flow { + val inv = try { ::bar2 } finally { ::foo2 } + inv() + } +} + +fun poll42(): Flow { + return flow { + val inv = try { ::bar3 } finally { ::foo3 } + inv() + } +} + +fun poll43(): Flow { + return flow { + val inv = try { ::bar4 } finally { ::foo4 } + inv() + } +} + +fun poll44(): Flow { + return flow { + val inv = try { ::bar5 } finally { ::foo5 } + inv() + } +} + +fun poll45(): Flow { + return flow { + val inv = try { ::Foo6 } finally { ::Foo6 } + inv() + } +} + +fun poll46(): Flow { + return flow { + val inv = try { foo7() } finally { ::Foo7 } + inv + } +} + +fun poll5(): Flow { + return flow { + val inv = try { ::bar } catch (e: Exception) { ::foo } finally { ::foo } + inv() + } +} + +fun poll51(): Flow { + return flow { + val inv = try { ::bar2 } catch (e: Exception) { ::foo2 } finally { ::foo2 } + inv() + } +} + +fun poll52(): Flow { + return flow { + val inv = try { ::bar3 } catch (e: Exception) { ::foo3 } finally { ::foo3 } + inv() + } +} + +fun poll53(): Flow { + return flow { + val inv = try { ::bar4 } catch (e: Exception) { ::foo4 } finally { ::foo4 } + inv() + } +} + +fun poll54(): Flow { + return flow { + val inv = try { ::bar5 } catch (e: Exception) { ::foo5 } finally { ::foo5 } + inv() + } +} + +fun poll55(): Flow { + return flow { + val inv = try { ::Foo6 } catch (e: Exception) { ::Foo6 } finally { ::Foo6 } + inv() + } +} + +fun poll56(): Flow { + return flow { + val inv = try { ::Foo7 } catch (e: Exception) { foo7() } finally { foo7() } + inv + } +} + +fun poll6(): Flow { + return flow { + val inv = ::bar + inv + } +} + +fun poll61(): Flow { + return flow { + val inv = ::bar2 + inv + } +} + +fun poll62(): Flow { + return flow { + val inv = ::bar3 + inv + } +} + +fun poll63(): Flow { + return flow { + val inv = ::bar4 + inv + } +} + +fun poll64(): Flow { + return flow { + val inv = ::bar5 + inv + } +} + +fun poll65(): Flow { + return flow { + val inv = ::Foo6 + inv + } +} + +fun poll66(): Flow { + return flow { + val inv = ::Foo7 + inv + } +} + +fun poll7(): Flow { + return flow { + val inv = ::bar!! + inv() + } +} + +fun poll71(): Flow { + return flow { + val inv = ::bar2!! + inv() + } +} + +fun poll72(): Flow { + return flow { + val inv = ::bar3!! + inv() + } +} + +fun poll73(): Flow { + return flow { + val inv = ::bar4!! + inv + } +} + +fun poll74(): Flow { + return flow { + val inv = ::bar5!! + inv + } +} + +fun poll75(): Flow { + return flow { + val inv = ::Foo6!! + inv + } +} + +fun poll76(): Flow { + return flow { + val inv = ::Foo7!! + inv + } +} + +fun poll8(): Flow { + return flow { + val inv = ::bar in setOf(::foo) + inv() + } +} + +fun poll81(): Flow { + return flow { + val inv = ::bar2 in setOf(::foo2) + inv() + } +} + +fun poll82(): Flow { + return flow { + val inv = ::bar3 in setOf(::foo3) + inv() + } +} + +fun poll83(): Flow { + return flow { + val inv = ::bar4 in setOf(::foo4) + inv + } +} + +fun poll84(): Flow { + return flow { + val inv = ::bar5 in setOf(::foo5) + inv + } +} + +fun poll85(): Flow { + return flow { + val inv = ::Foo6 in setOf(::Foo6) + inv + } +} + +fun poll86(): Flow { + return flow { + val inv = ::Foo7 in setOf(::Foo7) + inv + } +} + +fun poll87(): Flow { + return flow { + val inv = ::Foo7 in setOf(foo7()) + inv + } +} + +fun poll88(): Flow { + return flow { + val inv = foo7() in setOf(::Foo7) + inv + } +} diff --git a/compiler/testData/diagnostics/tests/inference/builderInference/specialCallsWithLambdas.fir.kt b/compiler/testData/diagnostics/tests/inference/builderInference/specialCallsWithLambdas.fir.kt new file mode 100644 index 00000000000..ef0c7ae3442 --- /dev/null +++ b/compiler/testData/diagnostics/tests/inference/builderInference/specialCallsWithLambdas.fir.kt @@ -0,0 +1,195 @@ +// WITH_RUNTIME +// SKIP_TXT +// !DIAGNOSTICS: -CAST_NEVER_SUCCEEDS -UNUSED_LAMBDA_EXPRESSION -UNCHECKED_CAST -UNUSED_PARAMETER -UNUSED_VARIABLE -EXPERIMENTAL_API_USAGE_ERROR -UNUSED_EXPRESSION + +import kotlin.experimental.ExperimentalTypeInference + +interface FlowCollector {} + +fun flow(@BuilderInference block: suspend FlowCollector.() -> Unit) = Flow(block) + +class Flow(private val block: suspend FlowCollector.() -> Unit) + +fun select(vararg x: R) = x[0] + +fun poll0(): Flow { + return flow { + val inv = select({}, {}) + inv() + } +} + +fun poll01(): Flow { + return flow { + val inv = select({ 1 }, { 1f }) + inv() + } +} + +fun poll1(flag: Boolean): Flow { + return flow { + val inv = if (flag) { {} } else { {} } + inv() + } +} + +fun poll11(flag: Boolean): Flow { + return flow { + val inv = if (flag) { { 1 } } else { { 1f } } + inv() + } +} + +fun poll12(flag: Boolean): Flow { + return flow { + val inv = if (flag) ({ }) else ({ }) + inv() + } +} + +fun poll13(flag: Boolean): Flow { + return flow { + val inv = if (flag) ({ 1 }) else ({ 1f }) + inv() + } +} + +fun poll2(flag: Boolean): Flow { + return flow { + val inv = when (flag) { true -> {{}} else -> {{}} } + inv() + } +} + +fun poll21(flag: Boolean): Flow { + return flow { + val inv = when (flag) { true -> {{1}} else -> {{1f}} } + inv() + } +} + +fun poll22(flag: Boolean): Flow { + return flow { + val inv = when (flag) { true -> ({}) else -> ({}) } + inv() + } +} + +fun poll23(flag: Boolean): Flow { + return flow { + val inv = when (flag) { true -> ({1}) else -> ({1f}) } + inv() + } +} + +fun poll4(): Flow { + return flow { + val inv = try { {} } finally { {} } + inv() + } +} + +fun poll41(): Flow { + return flow { + val inv = try { {1} } finally { {1f} } + inv() + } +} + +fun poll42(): Flow { + return flow { + val inv = try { ({1}) } finally { ({1f}) } + inv() + } +} + +fun poll43(): Flow { + return flow { + val inv = try { ({}) } finally { ({}) } + inv() + } +} + +fun poll5(): Flow { + return flow { + val inv = try { {1} } catch (e: Exception) { {1f} } finally { {} } + inv() + } +} + +fun poll7(): Flow { + return flow { + val inv = {}!! + inv() + } +} + +fun poll71(): Flow { + return flow { + val inv = {1f}!! + inv() + } +} + +fun poll72(): Flow { + return flow { + val inv = {{}}!! + inv() + } +} + +fun poll73(): Flow { + return flow { + val inv = ({})!! + inv + } +} + +fun poll8(): Flow { + return flow { + val inv = {1} in setOf({1f}) + inv() + } +} + +fun poll81(): Flow { + return flow { + val inv = {} in setOf({}) + inv() + } +} + +fun poll82(): Flow { + return flow { + val inv = {{}} in setOf({{}}) + inv() + } +} + +fun poll83(): Flow { + return flow { + val inv = {({})} in setOf({({})}) + inv() + } +} + +fun poll84(): Flow { + return flow { + val inv = {{1}} in setOf({{1f}}) + inv() + } +} + +fun poll85(): Flow { + return flow { + val inv = {({"1"})} in setOf({({"1f"})}) + inv() + } +} + +fun poll86(): Flow { + return flow { + val inv = {({"1"})}!! in setOf({({"1f"})}!!) + inv() + } +} diff --git a/compiler/testData/diagnostics/tests/inference/builderInference/specialCallsWithLambdas.kt b/compiler/testData/diagnostics/tests/inference/builderInference/specialCallsWithLambdas.kt new file mode 100644 index 00000000000..0134ee521ae --- /dev/null +++ b/compiler/testData/diagnostics/tests/inference/builderInference/specialCallsWithLambdas.kt @@ -0,0 +1,195 @@ +// WITH_RUNTIME +// SKIP_TXT +// !DIAGNOSTICS: -CAST_NEVER_SUCCEEDS -UNUSED_LAMBDA_EXPRESSION -UNCHECKED_CAST -UNUSED_PARAMETER -UNUSED_VARIABLE -EXPERIMENTAL_API_USAGE_ERROR -UNUSED_EXPRESSION + +import kotlin.experimental.ExperimentalTypeInference + +interface FlowCollector {} + +fun flow(@BuilderInference block: suspend FlowCollector.() -> Unit) = Flow(block) + +class Flow(private val block: suspend FlowCollector.() -> Unit) + +fun select(vararg x: R) = x[0] + +fun poll0(): Flow { + return flow { + val inv = select({}, {}) + inv() + } +} + +fun poll01(): Flow { + return flow { + val inv = select({ 1 }, { 1f }) + inv() + } +} + +fun poll1(flag: Boolean): Flow { + return flow { + val inv = if (flag) { {} } else { {} } + inv() + } +} + +fun poll11(flag: Boolean): Flow { + return flow { + val inv = if (flag) { { 1 } } else { { 1f } } + inv() + } +} + +fun poll12(flag: Boolean): Flow { + return flow { + val inv = if (flag) ({ }) else ({ }) + inv() + } +} + +fun poll13(flag: Boolean): Flow { + return flow { + val inv = if (flag) ({ 1 }) else ({ 1f }) + inv() + } +} + +fun poll2(flag: Boolean): Flow { + return flow { + val inv = when (flag) { true -> {{}} else -> {{}} } + inv() + } +} + +fun poll21(flag: Boolean): Flow { + return flow { + val inv = when (flag) { true -> {{1}} else -> {{1f}} } + inv() + } +} + +fun poll22(flag: Boolean): Flow { + return flow { + val inv = when (flag) { true -> ({}) else -> ({}) } + inv() + } +} + +fun poll23(flag: Boolean): Flow { + return flow { + val inv = when (flag) { true -> ({1}) else -> ({1f}) } + inv() + } +} + +fun poll4(): Flow { + return flow { + val inv = try { {} } finally { {} } + inv() + } +} + +fun poll41(): Flow { + return flow { + val inv = try { {1} } finally { {1f} } + inv() + } +} + +fun poll42(): Flow { + return flow { + val inv = try { ({1}) } finally { ({1f}) } + inv() + } +} + +fun poll43(): Flow { + return flow { + val inv = try { ({}) } finally { ({}) } + inv() + } +} + +fun poll5(): Flow { + return flow { + val inv = try { {1} } catch (e: Exception) { {1f} } finally { {} } + inv() + } +} + +fun poll7(): Flow { + return flow { + val inv = {}!! + inv() + } +} + +fun poll71(): Flow { + return flow { + val inv = {1f}!! + inv() + } +} + +fun poll72(): Flow { + return flow { + val inv = {{}}!! + inv() + } +} + +fun poll73(): Flow { + return flow { + val inv = ({})!! + inv + } +} + +fun poll8(): Flow { + return flow { + val inv = {1} in setOf({1f}) + inv() + } +} + +fun poll81(): Flow { + return flow { + val inv = {} in setOf({}) + inv() + } +} + +fun poll82(): Flow { + return flow { + val inv = {{}} in setOf({{}}) + inv() + } +} + +fun poll83(): Flow { + return flow { + val inv = {({})} in setOf({({})}) + inv() + } +} + +fun poll84(): Flow { + return flow { + val inv = {{1}} in setOf({{1f}}) + inv() + } +} + +fun poll85(): Flow { + return flow { + val inv = {({"1"})} in setOf({({"1f"})}) + inv() + } +} + +fun poll86(): Flow { + return flow { + val inv = {({"1"})}!! in setOf({({"1f"})}!!) + inv() + } +} diff --git a/compiler/testData/diagnostics/tests/inference/specialCallsWithCallableReferences.fir.kt b/compiler/testData/diagnostics/tests/inference/specialCallsWithCallableReferences.fir.kt index 662faa580a9..729572ad9eb 100644 --- a/compiler/testData/diagnostics/tests/inference/specialCallsWithCallableReferences.fir.kt +++ b/compiler/testData/diagnostics/tests/inference/specialCallsWithCallableReferences.fir.kt @@ -10,12 +10,8 @@ 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) {} +fun bar4(): K = null as K +fun foo4(): K = null as K class Foo6 @@ -44,7 +40,7 @@ fun poll13(flag: Boolean) { fun poll14(flag: Boolean) { val inv = if (flag) { ::bar4 } else { ::foo4 } - inv() + inv() } fun poll15(flag: Boolean) { @@ -79,7 +75,7 @@ fun poll22(flag: Boolean) { fun poll23(flag: Boolean) { val inv = when (flag) { true -> ::bar4 else -> ::foo4 } - inv() + inv() } fun poll24(flag: Boolean) { @@ -114,7 +110,7 @@ fun poll32(flag: Boolean) { fun poll33(flag: Boolean) { val inv = when (flag) { true -> ::bar4 false -> ::foo4 } - inv() + inv() } fun poll34(flag: Boolean) { @@ -149,7 +145,7 @@ fun poll42() { fun poll43() { val inv = try { ::bar4 } finally { ::foo4 } - inv() + inv() } fun poll44() { @@ -184,7 +180,7 @@ fun poll52() { fun poll53() { val inv = try { ::bar4 } catch (e: Exception) { ::foo4 } finally { ::foo4 } - inv() + inv() } fun poll54() { diff --git a/compiler/tests-gen/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java b/compiler/tests-gen/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java index 3dfe5b02214..07d22d9d5d3 100644 --- a/compiler/tests-gen/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java +++ b/compiler/tests-gen/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java @@ -13506,6 +13506,11 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest { runTest("compiler/testData/codegen/box/inference/builderInference/lackOfNullCheckOnNullableInsideBuild.kt"); } + @TestMetadata("specialCallsWithCallableReferences.kt") + public void testSpecialCallsWithCallableReferences() throws Exception { + runTest("compiler/testData/codegen/box/inference/builderInference/specialCallsWithCallableReferences.kt"); + } + @TestMetadata("specialCallsWithCallableReferencesDontCareTypeInBlockExpression.kt") public void testSpecialCallsWithCallableReferencesDontCareTypeInBlockExpression() throws Exception { runTest("compiler/testData/codegen/box/inference/builderInference/specialCallsWithCallableReferencesDontCareTypeInBlockExpression.kt"); @@ -13521,6 +13526,11 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest { runTest("compiler/testData/codegen/box/inference/builderInference/specialCallsWithCallableReferencesNonStrictOnlyInputTypes.kt"); } + @TestMetadata("specialCallsWithLambdas.kt") + public void testSpecialCallsWithLambdas() throws Exception { + runTest("compiler/testData/codegen/box/inference/builderInference/specialCallsWithLambdas.kt"); + } + @TestMetadata("substituteStubTypeIntoCR.kt") public void testSubstituteStubTypeIntoCR() throws Exception { runTest("compiler/testData/codegen/box/inference/builderInference/substituteStubTypeIntoCR.kt");