Do not coerce function literals to suspend.
The design is to use `suspend fun` instead of coercion, just as suspend lambdas. However, this syntax is not supported in the parser. But this is not a problem, since the coercion lead to internal compiler error. As a workaround everybody uses suspend lambdas. #KT-24860: Fixed
This commit is contained in:
committed by
Ilya Gorbunov
parent
d57e1bb68b
commit
9df411481c
+12
-20
@@ -1,17 +1,6 @@
|
||||
/*
|
||||
* Copyright 2010-2017 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||
* that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.resolve.calls;
|
||||
@@ -198,7 +187,8 @@ public class ArgumentTypeResolver {
|
||||
public KotlinTypeInfo getArgumentTypeInfo(
|
||||
@Nullable KtExpression expression,
|
||||
@NotNull CallResolutionContext<?> context,
|
||||
@NotNull ResolveArgumentsMode resolveArgumentsMode
|
||||
@NotNull ResolveArgumentsMode resolveArgumentsMode,
|
||||
boolean suspendFunctionTypeExpected
|
||||
) {
|
||||
if (expression == null) {
|
||||
return TypeInfoFactoryKt.noTypeInfo(context);
|
||||
@@ -206,7 +196,7 @@ public class ArgumentTypeResolver {
|
||||
|
||||
KtFunction functionLiteralArgument = getFunctionLiteralArgumentIfAny(expression, context);
|
||||
if (functionLiteralArgument != null) {
|
||||
return getFunctionLiteralTypeInfo(expression, functionLiteralArgument, context, resolveArgumentsMode);
|
||||
return getFunctionLiteralTypeInfo(expression, functionLiteralArgument, context, resolveArgumentsMode, suspendFunctionTypeExpected);
|
||||
}
|
||||
|
||||
KtCallableReferenceExpression callableReferenceExpression = getCallableReferenceExpressionIfAny(expression, context);
|
||||
@@ -319,10 +309,11 @@ public class ArgumentTypeResolver {
|
||||
@NotNull KtExpression expression,
|
||||
@NotNull KtFunction functionLiteral,
|
||||
@NotNull CallResolutionContext<?> context,
|
||||
@NotNull ResolveArgumentsMode resolveArgumentsMode
|
||||
@NotNull ResolveArgumentsMode resolveArgumentsMode,
|
||||
boolean suspendFunctionTypeExpected
|
||||
) {
|
||||
if (resolveArgumentsMode == SHAPE_FUNCTION_ARGUMENTS) {
|
||||
KotlinType type = getShapeTypeOfFunctionLiteral(functionLiteral, context.scope, context.trace, true);
|
||||
KotlinType type = getShapeTypeOfFunctionLiteral(functionLiteral, context.scope, context.trace, true, suspendFunctionTypeExpected);
|
||||
return TypeInfoFactoryKt.createTypeInfo(type, context);
|
||||
}
|
||||
return expressionTypingServices.getTypeInfo(expression, context.replaceContextDependency(INDEPENDENT));
|
||||
@@ -333,7 +324,8 @@ public class ArgumentTypeResolver {
|
||||
@NotNull KtFunction function,
|
||||
@NotNull LexicalScope scope,
|
||||
@NotNull BindingTrace trace,
|
||||
boolean expectedTypeIsUnknown
|
||||
boolean expectedTypeIsUnknown,
|
||||
boolean suspendFunctionTypeExpected
|
||||
) {
|
||||
boolean isFunctionLiteral = function instanceof KtFunctionLiteral;
|
||||
if (function.getValueParameterList() == null && isFunctionLiteral) {
|
||||
@@ -363,7 +355,7 @@ public class ArgumentTypeResolver {
|
||||
return expectedTypeIsUnknown && isFunctionLiteral
|
||||
? functionPlaceholders.createFunctionPlaceholderType(parameterTypes, /* hasDeclaredArguments = */ true)
|
||||
: FunctionTypesKt.createFunctionType(
|
||||
builtIns, Annotations.Companion.getEMPTY(), receiverType, parameterTypes, parameterNames, returnType
|
||||
builtIns, Annotations.Companion.getEMPTY(), receiverType, parameterTypes, parameterNames, returnType, suspendFunctionTypeExpected
|
||||
);
|
||||
}
|
||||
|
||||
@@ -399,7 +391,7 @@ public class ArgumentTypeResolver {
|
||||
|
||||
CallResolutionContext<?> newContext = context.replaceDataFlowInfo(infoForArguments.getInfo(argument));
|
||||
// Here we go inside arguments and determine additional data flow information for them
|
||||
KotlinTypeInfo typeInfoForCall = getArgumentTypeInfo(expression, newContext, resolveArgumentsMode);
|
||||
KotlinTypeInfo typeInfoForCall = getArgumentTypeInfo(expression, newContext, resolveArgumentsMode, false);
|
||||
infoForArguments.updateInfo(argument, typeInfoForCall.getDataFlowInfo());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,17 +1,6 @@
|
||||
/*
|
||||
* Copyright 2010-2017 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||
* that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.resolve.calls
|
||||
@@ -367,7 +356,7 @@ class CallCompleter(
|
||||
// While the expected type is not known, the function literal arguments are not analyzed (to analyze function literal bodies once),
|
||||
// but they should be analyzed when the expected type is known (during the call completion).
|
||||
ArgumentTypeResolver.getFunctionLiteralArgumentIfAny(expression, context)?.let { functionLiteralArgument ->
|
||||
argumentTypeResolver.getFunctionLiteralTypeInfo(expression, functionLiteralArgument, context, RESOLVE_FUNCTION_ARGUMENTS)
|
||||
argumentTypeResolver.getFunctionLiteralTypeInfo(expression, functionLiteralArgument, context, RESOLVE_FUNCTION_ARGUMENTS, false)
|
||||
}
|
||||
|
||||
// While the expected type is not known, (possibly overloaded) callable references can have placeholder types
|
||||
|
||||
@@ -1,23 +1,13 @@
|
||||
/*
|
||||
* Copyright 2010-2017 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||
* that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.resolve.calls
|
||||
|
||||
import com.google.common.collect.Lists
|
||||
import org.jetbrains.kotlin.builtins.ReflectionTypes
|
||||
import org.jetbrains.kotlin.builtins.isSuspendFunctionType
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.impl.TypeAliasConstructorDescriptor
|
||||
@@ -362,7 +352,7 @@ class CandidateResolver(
|
||||
val expectedType = getEffectiveExpectedType(parameterDescriptor, argument, context)
|
||||
|
||||
val newContext = context.replaceDataFlowInfo(infoForArguments.getInfo(argument)).replaceExpectedType(expectedType)
|
||||
val typeInfoForCall = argumentTypeResolver.getArgumentTypeInfo(expression, newContext, resolveFunctionArgumentBodies)
|
||||
val typeInfoForCall = argumentTypeResolver.getArgumentTypeInfo(expression, newContext, resolveFunctionArgumentBodies, expectedType.isSuspendFunctionType)
|
||||
val type = typeInfoForCall.type
|
||||
infoForArguments.updateInfo(argument, typeInfoForCall.dataFlowInfo)
|
||||
|
||||
|
||||
+22
-22
@@ -1,25 +1,11 @@
|
||||
/*
|
||||
* Copyright 2010-2017 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||
* that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.resolve.calls
|
||||
|
||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||
import org.jetbrains.kotlin.builtins.ReflectionTypes
|
||||
import org.jetbrains.kotlin.builtins.isBuiltinFunctionalTypeOrSubtype
|
||||
import org.jetbrains.kotlin.builtins.isFunctionTypeOrSubtype
|
||||
import org.jetbrains.kotlin.builtins.*
|
||||
import org.jetbrains.kotlin.config.LanguageFeature
|
||||
import org.jetbrains.kotlin.config.LanguageVersionSettings
|
||||
import org.jetbrains.kotlin.descriptors.CallableDescriptor
|
||||
@@ -261,7 +247,12 @@ class GenericCandidateResolver(
|
||||
val dataFlowInfoForArgument = context.candidateCall.dataFlowInfoForArguments.getInfo(valueArgument)
|
||||
val newContext = context.replaceExpectedType(expectedType).replaceDataFlowInfo(dataFlowInfoForArgument)
|
||||
|
||||
val typeInfoForCall = argumentTypeResolver.getArgumentTypeInfo(argumentExpression, newContext, resolveFunctionArgumentBodies)
|
||||
val typeInfoForCall = argumentTypeResolver.getArgumentTypeInfo(
|
||||
argumentExpression,
|
||||
newContext,
|
||||
resolveFunctionArgumentBodies,
|
||||
expectedType?.isSuspendFunctionType == true
|
||||
)
|
||||
context.candidateCall.dataFlowInfoForArguments.updateInfo(valueArgument, typeInfoForCall.dataFlowInfo)
|
||||
|
||||
val constraintPosition = VALUE_PARAMETER_POSITION.position(valueParameterDescriptor.index)
|
||||
@@ -435,7 +426,13 @@ class GenericCandidateResolver(
|
||||
var expectedType = newSubstitution.buildSubstitutor().substitute(effectiveExpectedType, Variance.IN_VARIANCE)
|
||||
|
||||
if (expectedType == null || TypeUtils.isDontCarePlaceholder(expectedType)) {
|
||||
expectedType = argumentTypeResolver.getShapeTypeOfFunctionLiteral(functionLiteral, context.scope, context.trace, false)
|
||||
expectedType = argumentTypeResolver.getShapeTypeOfFunctionLiteral(
|
||||
functionLiteral,
|
||||
context.scope,
|
||||
context.trace,
|
||||
false,
|
||||
expectedType?.isSuspendFunctionType == true
|
||||
)
|
||||
}
|
||||
if (expectedType == null || !expectedType.isBuiltinFunctionalTypeOrSubtype || hasUnknownFunctionParameter(expectedType)) {
|
||||
return
|
||||
@@ -463,7 +460,8 @@ class GenericCandidateResolver(
|
||||
.replaceDataFlowInfo(dataFlowInfoForArgument).replaceResolutionResultsCache(temporaryToResolveFunctionLiteral.cache)
|
||||
.replaceContextDependency(INDEPENDENT)
|
||||
val type = argumentTypeResolver.getFunctionLiteralTypeInfo(
|
||||
argumentExpression, functionLiteral, newContext, RESOLVE_FUNCTION_ARGUMENTS
|
||||
argumentExpression, functionLiteral, newContext, RESOLVE_FUNCTION_ARGUMENTS,
|
||||
expectedType.isSuspendFunctionType
|
||||
).type
|
||||
if (!mismatch[0]) {
|
||||
constraintSystem.addSubtypeConstraint(type, effectiveExpectedTypeInSystem, position)
|
||||
@@ -476,8 +474,10 @@ class GenericCandidateResolver(
|
||||
val newContext = context.replaceExpectedType(expectedTypeWithEstimatedReturnType).replaceDataFlowInfo(dataFlowInfoForArgument)
|
||||
.replaceContextDependency(INDEPENDENT)
|
||||
val type =
|
||||
argumentTypeResolver.getFunctionLiteralTypeInfo(argumentExpression, functionLiteral, newContext, RESOLVE_FUNCTION_ARGUMENTS)
|
||||
.type
|
||||
argumentTypeResolver.getFunctionLiteralTypeInfo(
|
||||
argumentExpression, functionLiteral, newContext, RESOLVE_FUNCTION_ARGUMENTS,
|
||||
expectedType.isSuspendFunctionType
|
||||
).type
|
||||
constraintSystem.addSubtypeConstraint(type, effectiveExpectedTypeInSystem, position)
|
||||
}
|
||||
|
||||
|
||||
+4
-15
@@ -1,17 +1,6 @@
|
||||
/*
|
||||
* Copyright 2010-2017 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||
* that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.resolve.calls.inference
|
||||
@@ -178,7 +167,7 @@ class CoroutineInferenceSupport(
|
||||
val newContext = context.replaceExpectedType(newExpectedType)
|
||||
.replaceDataFlowInfo(context.candidateCall.dataFlowInfoForArguments.getInfo(valueArgument))
|
||||
.replaceContextDependency(ContextDependency.INDEPENDENT).replaceTraceAndCache(temporaryForCoroutine)
|
||||
argumentTypeResolver.getFunctionLiteralTypeInfo(argumentExpression, functionLiteral, newContext, RESOLVE_FUNCTION_ARGUMENTS)
|
||||
argumentTypeResolver.getFunctionLiteralTypeInfo(argumentExpression, functionLiteral, newContext, RESOLVE_FUNCTION_ARGUMENTS, true)
|
||||
|
||||
inferenceData.reportInferenceResult(csBuilder)
|
||||
}
|
||||
@@ -260,7 +249,7 @@ class CoroutineInferenceSupport(
|
||||
context: CallResolutionContext<*>
|
||||
): KotlinTypeInfo {
|
||||
getFunctionLiteralArgumentIfAny(expression, context)?.let {
|
||||
return argumentTypeResolver.getFunctionLiteralTypeInfo(expression, it, context, RESOLVE_FUNCTION_ARGUMENTS)
|
||||
return argumentTypeResolver.getFunctionLiteralTypeInfo(expression, it, context, RESOLVE_FUNCTION_ARGUMENTS, false)
|
||||
}
|
||||
|
||||
getCallableReferenceExpressionIfAny(expression, context)?.let {
|
||||
|
||||
+4
-4
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||
* that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
@@ -118,11 +118,11 @@ internal class FunctionsTypingVisitor(facade: ExpressionTypingInternals) : Expre
|
||||
val expectedType = context.expectedType
|
||||
|
||||
val functionalTypeExpected = expectedType.isBuiltinFunctionalType()
|
||||
val suspendFunctionTypeExpected = expectedType.isSuspendFunctionType()
|
||||
|
||||
val resultType = functionDescriptor.createFunctionType(suspendFunctionTypeExpected)
|
||||
// We forbid anonymous function expressions to suspend type coercion for now, until `suspend fun` syntax is supported
|
||||
val resultType = functionDescriptor.createFunctionType(suspendFunction = false)
|
||||
|
||||
if (components.languageVersionSettings.supportsFeature(LanguageFeature.NewInference) && functionalTypeExpected)
|
||||
if (components.languageVersionSettings.supportsFeature(LanguageFeature.NewInference) && functionalTypeExpected && !expectedType.isSuspendFunctionType)
|
||||
createTypeInfo(resultType, context)
|
||||
else
|
||||
components.dataFlowAnalyzer.createCheckedTypeInfo(resultType, context, function)
|
||||
|
||||
+29
@@ -0,0 +1,29 @@
|
||||
// !DIAGNOSTICS: -UNUSED_PARAMETER
|
||||
|
||||
fun fail1(c: suspend () -> Unit) {}
|
||||
|
||||
fun fail2(c: () -> Unit) {}
|
||||
|
||||
fun success1(c: suspend () -> Unit) {}
|
||||
|
||||
fun test1() {
|
||||
fail1(<!TYPE_MISMATCH!>fun () {}<!>)
|
||||
fun fail2(c: suspend () -> Unit) {}
|
||||
fail2(<!TYPE_MISMATCH!>fun () {}<!>)
|
||||
fun success1(c: () -> Unit) {}
|
||||
success1(fun() {})
|
||||
}
|
||||
|
||||
suspend fun fail3(c: suspend () -> Unit) {}
|
||||
|
||||
suspend fun fail4(c: () -> Unit) {}
|
||||
|
||||
suspend fun success2(c: suspend () -> Unit) {}
|
||||
|
||||
suspend fun test2() {
|
||||
fail3(<!TYPE_MISMATCH!>fun () {}<!>)
|
||||
fun fail4(c: suspend () -> Unit) {}
|
||||
fail4(<!TYPE_MISMATCH!>fun () {}<!>)
|
||||
fun success2(c: () -> Unit) {}
|
||||
success2(fun() {})
|
||||
}
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
package
|
||||
|
||||
public fun fail1(/*0*/ c: suspend () -> kotlin.Unit): kotlin.Unit
|
||||
public fun fail2(/*0*/ c: () -> kotlin.Unit): kotlin.Unit
|
||||
public suspend fun fail3(/*0*/ c: suspend () -> kotlin.Unit): kotlin.Unit
|
||||
public suspend fun fail4(/*0*/ c: () -> kotlin.Unit): kotlin.Unit
|
||||
public fun success1(/*0*/ c: suspend () -> kotlin.Unit): kotlin.Unit
|
||||
public suspend fun success2(/*0*/ c: suspend () -> kotlin.Unit): kotlin.Unit
|
||||
public fun test1(): kotlin.Unit
|
||||
public suspend fun test2(): kotlin.Unit
|
||||
Vendored
+4
-5
@@ -1,10 +1,9 @@
|
||||
// !WITH_NEW_INFERENCE
|
||||
typealias SuspendFn = suspend () -> Unit
|
||||
|
||||
val test1f: suspend () -> Unit = fun () {}
|
||||
val test2f: suspend Any.() -> Unit = fun Any.() {}
|
||||
val test1f: suspend () -> Unit = <!TYPE_MISMATCH!>fun () {}<!>
|
||||
val test2f: suspend Any.() -> Unit = <!TYPE_MISMATCH!>fun Any.() {}<!>
|
||||
|
||||
// This is a bug in the old inference and should be fixed in new inference
|
||||
// see "Fix anonymous function literals handling in type checker" for more deatils
|
||||
val test3f: suspend Any.(Int) -> Int = <!OI;TYPE_MISMATCH!>fun (k: Int) = k + 1<!>
|
||||
val test4f: SuspendFn = <!OI;TYPE_MISMATCH!>fun Any.() {}<!>
|
||||
val test3f: suspend Any.(Int) -> Int = <!TYPE_MISMATCH!>fun (k: Int) = k + 1<!>
|
||||
val test4f: SuspendFn = <!TYPE_MISMATCH!>fun Any.() {}<!>
|
||||
@@ -9245,6 +9245,11 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTest {
|
||||
runTest("compiler/testData/diagnostics/tests/inference/cannotCompleteResolveWithFunctionLiterals.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("coerceFunctionLiteralToSuspend.kt")
|
||||
public void testCoerceFunctionLiteralToSuspend() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/inference/coerceFunctionLiteralToSuspend.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("completeInferenceIfManyFailed.kt")
|
||||
public void testCompleteInferenceIfManyFailed() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/inference/completeInferenceIfManyFailed.kt");
|
||||
|
||||
Generated
+5
@@ -9245,6 +9245,11 @@ public class DiagnosticsUsingJavacTestGenerated extends AbstractDiagnosticsUsing
|
||||
runTest("compiler/testData/diagnostics/tests/inference/cannotCompleteResolveWithFunctionLiterals.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("coerceFunctionLiteralToSuspend.kt")
|
||||
public void testCoerceFunctionLiteralToSuspend() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/inference/coerceFunctionLiteralToSuspend.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("completeInferenceIfManyFailed.kt")
|
||||
public void testCompleteInferenceIfManyFailed() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/inference/completeInferenceIfManyFailed.kt");
|
||||
|
||||
Reference in New Issue
Block a user