Deprecate ExtensionFunctionType on a non-function types
Related to KT-43527
This commit is contained in:
+6
@@ -951,6 +951,12 @@ internal val KT_DIAGNOSTIC_CONVERTER = KtDiagnosticConverterBuilder.buildConvert
|
|||||||
token,
|
token,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
add(FirErrors.WRONG_EXTENSION_FUNCTION_TYPE_WARNING) { firDiagnostic ->
|
||||||
|
WrongExtensionFunctionTypeWarningImpl(
|
||||||
|
firDiagnostic as KtPsiDiagnostic,
|
||||||
|
token,
|
||||||
|
)
|
||||||
|
}
|
||||||
add(FirErrors.OPT_IN_USAGE) { firDiagnostic ->
|
add(FirErrors.OPT_IN_USAGE) { firDiagnostic ->
|
||||||
OptInUsageImpl(
|
OptInUsageImpl(
|
||||||
firDiagnostic.a,
|
firDiagnostic.a,
|
||||||
|
|||||||
+4
@@ -684,6 +684,10 @@ sealed class KtFirDiagnostic<PSI : PsiElement> : KtDiagnosticWithPsi<PSI> {
|
|||||||
override val diagnosticClass get() = WrongExtensionFunctionType::class
|
override val diagnosticClass get() = WrongExtensionFunctionType::class
|
||||||
}
|
}
|
||||||
|
|
||||||
|
abstract class WrongExtensionFunctionTypeWarning : KtFirDiagnostic<KtAnnotationEntry>() {
|
||||||
|
override val diagnosticClass get() = WrongExtensionFunctionTypeWarning::class
|
||||||
|
}
|
||||||
|
|
||||||
abstract class OptInUsage : KtFirDiagnostic<PsiElement>() {
|
abstract class OptInUsage : KtFirDiagnostic<PsiElement>() {
|
||||||
override val diagnosticClass get() = OptInUsage::class
|
override val diagnosticClass get() = OptInUsage::class
|
||||||
abstract val optInMarkerFqName: FqName
|
abstract val optInMarkerFqName: FqName
|
||||||
|
|||||||
+5
@@ -821,6 +821,11 @@ internal class WrongExtensionFunctionTypeImpl(
|
|||||||
override val token: ValidityToken,
|
override val token: ValidityToken,
|
||||||
) : KtFirDiagnostic.WrongExtensionFunctionType(), KtAbstractFirDiagnostic<KtAnnotationEntry>
|
) : KtFirDiagnostic.WrongExtensionFunctionType(), KtAbstractFirDiagnostic<KtAnnotationEntry>
|
||||||
|
|
||||||
|
internal class WrongExtensionFunctionTypeWarningImpl(
|
||||||
|
override val firDiagnostic: KtPsiDiagnostic,
|
||||||
|
override val token: ValidityToken,
|
||||||
|
) : KtFirDiagnostic.WrongExtensionFunctionTypeWarning(), KtAbstractFirDiagnostic<KtAnnotationEntry>
|
||||||
|
|
||||||
internal class OptInUsageImpl(
|
internal class OptInUsageImpl(
|
||||||
override val optInMarkerFqName: FqName,
|
override val optInMarkerFqName: FqName,
|
||||||
override val message: String,
|
override val message: String,
|
||||||
|
|||||||
+1
@@ -288,6 +288,7 @@ object DIAGNOSTICS_LIST : DiagnosticList("FirErrors") {
|
|||||||
val REPEATED_ANNOTATION_WARNING by warning<KtAnnotationEntry>()
|
val REPEATED_ANNOTATION_WARNING by warning<KtAnnotationEntry>()
|
||||||
val NOT_A_CLASS by error<PsiElement>()
|
val NOT_A_CLASS by error<PsiElement>()
|
||||||
val WRONG_EXTENSION_FUNCTION_TYPE by error<KtAnnotationEntry>()
|
val WRONG_EXTENSION_FUNCTION_TYPE by error<KtAnnotationEntry>()
|
||||||
|
val WRONG_EXTENSION_FUNCTION_TYPE_WARNING by warning<KtAnnotationEntry>()
|
||||||
}
|
}
|
||||||
|
|
||||||
val OPT_IN by object : DiagnosticGroup("OptIn") {
|
val OPT_IN by object : DiagnosticGroup("OptIn") {
|
||||||
|
|||||||
@@ -254,6 +254,7 @@ object FirErrors {
|
|||||||
val REPEATED_ANNOTATION_WARNING by warning0<KtAnnotationEntry>()
|
val REPEATED_ANNOTATION_WARNING by warning0<KtAnnotationEntry>()
|
||||||
val NOT_A_CLASS by error0<PsiElement>()
|
val NOT_A_CLASS by error0<PsiElement>()
|
||||||
val WRONG_EXTENSION_FUNCTION_TYPE by error0<KtAnnotationEntry>()
|
val WRONG_EXTENSION_FUNCTION_TYPE by error0<KtAnnotationEntry>()
|
||||||
|
val WRONG_EXTENSION_FUNCTION_TYPE_WARNING by warning0<KtAnnotationEntry>()
|
||||||
|
|
||||||
// OptIn
|
// OptIn
|
||||||
val OPT_IN_USAGE by warning2<PsiElement, FqName, String>(SourceElementPositioningStrategies.REFERENCE_BY_QUALIFIED)
|
val OPT_IN_USAGE by warning2<PsiElement, FqName, String>(SourceElementPositioningStrategies.REFERENCE_BY_QUALIFIED)
|
||||||
|
|||||||
+9
-1
@@ -5,6 +5,7 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.fir.analysis.checkers.type
|
package org.jetbrains.kotlin.fir.analysis.checkers.type
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.config.LanguageFeature
|
||||||
import org.jetbrains.kotlin.descriptors.annotations.KotlinTarget
|
import org.jetbrains.kotlin.descriptors.annotations.KotlinTarget
|
||||||
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
||||||
import org.jetbrains.kotlin.fir.analysis.checkers.getAllowedAnnotationTargets
|
import org.jetbrains.kotlin.fir.analysis.checkers.getAllowedAnnotationTargets
|
||||||
@@ -33,7 +34,14 @@ object FirTypeAnnotationChecker : FirTypeRefChecker() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (annotation.classId == StandardClassIds.Annotations.ExtensionFunctionType) {
|
if (annotation.classId == StandardClassIds.Annotations.ExtensionFunctionType) {
|
||||||
if (typeRef.type.isBuiltinFunctionalType(context.session) && typeRef.type.typeArguments.size <= 1) {
|
if (!typeRef.type.isBuiltinFunctionalType(context.session)) {
|
||||||
|
if (context.languageVersionSettings.supportsFeature(LanguageFeature.ForbidExtensionFunctionTypeOnNonFunctionTypes)) {
|
||||||
|
reporter.reportOn(annotation.source, FirErrors.WRONG_EXTENSION_FUNCTION_TYPE, context)
|
||||||
|
} else {
|
||||||
|
reporter.reportOn(annotation.source, FirErrors.WRONG_EXTENSION_FUNCTION_TYPE_WARNING, context)
|
||||||
|
}
|
||||||
|
|
||||||
|
} else if (typeRef.type.typeArguments.size <= 1) {
|
||||||
reporter.reportOn(annotation.source, FirErrors.WRONG_EXTENSION_FUNCTION_TYPE, context)
|
reporter.reportOn(annotation.source, FirErrors.WRONG_EXTENSION_FUNCTION_TYPE, context)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+9
-1
@@ -562,6 +562,7 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.VIRTUAL_MEMBER_HI
|
|||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.WRONG_ANNOTATION_TARGET
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.WRONG_ANNOTATION_TARGET
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.WRONG_ANNOTATION_TARGET_WITH_USE_SITE_TARGET
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.WRONG_ANNOTATION_TARGET_WITH_USE_SITE_TARGET
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.WRONG_EXTENSION_FUNCTION_TYPE
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.WRONG_EXTENSION_FUNCTION_TYPE
|
||||||
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.WRONG_EXTENSION_FUNCTION_TYPE_WARNING
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.WRONG_GETTER_RETURN_TYPE
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.WRONG_GETTER_RETURN_TYPE
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.WRONG_INVOCATION_KIND
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.WRONG_INVOCATION_KIND
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.WRONG_LONG_SUFFIX
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.WRONG_LONG_SUFFIX
|
||||||
@@ -854,7 +855,14 @@ object FirErrorsDefaultMessages : BaseDiagnosticRendererFactory() {
|
|||||||
"Opt-in requirement marker annotation on override makes no sense without the same marker on base declaration"
|
"Opt-in requirement marker annotation on override makes no sense without the same marker on base declaration"
|
||||||
)
|
)
|
||||||
map.put(NOT_A_CLASS, "Not a class")
|
map.put(NOT_A_CLASS, "Not a class")
|
||||||
map.put(WRONG_EXTENSION_FUNCTION_TYPE, "ExtensionFunctionType is forbidden on a function type without parameters")
|
map.put(
|
||||||
|
WRONG_EXTENSION_FUNCTION_TYPE,
|
||||||
|
"ExtensionFunctionType is forbidden on a function type without parameters or on a non-function type"
|
||||||
|
)
|
||||||
|
map.put(
|
||||||
|
WRONG_EXTENSION_FUNCTION_TYPE_WARNING,
|
||||||
|
"ExtensionFunctionType makes no sense on a non-function type. It will be an error in a future release."
|
||||||
|
)
|
||||||
|
|
||||||
// Exposed visibility group // #
|
// Exposed visibility group // #
|
||||||
map.put(
|
map.put(
|
||||||
|
|||||||
@@ -279,6 +279,7 @@ public interface Errors {
|
|||||||
DiagnosticFactory0<KtAnnotationEntry> REPEATED_ANNOTATION_WARNING = DiagnosticFactory0.create(WARNING);
|
DiagnosticFactory0<KtAnnotationEntry> REPEATED_ANNOTATION_WARNING = DiagnosticFactory0.create(WARNING);
|
||||||
DiagnosticFactory0<KtAnnotationEntry> NON_SOURCE_ANNOTATION_ON_INLINED_LAMBDA_EXPRESSION = DiagnosticFactory0.create(ERROR);
|
DiagnosticFactory0<KtAnnotationEntry> NON_SOURCE_ANNOTATION_ON_INLINED_LAMBDA_EXPRESSION = DiagnosticFactory0.create(ERROR);
|
||||||
DiagnosticFactory0<KtAnnotationEntry> WRONG_EXTENSION_FUNCTION_TYPE = DiagnosticFactory0.create(ERROR);
|
DiagnosticFactory0<KtAnnotationEntry> WRONG_EXTENSION_FUNCTION_TYPE = DiagnosticFactory0.create(ERROR);
|
||||||
|
DiagnosticFactory0<KtAnnotationEntry> WRONG_EXTENSION_FUNCTION_TYPE_WARNING = DiagnosticFactory0.create(WARNING);
|
||||||
|
|
||||||
// Annotations
|
// Annotations
|
||||||
|
|
||||||
|
|||||||
+2
-1
@@ -146,7 +146,8 @@ public class DefaultErrorMessages {
|
|||||||
MAP.put(REPEATED_ANNOTATION, "This annotation is not repeatable");
|
MAP.put(REPEATED_ANNOTATION, "This annotation is not repeatable");
|
||||||
MAP.put(REPEATED_ANNOTATION_WARNING, "This annotation is not repeatable");
|
MAP.put(REPEATED_ANNOTATION_WARNING, "This annotation is not repeatable");
|
||||||
MAP.put(NON_SOURCE_ANNOTATION_ON_INLINED_LAMBDA_EXPRESSION, "The lambda expression here is an inlined argument so this annotation cannot be stored anywhere");
|
MAP.put(NON_SOURCE_ANNOTATION_ON_INLINED_LAMBDA_EXPRESSION, "The lambda expression here is an inlined argument so this annotation cannot be stored anywhere");
|
||||||
MAP.put(WRONG_EXTENSION_FUNCTION_TYPE, "ExtensionFunctionType is forbidden on a function type without parameters");
|
MAP.put(WRONG_EXTENSION_FUNCTION_TYPE, "ExtensionFunctionType is forbidden on a function type without parameters or on a non-function type");
|
||||||
|
MAP.put(WRONG_EXTENSION_FUNCTION_TYPE_WARNING, "ExtensionFunctionType makes no sense on a non-function type. It will be an error in a future release.");
|
||||||
|
|
||||||
MAP.put(INAPPLICABLE_TARGET_ON_PROPERTY, "''@{0}:'' annotations could be applied only to property declarations", TO_STRING);
|
MAP.put(INAPPLICABLE_TARGET_ON_PROPERTY, "''@{0}:'' annotations could be applied only to property declarations", TO_STRING);
|
||||||
MAP.put(INAPPLICABLE_TARGET_PROPERTY_IMMUTABLE, "''@{0}:'' annotations could be applied only to mutable properties", TO_STRING);
|
MAP.put(INAPPLICABLE_TARGET_PROPERTY_IMMUTABLE, "''@{0}:'' annotations could be applied only to mutable properties", TO_STRING);
|
||||||
|
|||||||
@@ -185,9 +185,17 @@ class AnnotationChecker(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (descriptor?.annotationClass?.classId == StandardClassIds.Annotations.ExtensionFunctionType) {
|
if (descriptor?.annotationClass?.classId == StandardClassIds.Annotations.ExtensionFunctionType) {
|
||||||
val type = trace[BindingContext.TYPE, reference]
|
val type = trace[BindingContext.TYPE, reference] ?: trace[BindingContext.ABBREVIATED_TYPE, reference]
|
||||||
if (type != null && type.isFunctionOrKFunctionTypeWithAnySuspendability && type.arguments.size <= 1) {
|
if (type != null) {
|
||||||
trace.report(Errors.WRONG_EXTENSION_FUNCTION_TYPE.on(entry))
|
if (!type.isFunctionOrKFunctionTypeWithAnySuspendability) {
|
||||||
|
if (languageVersionSettings.supportsFeature(ForbidExtensionFunctionTypeOnNonFunctionTypes)) {
|
||||||
|
trace.report(Errors.WRONG_EXTENSION_FUNCTION_TYPE.on(entry))
|
||||||
|
} else {
|
||||||
|
trace.report(Errors.WRONG_EXTENSION_FUNCTION_TYPE_WARNING.on(entry))
|
||||||
|
}
|
||||||
|
} else if (type.arguments.size <= 1) {
|
||||||
|
trace.report(Errors.WRONG_EXTENSION_FUNCTION_TYPE.on(entry))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ fun foo(a: (String) -> Unit) {
|
|||||||
|
|
||||||
interface A : (String) -> Unit {}
|
interface A : (String) -> Unit {}
|
||||||
|
|
||||||
fun foo(a: @ExtensionFunctionType A) {
|
fun foo(a: <!WRONG_EXTENSION_FUNCTION_TYPE_WARNING!>@ExtensionFunctionType<!> A) {
|
||||||
// @Extension annotation on an unrelated type shouldn't have any effect on this diagnostic.
|
// @Extension annotation on an unrelated type shouldn't have any effect on this diagnostic.
|
||||||
// Only kotlin.Function{n} type annotated with @Extension should
|
// Only kotlin.Function{n} type annotated with @Extension should
|
||||||
"".a()
|
"".a()
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ fun foo(a: (String) -> Unit) {
|
|||||||
|
|
||||||
interface A : (String) -> Unit {}
|
interface A : (String) -> Unit {}
|
||||||
|
|
||||||
fun foo(a: @ExtensionFunctionType A) {
|
fun foo(a: <!WRONG_EXTENSION_FUNCTION_TYPE_WARNING!>@ExtensionFunctionType<!> A) {
|
||||||
// @Extension annotation on an unrelated type shouldn't have any effect on this diagnostic.
|
// @Extension annotation on an unrelated type shouldn't have any effect on this diagnostic.
|
||||||
// Only kotlin.Function{n} type annotated with @Extension should
|
// Only kotlin.Function{n} type annotated with @Extension should
|
||||||
"".<!UNRESOLVED_REFERENCE!>a<!>()
|
"".<!UNRESOLVED_REFERENCE!>a<!>()
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
// WITH_STDLIB
|
// WITH_STDLIB
|
||||||
|
// !LANGUAGE: +ForbidExtensionFunctionTypeOnNonFunctionTypes
|
||||||
// This test checks that annotations on extension function types are preserved. See the corresponding .txt file
|
// This test checks that annotations on extension function types are preserved. See the corresponding .txt file
|
||||||
|
|
||||||
@Target(AnnotationTarget.TYPE)
|
@Target(AnnotationTarget.TYPE)
|
||||||
@@ -17,4 +18,6 @@ interface Some {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun f7(x: <!WRONG_EXTENSION_FUNCTION_TYPE!>@ExtensionFunctionType<!> Function0<Int>)
|
fun f7(x: <!WRONG_EXTENSION_FUNCTION_TYPE!>@ExtensionFunctionType<!> Function0<Int>)
|
||||||
|
|
||||||
|
fun f8(x: <!WRONG_EXTENSION_FUNCTION_TYPE!>@ExtensionFunctionType<!> Int)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
// WITH_STDLIB
|
// WITH_STDLIB
|
||||||
|
// !LANGUAGE: +ForbidExtensionFunctionTypeOnNonFunctionTypes
|
||||||
// This test checks that annotations on extension function types are preserved. See the corresponding .txt file
|
// This test checks that annotations on extension function types are preserved. See the corresponding .txt file
|
||||||
|
|
||||||
@Target(AnnotationTarget.TYPE)
|
@Target(AnnotationTarget.TYPE)
|
||||||
@@ -17,4 +18,6 @@ interface Some {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun f7(x: <!WRONG_EXTENSION_FUNCTION_TYPE!>@ExtensionFunctionType<!> Function0<Int>)
|
fun f7(x: <!WRONG_EXTENSION_FUNCTION_TYPE!>@ExtensionFunctionType<!> Function0<Int>)
|
||||||
|
|
||||||
|
fun f8(x: <!WRONG_EXTENSION_FUNCTION_TYPE!>@ExtensionFunctionType<!> Int)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ public interface Some {
|
|||||||
public abstract fun f5(): kotlin.Int.(???) -> kotlin.Int
|
public abstract fun f5(): kotlin.Int.(???) -> kotlin.Int
|
||||||
public open fun f6(/*0*/ x: kotlin.Int.(???) -> kotlin.Int): kotlin.Unit
|
public open fun f6(/*0*/ x: kotlin.Int.(???) -> kotlin.Int): kotlin.Unit
|
||||||
public abstract fun f7(/*0*/ x: kotlin.Int.(???) -> kotlin.Int): kotlin.Unit
|
public abstract fun f7(/*0*/ x: kotlin.Int.(???) -> kotlin.Int): kotlin.Unit
|
||||||
|
public abstract fun f8(/*0*/ x: @kotlin.ExtensionFunctionType kotlin.Int): kotlin.Unit
|
||||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
// FIR_IDENTICAL
|
// FIR_IDENTICAL
|
||||||
|
// !LANGUAGE: -ForbidExtensionFunctionTypeOnNonFunctionTypes
|
||||||
@Target(AnnotationTarget.TYPE)
|
@Target(AnnotationTarget.TYPE)
|
||||||
annotation class Ann1
|
annotation class Ann1
|
||||||
|
|
||||||
@@ -9,8 +10,7 @@ typealias Alias1 = @Ann1 String
|
|||||||
typealias Alias2 = @Ann2 Alias1
|
typealias Alias2 = @Ann2 Alias1
|
||||||
fun test1(a: Alias2) = a
|
fun test1(a: Alias2) = a
|
||||||
|
|
||||||
// NB @ExtensionFunctionType on non-functional type is not an error
|
typealias Alias3 = <!WRONG_EXTENSION_FUNCTION_TYPE_WARNING!>@ExtensionFunctionType<!> Alias1
|
||||||
typealias Alias3 = @ExtensionFunctionType Alias1
|
|
||||||
fun test2(a: Alias3) = a
|
fun test2(a: Alias3) = a
|
||||||
|
|
||||||
typealias LA1 = List<@Ann2 Alias1>
|
typealias LA1 = List<@Ann2 Alias1>
|
||||||
|
|||||||
@@ -263,6 +263,7 @@ enum class LanguageFeature(
|
|||||||
ProhibitConstructorCallOnFunctionalSupertype(KOTLIN_1_9, kind = BUG_FIX), // KT-46344
|
ProhibitConstructorCallOnFunctionalSupertype(KOTLIN_1_9, kind = BUG_FIX), // KT-46344
|
||||||
ProhibitArrayLiteralsInCompanionOfAnnotation(KOTLIN_1_9, kind = BUG_FIX), // KT-39041
|
ProhibitArrayLiteralsInCompanionOfAnnotation(KOTLIN_1_9, kind = BUG_FIX), // KT-39041
|
||||||
ProhibitCyclesInAnnotations(KOTLIN_1_9, kind = BUG_FIX), // KT-49110
|
ProhibitCyclesInAnnotations(KOTLIN_1_9, kind = BUG_FIX), // KT-49110
|
||||||
|
ForbidExtensionFunctionTypeOnNonFunctionTypes(KOTLIN_1_9), // related to KT-43527
|
||||||
|
|
||||||
// Temporarily disabled, see KT-27084/KT-22379
|
// Temporarily disabled, see KT-27084/KT-22379
|
||||||
SoundSmartcastFromLoopConditionForLoopAssignedVariables(sinceVersion = null, kind = BUG_FIX),
|
SoundSmartcastFromLoopConditionForLoopAssignedVariables(sinceVersion = null, kind = BUG_FIX),
|
||||||
|
|||||||
Reference in New Issue
Block a user