diff --git a/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/FunctionsTypingVisitor.kt b/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/FunctionsTypingVisitor.kt index 488f5b20a65..1cbf4b6f4cd 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/FunctionsTypingVisitor.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/FunctionsTypingVisitor.kt @@ -17,6 +17,7 @@ package org.jetbrains.kotlin.types.expressions import com.google.common.collect.Lists +import com.intellij.psi.PsiElement import org.jetbrains.kotlin.builtins.KotlinBuiltIns import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor import org.jetbrains.kotlin.descriptors.SimpleFunctionDescriptor @@ -27,6 +28,7 @@ import org.jetbrains.kotlin.diagnostics.DiagnosticUtils import org.jetbrains.kotlin.diagnostics.Errors.* import org.jetbrains.kotlin.lexer.KtTokens import org.jetbrains.kotlin.psi.* +import org.jetbrains.kotlin.psi.psiUtil.checkReservedPrefixWord import org.jetbrains.kotlin.psi.psiUtil.getAnnotationEntries import org.jetbrains.kotlin.resolve.* import org.jetbrains.kotlin.resolve.BindingContext.EXPECTED_RETURN_TYPE @@ -53,6 +55,7 @@ internal class FunctionsTypingVisitor(facade: ExpressionTypingInternals) : Expre isStatement: Boolean, statementScope: LexicalWritableScope? // must be not null if isStatement ): KotlinTypeInfo { + checkReservedAsync(context, function) if (!isStatement) { // function expression if (!function.getTypeParameters().isEmpty()) { @@ -131,6 +134,8 @@ internal class FunctionsTypingVisitor(facade: ExpressionTypingInternals) : Expre } override fun visitLambdaExpression(expression: KtLambdaExpression, context: ExpressionTypingContext): KotlinTypeInfo? { + checkReservedAsync(context, expression) + if (!expression.getFunctionLiteral().hasBody()) return null val expectedType = context.expectedType @@ -153,6 +158,10 @@ internal class FunctionsTypingVisitor(facade: ExpressionTypingInternals) : Expre return components.dataFlowAnalyzer.createCheckedTypeInfo(resultType, context, expression) } + private fun checkReservedAsync(context: ExpressionTypingContext, expression: PsiElement) { + checkReservedPrefixWord(context.trace, expression, "async", "async block/lambda. Use 'async() { ... }' or 'async(fun...)'") + } + private fun createFunctionLiteralDescriptor( expression: KtLambdaExpression, context: ExpressionTypingContext diff --git a/compiler/testData/diagnostics/tests/ReservedAsync.kt b/compiler/testData/diagnostics/tests/ReservedAsync.kt new file mode 100644 index 00000000000..b5fb492c941 --- /dev/null +++ b/compiler/testData/diagnostics/tests/ReservedAsync.kt @@ -0,0 +1,21 @@ +fun async(f: () -> Unit) { + f() +} + +infix fun Any.async(f: () -> Unit) = f() + +fun test(foo: Any) { + async { } + async /**/ { } + foo async { } + + async() { } + + async({ }) + foo async ({ }) + + foo async fun () {} + foo async (fun () {}) + + async (fun () {}) +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/ReservedAsync.txt b/compiler/testData/diagnostics/tests/ReservedAsync.txt new file mode 100644 index 00000000000..8f9046d89b8 --- /dev/null +++ b/compiler/testData/diagnostics/tests/ReservedAsync.txt @@ -0,0 +1,5 @@ +package + +public fun async(/*0*/ f: () -> kotlin.Unit): kotlin.Unit +public fun test(/*0*/ foo: kotlin.Any): kotlin.Unit +public infix fun kotlin.Any.async(/*0*/ f: () -> kotlin.Unit): kotlin.Unit diff --git a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java index 9b94afdc685..f59fadfaa2d 100644 --- a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java @@ -547,6 +547,12 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTest { doTest(fileName); } + @TestMetadata("ReservedAsync.kt") + public void testReservedAsync() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/ReservedAsync.kt"); + doTest(fileName); + } + @TestMetadata("ResolveOfJavaGenerics.kt") public void testResolveOfJavaGenerics() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/ResolveOfJavaGenerics.kt");