Introduce warning for private inline functions which return anonymous objects without specified supertypes (KT-33917)
This commit is contained in:
+5
@@ -12431,6 +12431,11 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirOldFronte
|
||||
runTest("compiler/testData/diagnostics/tests/inline/recursion.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("returnedAnonymousObjects.kt")
|
||||
public void testReturnedAnonymousObjects() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/inline/returnedAnonymousObjects.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("returns.kt")
|
||||
public void testReturns() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/inline/returns.kt");
|
||||
|
||||
@@ -1129,6 +1129,7 @@ public interface Errors {
|
||||
DiagnosticFactory1<PsiElement, CallableDescriptor> PROTECTED_CALL_FROM_PUBLIC_INLINE_ERROR = DiagnosticFactory1.create(ERROR);
|
||||
DiagnosticFactory2<KtElement, KtExpression, DeclarationDescriptor> INVALID_DEFAULT_FUNCTIONAL_PARAMETER_FOR_INLINE = DiagnosticFactory2.create(ERROR);
|
||||
DiagnosticFactory2<KtElement, KtExpression, DeclarationDescriptor> NOT_SUPPORTED_INLINE_PARAMETER_IN_INLINE_PARAMETER_DEFAULT_VALUE = DiagnosticFactory2.create(ERROR);
|
||||
DiagnosticFactory0<PsiElement> PRIVATE_INLINE_FUNCTIONS_RETURNING_ANONYMOUS_OBJECTS = DiagnosticFactory0.create(WARNING);
|
||||
|
||||
DiagnosticFactory0<PsiElement> NON_LOCAL_SUSPENSION_POINT = DiagnosticFactory0.create(ERROR);
|
||||
DiagnosticFactory1<PsiElement, CallableDescriptor> ILLEGAL_SUSPEND_FUNCTION_CALL = DiagnosticFactory1.create(ERROR);
|
||||
|
||||
+2
@@ -1016,6 +1016,8 @@ public class DefaultErrorMessages {
|
||||
MAP.put(PROTECTED_CALL_FROM_PUBLIC_INLINE_ERROR, "Protected function call from public-API inline function is prohibited", NAME);
|
||||
MAP.put(INVALID_DEFAULT_FUNCTIONAL_PARAMETER_FOR_INLINE, "Invalid default value for inline parameter: ''{0}''. Only lambdas, anonymous functions, and callable references are supported", ELEMENT_TEXT, SHORT_NAMES_IN_TYPES);
|
||||
MAP.put(NOT_SUPPORTED_INLINE_PARAMETER_IN_INLINE_PARAMETER_DEFAULT_VALUE, "Usage of inline parameter ''{0}'' in default value for another inline parameter is not supported", ELEMENT_TEXT, SHORT_NAMES_IN_TYPES);
|
||||
MAP.put(PRIVATE_INLINE_FUNCTIONS_RETURNING_ANONYMOUS_OBJECTS, "Return type of the private inline function can't be anonymous. It will be approximated to Any in 1.5." +
|
||||
"See https://youtrack.jetbrains.com/issue/KT-33917 for more details");
|
||||
//Inline non locals
|
||||
MAP.put(NON_LOCAL_RETURN_NOT_ALLOWED, "Can''t inline ''{0}'' here: it may contain non-local returns. Add ''crossinline'' modifier to parameter declaration ''{0}''", ELEMENT_TEXT);
|
||||
MAP.put(INLINE_CALL_CYCLE, "The ''{0}'' invocation is a part of inline cycle", NAME);
|
||||
|
||||
@@ -39,7 +39,8 @@ private val DEFAULT_DECLARATION_CHECKERS = listOf(
|
||||
MissingDependencySupertypeChecker.ForDeclarations,
|
||||
FunInterfaceDeclarationChecker(),
|
||||
DeprecatedSinceKotlinAnnotationChecker,
|
||||
ContractDescriptionBlockChecker
|
||||
ContractDescriptionBlockChecker,
|
||||
PrivateInlineFunctionsReturningAnonymousObjectsChecker
|
||||
)
|
||||
|
||||
private val DEFAULT_CALL_CHECKERS = listOf(
|
||||
|
||||
+36
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* 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.checkers
|
||||
|
||||
import org.jetbrains.kotlin.config.LanguageFeature
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.diagnostics.Errors
|
||||
import org.jetbrains.kotlin.psi.KtDeclaration
|
||||
import org.jetbrains.kotlin.psi.KtNamedFunction
|
||||
import org.jetbrains.kotlin.psi.psiUtil.isPrivate
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||
import org.jetbrains.kotlin.types.typeUtil.isAnyOrNullableAny
|
||||
|
||||
object PrivateInlineFunctionsReturningAnonymousObjectsChecker : DeclarationChecker {
|
||||
override fun check(declaration: KtDeclaration, descriptor: DeclarationDescriptor, context: DeclarationCheckerContext) {
|
||||
if (context.languageVersionSettings.supportsFeature(LanguageFeature.ForbidAnonymousReturnTypesInPrivateInlineFunctions))
|
||||
return
|
||||
|
||||
if (descriptor !is SimpleFunctionDescriptor || !descriptor.isInline || !declaration.isPrivate() || declaration !is KtNamedFunction)
|
||||
return
|
||||
|
||||
val returnTypeConstructor = descriptor.returnType?.constructor ?: return
|
||||
|
||||
if (returnTypeConstructor.supertypes.singleOrNull { it.isAnyOrNullableAny() } == null) return
|
||||
|
||||
val nameIdentifier = declaration.nameIdentifier ?: return
|
||||
val returnTypeDeclarationDescriptor = returnTypeConstructor.declarationDescriptor ?: return
|
||||
|
||||
if (DescriptorUtils.isAnonymousObject(returnTypeDeclarationDescriptor)) {
|
||||
context.trace.report(Errors.PRIVATE_INLINE_FUNCTIONS_RETURNING_ANONYMOUS_OBJECTS.on(nameIdentifier))
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
private inline fun foo(crossinline f: () -> Int) = object {
|
||||
fun bar(): Int = f()
|
||||
}
|
||||
|
||||
fun test(b: Boolean) {
|
||||
var x = foo { 1 }
|
||||
if (b) {
|
||||
x = foo { 2 }
|
||||
}
|
||||
x.bar()
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
private inline fun <!PRIVATE_INLINE_FUNCTIONS_RETURNING_ANONYMOUS_OBJECTS!>foo<!>(crossinline f: () -> Int) = object {
|
||||
fun bar(): Int = f()
|
||||
}
|
||||
|
||||
fun test(b: Boolean) {
|
||||
var x = foo { 1 }
|
||||
if (b) {
|
||||
x = foo { 2 }
|
||||
}
|
||||
x.bar()
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
package
|
||||
|
||||
private inline fun foo(/*0*/ crossinline f: () -> kotlin.Int): foo.<no name provided>
|
||||
public fun test(/*0*/ b: kotlin.Boolean): kotlin.Unit
|
||||
@@ -12438,6 +12438,11 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTestWithFirVali
|
||||
runTest("compiler/testData/diagnostics/tests/inline/recursion.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("returnedAnonymousObjects.kt")
|
||||
public void testReturnedAnonymousObjects() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/inline/returnedAnonymousObjects.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("returns.kt")
|
||||
public void testReturns() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/inline/returns.kt");
|
||||
|
||||
Generated
+5
@@ -12433,6 +12433,11 @@ public class DiagnosticsUsingJavacTestGenerated extends AbstractDiagnosticsUsing
|
||||
runTest("compiler/testData/diagnostics/tests/inline/recursion.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("returnedAnonymousObjects.kt")
|
||||
public void testReturnedAnonymousObjects() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/inline/returnedAnonymousObjects.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("returns.kt")
|
||||
public void testReturns() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/inline/returns.kt");
|
||||
|
||||
@@ -137,6 +137,7 @@ enum class LanguageFeature(
|
||||
ProhibitUsingNullableTypeParameterAgainstNotNullAnnotated(KOTLIN_1_5, kind = BUG_FIX),
|
||||
InferenceCompatibility(KOTLIN_1_5, kind = BUG_FIX),
|
||||
RequiredPrimaryConstructorDelegationCallInEnums(KOTLIN_1_5, kind = BUG_FIX),
|
||||
ForbidAnonymousReturnTypesInPrivateInlineFunctions(KOTLIN_1_5, kind = BUG_FIX),
|
||||
|
||||
// Temporarily disabled, see KT-27084/KT-22379
|
||||
SoundSmartcastFromLoopConditionForLoopAssignedVariables(sinceVersion = null, kind = BUG_FIX),
|
||||
|
||||
Reference in New Issue
Block a user