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:
Ilmir Usmanov
2018-06-13 16:29:48 +03:00
committed by Ilya Gorbunov
parent d57e1bb68b
commit 9df411481c
11 changed files with 102 additions and 94 deletions
@@ -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)
@@ -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)
}
@@ -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 {
@@ -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)