[FE] Don't issue a deprecation warning for open val deferred init when the property is unconditionally effectively final
^KT-61228 Fixed Review: https://jetbrains.team/p/kt/reviews/11694/timeline
This commit is contained in:
+24
@@ -3134,6 +3134,30 @@ public class DiagnosticCompilerTestFE10TestdataTestGenerated extends AbstractDia
|
|||||||
runTest("compiler/testData/diagnostics/tests/backingField/MustBeInitializedEffectivelyFinalOn.kt");
|
runTest("compiler/testData/diagnostics/tests/backingField/MustBeInitializedEffectivelyFinalOn.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("OpenValDeferredInitError_InFinalClass_DisableEffectivelyFinal.kt")
|
||||||
|
public void testOpenValDeferredInitError_InFinalClass_DisableEffectivelyFinal() throws Exception {
|
||||||
|
runTest("compiler/testData/diagnostics/tests/backingField/OpenValDeferredInitError_InFinalClass_DisableEffectivelyFinal.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("OpenValDeferredInitError_InFinalClass_EnableEffectivelyFinal.kt")
|
||||||
|
public void testOpenValDeferredInitError_InFinalClass_EnableEffectivelyFinal() throws Exception {
|
||||||
|
runTest("compiler/testData/diagnostics/tests/backingField/OpenValDeferredInitError_InFinalClass_EnableEffectivelyFinal.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("OpenValDeferredInitWarning_InFinalClass_DisableEffectivelyFinal.kt")
|
||||||
|
public void testOpenValDeferredInitWarning_InFinalClass_DisableEffectivelyFinal() throws Exception {
|
||||||
|
runTest("compiler/testData/diagnostics/tests/backingField/OpenValDeferredInitWarning_InFinalClass_DisableEffectivelyFinal.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("OpenValDeferredInitWarning_InFinalClass_EnableEffectivelyFinal.kt")
|
||||||
|
public void testOpenValDeferredInitWarning_InFinalClass_EnableEffectivelyFinal() throws Exception {
|
||||||
|
runTest("compiler/testData/diagnostics/tests/backingField/OpenValDeferredInitWarning_InFinalClass_EnableEffectivelyFinal.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@TestMetadata("OpenValPartialDeferredInitErrorAnyway.kt")
|
@TestMetadata("OpenValPartialDeferredInitErrorAnyway.kt")
|
||||||
public void testOpenValPartialDeferredInitErrorAnyway() throws Exception {
|
public void testOpenValPartialDeferredInitErrorAnyway() throws Exception {
|
||||||
|
|||||||
+24
@@ -3134,6 +3134,30 @@ public class LLFirPreresolvedReversedDiagnosticCompilerFE10TestDataTestGenerated
|
|||||||
runTest("compiler/testData/diagnostics/tests/backingField/MustBeInitializedEffectivelyFinalOn.kt");
|
runTest("compiler/testData/diagnostics/tests/backingField/MustBeInitializedEffectivelyFinalOn.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("OpenValDeferredInitError_InFinalClass_DisableEffectivelyFinal.kt")
|
||||||
|
public void testOpenValDeferredInitError_InFinalClass_DisableEffectivelyFinal() throws Exception {
|
||||||
|
runTest("compiler/testData/diagnostics/tests/backingField/OpenValDeferredInitError_InFinalClass_DisableEffectivelyFinal.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("OpenValDeferredInitError_InFinalClass_EnableEffectivelyFinal.kt")
|
||||||
|
public void testOpenValDeferredInitError_InFinalClass_EnableEffectivelyFinal() throws Exception {
|
||||||
|
runTest("compiler/testData/diagnostics/tests/backingField/OpenValDeferredInitError_InFinalClass_EnableEffectivelyFinal.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("OpenValDeferredInitWarning_InFinalClass_DisableEffectivelyFinal.kt")
|
||||||
|
public void testOpenValDeferredInitWarning_InFinalClass_DisableEffectivelyFinal() throws Exception {
|
||||||
|
runTest("compiler/testData/diagnostics/tests/backingField/OpenValDeferredInitWarning_InFinalClass_DisableEffectivelyFinal.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("OpenValDeferredInitWarning_InFinalClass_EnableEffectivelyFinal.kt")
|
||||||
|
public void testOpenValDeferredInitWarning_InFinalClass_EnableEffectivelyFinal() throws Exception {
|
||||||
|
runTest("compiler/testData/diagnostics/tests/backingField/OpenValDeferredInitWarning_InFinalClass_EnableEffectivelyFinal.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@TestMetadata("OpenValPartialDeferredInitErrorAnyway.kt")
|
@TestMetadata("OpenValPartialDeferredInitErrorAnyway.kt")
|
||||||
public void testOpenValPartialDeferredInitErrorAnyway() throws Exception {
|
public void testOpenValPartialDeferredInitErrorAnyway() throws Exception {
|
||||||
|
|||||||
+24
@@ -3134,6 +3134,30 @@ public class FirLightTreeOldFrontendDiagnosticsTestGenerated extends AbstractFir
|
|||||||
runTest("compiler/testData/diagnostics/tests/backingField/MustBeInitializedEffectivelyFinalOn.kt");
|
runTest("compiler/testData/diagnostics/tests/backingField/MustBeInitializedEffectivelyFinalOn.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("OpenValDeferredInitError_InFinalClass_DisableEffectivelyFinal.kt")
|
||||||
|
public void testOpenValDeferredInitError_InFinalClass_DisableEffectivelyFinal() throws Exception {
|
||||||
|
runTest("compiler/testData/diagnostics/tests/backingField/OpenValDeferredInitError_InFinalClass_DisableEffectivelyFinal.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("OpenValDeferredInitError_InFinalClass_EnableEffectivelyFinal.kt")
|
||||||
|
public void testOpenValDeferredInitError_InFinalClass_EnableEffectivelyFinal() throws Exception {
|
||||||
|
runTest("compiler/testData/diagnostics/tests/backingField/OpenValDeferredInitError_InFinalClass_EnableEffectivelyFinal.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("OpenValDeferredInitWarning_InFinalClass_DisableEffectivelyFinal.kt")
|
||||||
|
public void testOpenValDeferredInitWarning_InFinalClass_DisableEffectivelyFinal() throws Exception {
|
||||||
|
runTest("compiler/testData/diagnostics/tests/backingField/OpenValDeferredInitWarning_InFinalClass_DisableEffectivelyFinal.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("OpenValDeferredInitWarning_InFinalClass_EnableEffectivelyFinal.kt")
|
||||||
|
public void testOpenValDeferredInitWarning_InFinalClass_EnableEffectivelyFinal() throws Exception {
|
||||||
|
runTest("compiler/testData/diagnostics/tests/backingField/OpenValDeferredInitWarning_InFinalClass_EnableEffectivelyFinal.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@TestMetadata("OpenValPartialDeferredInitErrorAnyway.kt")
|
@TestMetadata("OpenValPartialDeferredInitErrorAnyway.kt")
|
||||||
public void testOpenValPartialDeferredInitErrorAnyway() throws Exception {
|
public void testOpenValPartialDeferredInitErrorAnyway() throws Exception {
|
||||||
|
|||||||
+24
@@ -3140,6 +3140,30 @@ public class FirPsiOldFrontendDiagnosticsTestGenerated extends AbstractFirPsiDia
|
|||||||
runTest("compiler/testData/diagnostics/tests/backingField/MustBeInitializedEffectivelyFinalOn.kt");
|
runTest("compiler/testData/diagnostics/tests/backingField/MustBeInitializedEffectivelyFinalOn.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("OpenValDeferredInitError_InFinalClass_DisableEffectivelyFinal.kt")
|
||||||
|
public void testOpenValDeferredInitError_InFinalClass_DisableEffectivelyFinal() throws Exception {
|
||||||
|
runTest("compiler/testData/diagnostics/tests/backingField/OpenValDeferredInitError_InFinalClass_DisableEffectivelyFinal.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("OpenValDeferredInitError_InFinalClass_EnableEffectivelyFinal.kt")
|
||||||
|
public void testOpenValDeferredInitError_InFinalClass_EnableEffectivelyFinal() throws Exception {
|
||||||
|
runTest("compiler/testData/diagnostics/tests/backingField/OpenValDeferredInitError_InFinalClass_EnableEffectivelyFinal.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("OpenValDeferredInitWarning_InFinalClass_DisableEffectivelyFinal.kt")
|
||||||
|
public void testOpenValDeferredInitWarning_InFinalClass_DisableEffectivelyFinal() throws Exception {
|
||||||
|
runTest("compiler/testData/diagnostics/tests/backingField/OpenValDeferredInitWarning_InFinalClass_DisableEffectivelyFinal.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("OpenValDeferredInitWarning_InFinalClass_EnableEffectivelyFinal.kt")
|
||||||
|
public void testOpenValDeferredInitWarning_InFinalClass_EnableEffectivelyFinal() throws Exception {
|
||||||
|
runTest("compiler/testData/diagnostics/tests/backingField/OpenValDeferredInitWarning_InFinalClass_EnableEffectivelyFinal.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@TestMetadata("OpenValPartialDeferredInitErrorAnyway.kt")
|
@TestMetadata("OpenValPartialDeferredInitErrorAnyway.kt")
|
||||||
public void testOpenValPartialDeferredInitErrorAnyway() throws Exception {
|
public void testOpenValPartialDeferredInitErrorAnyway() throws Exception {
|
||||||
|
|||||||
+27
-9
@@ -10,7 +10,6 @@ import org.jetbrains.kotlin.KtSourceElement
|
|||||||
import org.jetbrains.kotlin.config.LanguageFeature
|
import org.jetbrains.kotlin.config.LanguageFeature
|
||||||
import org.jetbrains.kotlin.config.LanguageVersionSettings
|
import org.jetbrains.kotlin.config.LanguageVersionSettings
|
||||||
import org.jetbrains.kotlin.descriptors.Modality
|
import org.jetbrains.kotlin.descriptors.Modality
|
||||||
import org.jetbrains.kotlin.descriptors.Visibilities
|
|
||||||
import org.jetbrains.kotlin.diagnostics.DiagnosticReporter
|
import org.jetbrains.kotlin.diagnostics.DiagnosticReporter
|
||||||
import org.jetbrains.kotlin.diagnostics.KtDiagnosticFactory0
|
import org.jetbrains.kotlin.diagnostics.KtDiagnosticFactory0
|
||||||
import org.jetbrains.kotlin.diagnostics.reportOn
|
import org.jetbrains.kotlin.diagnostics.reportOn
|
||||||
@@ -133,7 +132,24 @@ internal fun checkPropertyInitializer(
|
|||||||
if (property.receiverParameter != null && !property.hasAllAccessorImplementation) {
|
if (property.receiverParameter != null && !property.hasAllAccessorImplementation) {
|
||||||
reporter.reportOn(propertySource, FirErrors.EXTENSION_PROPERTY_MUST_HAVE_ACCESSORS_OR_BE_ABSTRACT, context)
|
reporter.reportOn(propertySource, FirErrors.EXTENSION_PROPERTY_MUST_HAVE_ACCESSORS_OR_BE_ABSTRACT, context)
|
||||||
} else if (reachable) {
|
} else if (reachable) {
|
||||||
reportMustBeInitialized(property, isDefinitelyAssignedInConstructor, containingClass, propertySource, reporter, context)
|
val isOpenValDeferredInitDeprecationWarning =
|
||||||
|
!context.languageVersionSettings.supportsFeature(LanguageFeature.ProhibitOpenValDeferredInitialization) &&
|
||||||
|
property.getEffectiveModality(containingClass, context.languageVersionSettings) == Modality.OPEN && property.isVal &&
|
||||||
|
isDefinitelyAssignedInConstructor
|
||||||
|
// KT-61228
|
||||||
|
val isFalsePositiveDeferredInitDeprecationWarning = isOpenValDeferredInitDeprecationWarning &&
|
||||||
|
property.getEffectiveModality(containingClass) == Modality.FINAL
|
||||||
|
if (!isFalsePositiveDeferredInitDeprecationWarning) {
|
||||||
|
reportMustBeInitialized(
|
||||||
|
property,
|
||||||
|
isDefinitelyAssignedInConstructor,
|
||||||
|
containingClass,
|
||||||
|
propertySource,
|
||||||
|
isOpenValDeferredInitDeprecationWarning,
|
||||||
|
reporter,
|
||||||
|
context
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (property.isLateInit) {
|
if (property.isLateInit) {
|
||||||
@@ -156,6 +172,7 @@ private fun reportMustBeInitialized(
|
|||||||
isDefinitelyAssignedInConstructor: Boolean,
|
isDefinitelyAssignedInConstructor: Boolean,
|
||||||
containingClass: FirClass?,
|
containingClass: FirClass?,
|
||||||
propertySource: KtSourceElement,
|
propertySource: KtSourceElement,
|
||||||
|
isOpenValDeferredInitDeprecationWarning: Boolean,
|
||||||
reporter: DiagnosticReporter,
|
reporter: DiagnosticReporter,
|
||||||
context: CheckerContext,
|
context: CheckerContext,
|
||||||
) {
|
) {
|
||||||
@@ -165,10 +182,6 @@ private fun reportMustBeInitialized(
|
|||||||
property.getEffectiveModality(containingClass, context.languageVersionSettings) != Modality.FINAL &&
|
property.getEffectiveModality(containingClass, context.languageVersionSettings) != Modality.FINAL &&
|
||||||
isDefinitelyAssignedInConstructor
|
isDefinitelyAssignedInConstructor
|
||||||
val suggestMakingItAbstract = containingClass != null && !property.hasAnyAccessorImplementation
|
val suggestMakingItAbstract = containingClass != null && !property.hasAnyAccessorImplementation
|
||||||
val isOpenValDeferredInitDeprecationWarning =
|
|
||||||
!context.languageVersionSettings.supportsFeature(LanguageFeature.ProhibitOpenValDeferredInitialization) &&
|
|
||||||
property.getEffectiveModality(containingClass, context.languageVersionSettings) == Modality.OPEN && property.isVal &&
|
|
||||||
isDefinitelyAssignedInConstructor
|
|
||||||
if (isOpenValDeferredInitDeprecationWarning && !suggestMakingItFinal && suggestMakingItAbstract) {
|
if (isOpenValDeferredInitDeprecationWarning && !suggestMakingItFinal && suggestMakingItAbstract) {
|
||||||
error("Not reachable case. Every \"open val + deferred init\" case that could be made `abstract`, also could be made `final`")
|
error("Not reachable case. Every \"open val + deferred init\" case that could be made `abstract`, also could be made `final`")
|
||||||
}
|
}
|
||||||
@@ -212,9 +225,14 @@ private val FirProperty.hasAnyAccessorImplementation: Boolean
|
|||||||
private val FirProperty.hasAllAccessorImplementation: Boolean
|
private val FirProperty.hasAllAccessorImplementation: Boolean
|
||||||
get() = getter.hasImplementation && (isVal || setter.hasImplementation)
|
get() = getter.hasImplementation && (isVal || setter.hasImplementation)
|
||||||
|
|
||||||
private fun FirProperty.getEffectiveModality(containingClass: FirClass?, languageVersionSettings: LanguageVersionSettings): Modality? =
|
private fun FirProperty.getEffectiveModality(containingClass: FirClass?): Modality? =
|
||||||
when (languageVersionSettings.supportsFeature(LanguageFeature.TakeIntoAccountEffectivelyFinalInMustBeInitializedCheck) &&
|
when (status.modality == Modality.OPEN && containingClass?.status?.modality == Modality.FINAL) {
|
||||||
status.modality == Modality.OPEN && containingClass?.status?.modality == Modality.FINAL) {
|
|
||||||
true -> Modality.FINAL
|
true -> Modality.FINAL
|
||||||
false -> status.modality
|
false -> status.modality
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun FirProperty.getEffectiveModality(containingClass: FirClass?, languageVersionSettings: LanguageVersionSettings): Modality? =
|
||||||
|
when (languageVersionSettings.supportsFeature(LanguageFeature.TakeIntoAccountEffectivelyFinalInMustBeInitializedCheck)) {
|
||||||
|
true -> getEffectiveModality(containingClass)
|
||||||
|
false -> status.modality
|
||||||
|
}
|
||||||
|
|||||||
@@ -38,7 +38,6 @@ import org.jetbrains.kotlin.resolve.DescriptorUtils.classCanHaveOpenMembers
|
|||||||
import org.jetbrains.kotlin.resolve.calls.results.TypeSpecificityComparator
|
import org.jetbrains.kotlin.resolve.calls.results.TypeSpecificityComparator
|
||||||
import org.jetbrains.kotlin.resolve.checkers.PlatformDiagnosticSuppressor
|
import org.jetbrains.kotlin.resolve.checkers.PlatformDiagnosticSuppressor
|
||||||
import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns
|
import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns
|
||||||
import org.jetbrains.kotlin.resolve.descriptorUtil.isAnnotationConstructor
|
|
||||||
import org.jetbrains.kotlin.resolve.descriptorUtil.isEffectivelyExternal
|
import org.jetbrains.kotlin.resolve.descriptorUtil.isEffectivelyExternal
|
||||||
import org.jetbrains.kotlin.resolve.inline.isInlineOnly
|
import org.jetbrains.kotlin.resolve.inline.isInlineOnly
|
||||||
import org.jetbrains.kotlin.resolve.source.KotlinSourceElement
|
import org.jetbrains.kotlin.resolve.source.KotlinSourceElement
|
||||||
@@ -796,14 +795,25 @@ class DeclarationsChecker(
|
|||||||
if (propertyDescriptor.extensionReceiverParameter != null && !hasAnyAccessorImplementation) {
|
if (propertyDescriptor.extensionReceiverParameter != null && !hasAnyAccessorImplementation) {
|
||||||
trace.report(EXTENSION_PROPERTY_MUST_HAVE_ACCESSORS_OR_BE_ABSTRACT.on(property))
|
trace.report(EXTENSION_PROPERTY_MUST_HAVE_ACCESSORS_OR_BE_ABSTRACT.on(property))
|
||||||
} else if (diagnosticSuppressor.shouldReportNoBody(propertyDescriptor)) {
|
} else if (diagnosticSuppressor.shouldReportNoBody(propertyDescriptor)) {
|
||||||
reportMustBeInitialized(
|
val isOpenValDeferredInitDeprecationWarning =
|
||||||
propertyDescriptor,
|
!languageVersionSettings.supportsFeature(LanguageFeature.ProhibitOpenValDeferredInitialization) &&
|
||||||
containingDeclaration,
|
propertyDescriptor.getEffectiveModality(languageVersionSettings) == Modality.OPEN &&
|
||||||
hasAnyAccessorImplementation,
|
!propertyDescriptor.isVar &&
|
||||||
property,
|
trace.bindingContext.get(IS_DEFINITELY_NOT_ASSIGNED_IN_CONSTRUCTOR, propertyDescriptor) == false
|
||||||
languageVersionSettings,
|
// KT-61228
|
||||||
trace
|
val isFalsePositiveDeferredInitDeprecationWarning = isOpenValDeferredInitDeprecationWarning &&
|
||||||
)
|
propertyDescriptor.getEffectiveModality() == Modality.FINAL
|
||||||
|
if (!isFalsePositiveDeferredInitDeprecationWarning) {
|
||||||
|
reportMustBeInitialized(
|
||||||
|
propertyDescriptor,
|
||||||
|
containingDeclaration,
|
||||||
|
hasAnyAccessorImplementation,
|
||||||
|
property,
|
||||||
|
isOpenValDeferredInitDeprecationWarning,
|
||||||
|
languageVersionSettings,
|
||||||
|
trace
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else if (property.typeReference == null && !languageVersionSettings.supportsFeature(LanguageFeature.ShortSyntaxForPropertyGetters)) {
|
} else if (property.typeReference == null && !languageVersionSettings.supportsFeature(LanguageFeature.ShortSyntaxForPropertyGetters)) {
|
||||||
trace.report(
|
trace.report(
|
||||||
@@ -832,6 +842,7 @@ class DeclarationsChecker(
|
|||||||
containingDeclaration: DeclarationDescriptor,
|
containingDeclaration: DeclarationDescriptor,
|
||||||
hasAnyAccessorImplementation: Boolean,
|
hasAnyAccessorImplementation: Boolean,
|
||||||
property: KtProperty,
|
property: KtProperty,
|
||||||
|
isOpenValDeferredInitDeprecationWarning: Boolean,
|
||||||
languageVersionSettings: LanguageVersionSettings,
|
languageVersionSettings: LanguageVersionSettings,
|
||||||
trace: BindingTrace,
|
trace: BindingTrace,
|
||||||
) {
|
) {
|
||||||
@@ -843,11 +854,6 @@ class DeclarationsChecker(
|
|||||||
propertyDescriptor.getEffectiveModality(languageVersionSettings) != Modality.FINAL &&
|
propertyDescriptor.getEffectiveModality(languageVersionSettings) != Modality.FINAL &&
|
||||||
trace.bindingContext.get(IS_DEFINITELY_NOT_ASSIGNED_IN_CONSTRUCTOR, propertyDescriptor) == false
|
trace.bindingContext.get(IS_DEFINITELY_NOT_ASSIGNED_IN_CONSTRUCTOR, propertyDescriptor) == false
|
||||||
val suggestMakingItAbstract = containingDeclaration is ClassDescriptor && !hasAnyAccessorImplementation
|
val suggestMakingItAbstract = containingDeclaration is ClassDescriptor && !hasAnyAccessorImplementation
|
||||||
val isOpenValDeferredInitDeprecationWarning =
|
|
||||||
!languageVersionSettings.supportsFeature(LanguageFeature.ProhibitOpenValDeferredInitialization) &&
|
|
||||||
propertyDescriptor.getEffectiveModality(languageVersionSettings) == Modality.OPEN &&
|
|
||||||
!propertyDescriptor.isVar &&
|
|
||||||
trace.bindingContext.get(IS_DEFINITELY_NOT_ASSIGNED_IN_CONSTRUCTOR, propertyDescriptor) == false
|
|
||||||
if (isOpenValDeferredInitDeprecationWarning && !suggestMakingItFinal && suggestMakingItAbstract) {
|
if (isOpenValDeferredInitDeprecationWarning && !suggestMakingItFinal && suggestMakingItAbstract) {
|
||||||
error("Not reachable case. Every \"open val + deferred init\" case that could be made `abstract`, also could be made `final`")
|
error("Not reachable case. Every \"open val + deferred init\" case that could be made `abstract`, also could be made `final`")
|
||||||
}
|
}
|
||||||
@@ -1132,9 +1138,14 @@ class DeclarationsChecker(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun PropertyDescriptor.getEffectiveModality(languageVersionSettings: LanguageVersionSettings): Modality =
|
private fun PropertyDescriptor.getEffectiveModality(): Modality =
|
||||||
when (languageVersionSettings.supportsFeature(LanguageFeature.TakeIntoAccountEffectivelyFinalInMustBeInitializedCheck) &&
|
when (modality == Modality.OPEN && (containingDeclaration as? ClassDescriptor)?.modality == Modality.FINAL) {
|
||||||
modality == Modality.OPEN && (containingDeclaration as? ClassDescriptor)?.modality == Modality.FINAL) {
|
|
||||||
true -> Modality.FINAL
|
true -> Modality.FINAL
|
||||||
false -> modality
|
false -> modality
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun PropertyDescriptor.getEffectiveModality(languageVersionSettings: LanguageVersionSettings): Modality =
|
||||||
|
when (languageVersionSettings.supportsFeature(LanguageFeature.TakeIntoAccountEffectivelyFinalInMustBeInitializedCheck)) {
|
||||||
|
true -> getEffectiveModality()
|
||||||
|
false -> modality
|
||||||
|
}
|
||||||
|
|||||||
+29
@@ -0,0 +1,29 @@
|
|||||||
|
// FIR_IDENTICAL
|
||||||
|
// DIAGNOSTICS: -DEBUG_INFO_LEAKING_THIS
|
||||||
|
// LANGUAGE:-TakeIntoAccountEffectivelyFinalInMustBeInitializedCheck
|
||||||
|
// LANGUAGE:+ProhibitOpenValDeferredInitialization
|
||||||
|
|
||||||
|
// Invalid combination of language feature flags. The user enabled 2.0 language flag (+ProhibitOpenValDeferredInitialization) and disabled
|
||||||
|
// 1.9 language flag (-TakeIntoAccountEffectivelyFinalInMustBeInitializedCheck) => It's only possible if users manually set `-XXLanguage` =>
|
||||||
|
// Technically, it's UB (undefined behaviour)
|
||||||
|
//
|
||||||
|
// On one hand, suppose that you have 1.9.0 compiler with -XXLanguage:-TakeIntoAccountEffectivelyFinalInMustBeInitializedCheck and then you
|
||||||
|
// bump your compiler version to 1.9.20. It's not nice that you will get this compilation error considering that you didn't have a warning
|
||||||
|
// => so probably we shouldn't report a error here
|
||||||
|
//
|
||||||
|
// But on the other hand, the error is expected by the combination of feature flags (we prohibit open val deferred initialization and
|
||||||
|
// since we don't take effectively final into account) => we must be report a error
|
||||||
|
//
|
||||||
|
// Anyway, it's UB. Users shouldn't manually tune `-XXLanguage`
|
||||||
|
|
||||||
|
interface Base {
|
||||||
|
val foo: Int
|
||||||
|
}
|
||||||
|
|
||||||
|
class Foo : Base {
|
||||||
|
<!MUST_BE_INITIALIZED_OR_FINAL_OR_ABSTRACT!>override val foo: Int<!>
|
||||||
|
|
||||||
|
init {
|
||||||
|
foo = 1
|
||||||
|
}
|
||||||
|
}
|
||||||
+15
@@ -0,0 +1,15 @@
|
|||||||
|
// FIR_IDENTICAL
|
||||||
|
// DIAGNOSTICS: -DEBUG_INFO_LEAKING_THIS
|
||||||
|
// LANGUAGE:+TakeIntoAccountEffectivelyFinalInMustBeInitializedCheck
|
||||||
|
// LANGUAGE:+ProhibitOpenValDeferredInitialization
|
||||||
|
interface Base {
|
||||||
|
val foo: Int
|
||||||
|
}
|
||||||
|
|
||||||
|
class Foo : Base {
|
||||||
|
override val foo: Int
|
||||||
|
|
||||||
|
init {
|
||||||
|
foo = 1
|
||||||
|
}
|
||||||
|
}
|
||||||
+16
@@ -0,0 +1,16 @@
|
|||||||
|
// FIR_IDENTICAL
|
||||||
|
// DIAGNOSTICS: -DEBUG_INFO_LEAKING_THIS
|
||||||
|
// LANGUAGE:-TakeIntoAccountEffectivelyFinalInMustBeInitializedCheck
|
||||||
|
// LANGUAGE:-ProhibitOpenValDeferredInitialization
|
||||||
|
// KT-61228 case
|
||||||
|
interface Base {
|
||||||
|
val foo: Int
|
||||||
|
}
|
||||||
|
|
||||||
|
class Foo : Base {
|
||||||
|
override val foo: Int
|
||||||
|
|
||||||
|
init {
|
||||||
|
foo = 1
|
||||||
|
}
|
||||||
|
}
|
||||||
+15
@@ -0,0 +1,15 @@
|
|||||||
|
// FIR_IDENTICAL
|
||||||
|
// DIAGNOSTICS: -DEBUG_INFO_LEAKING_THIS
|
||||||
|
// LANGUAGE:+TakeIntoAccountEffectivelyFinalInMustBeInitializedCheck
|
||||||
|
// LANGUAGE:-ProhibitOpenValDeferredInitialization
|
||||||
|
interface Base {
|
||||||
|
val foo: Int
|
||||||
|
}
|
||||||
|
|
||||||
|
class Foo : Base {
|
||||||
|
override val foo: Int
|
||||||
|
|
||||||
|
init {
|
||||||
|
foo = 1
|
||||||
|
}
|
||||||
|
}
|
||||||
Generated
+24
@@ -3140,6 +3140,30 @@ public class DiagnosticTestGenerated extends AbstractDiagnosticTest {
|
|||||||
runTest("compiler/testData/diagnostics/tests/backingField/MustBeInitializedEffectivelyFinalOn.kt");
|
runTest("compiler/testData/diagnostics/tests/backingField/MustBeInitializedEffectivelyFinalOn.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("OpenValDeferredInitError_InFinalClass_DisableEffectivelyFinal.kt")
|
||||||
|
public void testOpenValDeferredInitError_InFinalClass_DisableEffectivelyFinal() throws Exception {
|
||||||
|
runTest("compiler/testData/diagnostics/tests/backingField/OpenValDeferredInitError_InFinalClass_DisableEffectivelyFinal.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("OpenValDeferredInitError_InFinalClass_EnableEffectivelyFinal.kt")
|
||||||
|
public void testOpenValDeferredInitError_InFinalClass_EnableEffectivelyFinal() throws Exception {
|
||||||
|
runTest("compiler/testData/diagnostics/tests/backingField/OpenValDeferredInitError_InFinalClass_EnableEffectivelyFinal.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("OpenValDeferredInitWarning_InFinalClass_DisableEffectivelyFinal.kt")
|
||||||
|
public void testOpenValDeferredInitWarning_InFinalClass_DisableEffectivelyFinal() throws Exception {
|
||||||
|
runTest("compiler/testData/diagnostics/tests/backingField/OpenValDeferredInitWarning_InFinalClass_DisableEffectivelyFinal.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("OpenValDeferredInitWarning_InFinalClass_EnableEffectivelyFinal.kt")
|
||||||
|
public void testOpenValDeferredInitWarning_InFinalClass_EnableEffectivelyFinal() throws Exception {
|
||||||
|
runTest("compiler/testData/diagnostics/tests/backingField/OpenValDeferredInitWarning_InFinalClass_EnableEffectivelyFinal.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@TestMetadata("OpenValPartialDeferredInitErrorAnyway.kt")
|
@TestMetadata("OpenValPartialDeferredInitErrorAnyway.kt")
|
||||||
public void testOpenValPartialDeferredInitErrorAnyway() throws Exception {
|
public void testOpenValPartialDeferredInitErrorAnyway() throws Exception {
|
||||||
|
|||||||
Reference in New Issue
Block a user