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> WRONG_MODIFIER_CONTAINING_DECLARATION = DiagnosticFactory2.create(ERROR);
|
||||||
DiagnosticFactory2<PsiElement, KtModifierKeywordToken, String> DEPRECATED_MODIFIER_CONTAINING_DECLARATION = DiagnosticFactory2.create(WARNING);
|
DiagnosticFactory2<PsiElement, KtModifierKeywordToken, String> DEPRECATED_MODIFIER_CONTAINING_DECLARATION = DiagnosticFactory2.create(WARNING);
|
||||||
DiagnosticFactory1<PsiElement, KtModifierKeywordToken> ILLEGAL_INLINE_PARAMETER_MODIFIER = DiagnosticFactory1.create(ERROR);
|
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);
|
DiagnosticFactory1<KtAnnotationEntry, String> WRONG_ANNOTATION_TARGET = DiagnosticFactory1.create(ERROR);
|
||||||
DiagnosticFactory2<KtAnnotationEntry, String, String> WRONG_ANNOTATION_TARGET_WITH_USE_SITE_TARGET = DiagnosticFactory2.create(ERROR);
|
DiagnosticFactory2<KtAnnotationEntry, String, String> WRONG_ANNOTATION_TARGET_WITH_USE_SITE_TARGET = DiagnosticFactory2.create(ERROR);
|
||||||
DiagnosticFactory0<KtAnnotationEntry> REPEATED_ANNOTATION = DiagnosticFactory0.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(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(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(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, "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(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");
|
MAP.put(REPEATED_ANNOTATION, "This annotation is not repeatable");
|
||||||
|
|||||||
+8
-1
@@ -16,7 +16,9 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.resolve.checkers
|
package org.jetbrains.kotlin.resolve.checkers
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.builtins.isBuiltinFunctionalType
|
||||||
import org.jetbrains.kotlin.builtins.isFunctionType
|
import org.jetbrains.kotlin.builtins.isFunctionType
|
||||||
|
import org.jetbrains.kotlin.builtins.isSuspendFunctionType
|
||||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
||||||
import org.jetbrains.kotlin.diagnostics.DiagnosticSink
|
import org.jetbrains.kotlin.diagnostics.DiagnosticSink
|
||||||
import org.jetbrains.kotlin.diagnostics.Errors
|
import org.jetbrains.kotlin.diagnostics.Errors
|
||||||
@@ -35,10 +37,15 @@ object InlineParameterChecker : SimpleDeclarationChecker {
|
|||||||
val inline = declaration.hasModifier(KtTokens.INLINE_KEYWORD)
|
val inline = declaration.hasModifier(KtTokens.INLINE_KEYWORD)
|
||||||
for (parameter in declaration.valueParameters) {
|
for (parameter in declaration.valueParameters) {
|
||||||
val parameterDescriptor = bindingContext.get(BindingContext.VALUE_PARAMETER, parameter)
|
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.NOINLINE_KEYWORD, diagnosticHolder)
|
||||||
parameter.reportIncorrectInline(KtTokens.CROSSINLINE_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 {
|
inline suspend fun Iterable<String>.test() = testAsync {
|
||||||
var sum = ""
|
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);
|
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")
|
@TestMetadata("invoke.kt")
|
||||||
public void testInvoke() throws Exception {
|
public void testInvoke() throws Exception {
|
||||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithStdLib/coroutines/suspendFunctionType/invoke.kt");
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithStdLib/coroutines/suspendFunctionType/invoke.kt");
|
||||||
|
|||||||
Reference in New Issue
Block a user