Prohibit inline lambda parameters of suspend function type
#KT-16068 Fixed
This commit is contained in:
@@ -193,6 +193,7 @@ public interface Errors {
|
||||
DiagnosticFactory2<PsiElement, KtModifierKeywordToken, String> WRONG_MODIFIER_CONTAINING_DECLARATION = DiagnosticFactory2.create(ERROR);
|
||||
DiagnosticFactory2<PsiElement, KtModifierKeywordToken, String> DEPRECATED_MODIFIER_CONTAINING_DECLARATION = DiagnosticFactory2.create(WARNING);
|
||||
DiagnosticFactory1<PsiElement, KtModifierKeywordToken> ILLEGAL_INLINE_PARAMETER_MODIFIER = DiagnosticFactory1.create(ERROR);
|
||||
DiagnosticFactory0<KtParameter> INLINE_SUSPEND_FUNCTION_TYPE_UNSUPPORTED = DiagnosticFactory0.create(ERROR);
|
||||
DiagnosticFactory1<KtAnnotationEntry, String> WRONG_ANNOTATION_TARGET = DiagnosticFactory1.create(ERROR);
|
||||
DiagnosticFactory2<KtAnnotationEntry, String, String> WRONG_ANNOTATION_TARGET_WITH_USE_SITE_TARGET = DiagnosticFactory2.create(ERROR);
|
||||
DiagnosticFactory0<KtAnnotationEntry> REPEATED_ANNOTATION = DiagnosticFactory0.create(ERROR);
|
||||
|
||||
+1
@@ -159,6 +159,7 @@ public class DefaultErrorMessages {
|
||||
MAP.put(WRONG_MODIFIER_CONTAINING_DECLARATION, "Modifier ''{0}'' is not applicable inside ''{1}''", TO_STRING, TO_STRING);
|
||||
MAP.put(DEPRECATED_MODIFIER_CONTAINING_DECLARATION, "Modifier ''{0}'' is deprecated inside ''{1}''", TO_STRING, TO_STRING);
|
||||
MAP.put(ILLEGAL_INLINE_PARAMETER_MODIFIER, "Modifier ''{0}'' is allowed only for function parameters of an inline function", TO_STRING);
|
||||
MAP.put(INLINE_SUSPEND_FUNCTION_TYPE_UNSUPPORTED, "Inline lambda parameters of suspend function type are not fully supported. Add 'noinline' modifier.");
|
||||
MAP.put(WRONG_ANNOTATION_TARGET, "This annotation is not applicable to target ''{0}''", TO_STRING);
|
||||
MAP.put(WRONG_ANNOTATION_TARGET_WITH_USE_SITE_TARGET, "This annotation is not applicable to target ''{0}'' and use site target ''@{1}''", TO_STRING, TO_STRING);
|
||||
MAP.put(REPEATED_ANNOTATION, "This annotation is not repeatable");
|
||||
|
||||
+8
-1
@@ -16,7 +16,9 @@
|
||||
|
||||
package org.jetbrains.kotlin.resolve.checkers
|
||||
|
||||
import org.jetbrains.kotlin.builtins.isBuiltinFunctionalType
|
||||
import org.jetbrains.kotlin.builtins.isFunctionType
|
||||
import org.jetbrains.kotlin.builtins.isSuspendFunctionType
|
||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
||||
import org.jetbrains.kotlin.diagnostics.DiagnosticSink
|
||||
import org.jetbrains.kotlin.diagnostics.Errors
|
||||
@@ -35,10 +37,15 @@ object InlineParameterChecker : SimpleDeclarationChecker {
|
||||
val inline = declaration.hasModifier(KtTokens.INLINE_KEYWORD)
|
||||
for (parameter in declaration.valueParameters) {
|
||||
val parameterDescriptor = bindingContext.get(BindingContext.VALUE_PARAMETER, parameter)
|
||||
if (!inline || (parameterDescriptor != null && !parameterDescriptor.type.isFunctionType)) {
|
||||
if (!inline || (parameterDescriptor != null && !parameterDescriptor.type.isBuiltinFunctionalType)) {
|
||||
parameter.reportIncorrectInline(KtTokens.NOINLINE_KEYWORD, diagnosticHolder)
|
||||
parameter.reportIncorrectInline(KtTokens.CROSSINLINE_KEYWORD, diagnosticHolder)
|
||||
}
|
||||
|
||||
if (inline && !parameter.hasModifier(KtTokens.NOINLINE_KEYWORD) &&
|
||||
parameterDescriptor?.type?.isSuspendFunctionType == true) {
|
||||
diagnosticHolder.report(Errors.INLINE_SUSPEND_FUNCTION_TYPE_UNSUPPORTED.on(parameter))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -12,7 +12,7 @@ class MyTest {
|
||||
}
|
||||
}
|
||||
|
||||
inline suspend fun <T> testAsync(routine: suspend MyTest.() -> T): T = routine(MyTest())
|
||||
inline suspend fun <T> testAsync(noinline routine: suspend MyTest.() -> T): T = routine(MyTest())
|
||||
|
||||
inline suspend fun Iterable<String>.test() = testAsync {
|
||||
var sum = ""
|
||||
|
||||
+45
@@ -0,0 +1,45 @@
|
||||
// !DIAGNOSTICS: -UNUSED_PARAMETER
|
||||
// SKIP_TXT
|
||||
<!NOTHING_TO_INLINE!>inline<!> fun foo1(<!INLINE_SUSPEND_FUNCTION_TYPE_UNSUPPORTED!>x: suspend () -> Unit<!>) {}
|
||||
<!NOTHING_TO_INLINE!>inline<!> fun foo2(<!INLINE_SUSPEND_FUNCTION_TYPE_UNSUPPORTED!>crossinline x: suspend () -> Unit<!>) {}
|
||||
<!NOTHING_TO_INLINE!>inline<!> fun foo3(noinline x: suspend () -> Unit) {}
|
||||
<!NOTHING_TO_INLINE!>inline<!> fun foo4(<!INCOMPATIBLE_MODIFIERS!>noinline<!> <!INCOMPATIBLE_MODIFIERS!>crossinline<!> x: suspend () -> Unit) {}
|
||||
|
||||
suspend <!NOTHING_TO_INLINE!>inline<!> fun bar1(<!INLINE_SUSPEND_FUNCTION_TYPE_UNSUPPORTED!>x: suspend () -> Unit<!>) {}
|
||||
suspend <!NOTHING_TO_INLINE!>inline<!> fun bar2(<!INLINE_SUSPEND_FUNCTION_TYPE_UNSUPPORTED!>crossinline x: suspend () -> Unit<!>) {}
|
||||
suspend <!NOTHING_TO_INLINE!>inline<!> fun bar3(noinline x: suspend () -> Unit) {}
|
||||
suspend <!NOTHING_TO_INLINE!>inline<!> fun bar4(<!INCOMPATIBLE_MODIFIERS!>noinline<!> <!INCOMPATIBLE_MODIFIERS!>crossinline<!> x: suspend () -> Unit) {}
|
||||
|
||||
suspend fun baz() {
|
||||
foo1 {
|
||||
<!RETURN_NOT_ALLOWED!>return@baz<!>
|
||||
}
|
||||
|
||||
foo2 {
|
||||
<!RETURN_NOT_ALLOWED!>return@baz<!>
|
||||
}
|
||||
|
||||
foo3 {
|
||||
<!RETURN_NOT_ALLOWED!>return@baz<!>
|
||||
}
|
||||
|
||||
foo4 {
|
||||
<!RETURN_NOT_ALLOWED!>return@baz<!>
|
||||
}
|
||||
|
||||
bar1 {
|
||||
<!RETURN_NOT_ALLOWED!>return@baz<!>
|
||||
}
|
||||
|
||||
bar2 {
|
||||
<!RETURN_NOT_ALLOWED!>return@baz<!>
|
||||
}
|
||||
|
||||
bar3 {
|
||||
<!RETURN_NOT_ALLOWED!>return@baz<!>
|
||||
}
|
||||
|
||||
bar4 {
|
||||
<!RETURN_NOT_ALLOWED!>return@baz<!>
|
||||
}
|
||||
}
|
||||
@@ -979,6 +979,12 @@ public class DiagnosticsTestWithStdLibGenerated extends AbstractDiagnosticsTestW
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("inline.kt")
|
||||
public void testInline() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithStdLib/coroutines/suspendFunctionType/inline.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("invoke.kt")
|
||||
public void testInvoke() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithStdLib/coroutines/suspendFunctionType/invoke.kt");
|
||||
|
||||
Reference in New Issue
Block a user