diff --git a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDataClassConverters.kt b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDataClassConverters.kt index 69b20d9c881..38d18dcc216 100644 --- a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDataClassConverters.kt +++ b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDataClassConverters.kt @@ -2877,6 +2877,31 @@ internal val KT_DIAGNOSTIC_CONVERTER = KtDiagnosticConverterBuilder.buildConvert token, ) } + add(FirErrors.LATEINIT_INTRINSIC_CALL_ON_NON_LITERAL) { firDiagnostic -> + LateinitIntrinsicCallOnNonLiteralImpl( + firDiagnostic as KtPsiDiagnostic, + token, + ) + } + add(FirErrors.LATEINIT_INTRINSIC_CALL_ON_NON_LATEINIT) { firDiagnostic -> + LateinitIntrinsicCallOnNonLateinitImpl( + firDiagnostic as KtPsiDiagnostic, + token, + ) + } + add(FirErrors.LATEINIT_INTRINSIC_CALL_IN_INLINE_FUNCTION) { firDiagnostic -> + LateinitIntrinsicCallInInlineFunctionImpl( + firDiagnostic as KtPsiDiagnostic, + token, + ) + } + add(FirErrors.LATEINIT_INTRINSIC_CALL_ON_NON_ACCESSIBLE_PROPERTY) { firDiagnostic -> + LateinitIntrinsicCallOnNonAccessiblePropertyImpl( + firSymbolBuilder.buildSymbol(firDiagnostic.a), + firDiagnostic as KtPsiDiagnostic, + token, + ) + } add(FirErrors.EXPECTED_DECLARATION_WITH_BODY) { firDiagnostic -> ExpectedDeclarationWithBodyImpl( firDiagnostic as KtPsiDiagnostic, diff --git a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDiagnostics.kt b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDiagnostics.kt index 89a33d4b54a..edfc32d3692 100644 --- a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDiagnostics.kt +++ b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDiagnostics.kt @@ -2031,6 +2031,23 @@ sealed class KtFirDiagnostic : KtDiagnosticWithPsi { override val diagnosticClass get() = ExplicitTypeArgumentsInPropertyAccess::class } + abstract class LateinitIntrinsicCallOnNonLiteral : KtFirDiagnostic() { + override val diagnosticClass get() = LateinitIntrinsicCallOnNonLiteral::class + } + + abstract class LateinitIntrinsicCallOnNonLateinit : KtFirDiagnostic() { + override val diagnosticClass get() = LateinitIntrinsicCallOnNonLateinit::class + } + + abstract class LateinitIntrinsicCallInInlineFunction : KtFirDiagnostic() { + override val diagnosticClass get() = LateinitIntrinsicCallInInlineFunction::class + } + + abstract class LateinitIntrinsicCallOnNonAccessibleProperty : KtFirDiagnostic() { + override val diagnosticClass get() = LateinitIntrinsicCallOnNonAccessibleProperty::class + abstract val declaration: KtSymbol + } + abstract class ExpectedDeclarationWithBody : KtFirDiagnostic() { override val diagnosticClass get() = ExpectedDeclarationWithBody::class } diff --git a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDiagnosticsImpl.kt b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDiagnosticsImpl.kt index 56d97ca561c..ec89a7e5feb 100644 --- a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDiagnosticsImpl.kt +++ b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDiagnosticsImpl.kt @@ -2446,6 +2446,27 @@ internal class ExplicitTypeArgumentsInPropertyAccessImpl( override val token: KtLifetimeToken, ) : KtFirDiagnostic.ExplicitTypeArgumentsInPropertyAccess(), KtAbstractFirDiagnostic +internal class LateinitIntrinsicCallOnNonLiteralImpl( + override val firDiagnostic: KtPsiDiagnostic, + override val token: KtLifetimeToken, +) : KtFirDiagnostic.LateinitIntrinsicCallOnNonLiteral(), KtAbstractFirDiagnostic + +internal class LateinitIntrinsicCallOnNonLateinitImpl( + override val firDiagnostic: KtPsiDiagnostic, + override val token: KtLifetimeToken, +) : KtFirDiagnostic.LateinitIntrinsicCallOnNonLateinit(), KtAbstractFirDiagnostic + +internal class LateinitIntrinsicCallInInlineFunctionImpl( + override val firDiagnostic: KtPsiDiagnostic, + override val token: KtLifetimeToken, +) : KtFirDiagnostic.LateinitIntrinsicCallInInlineFunction(), KtAbstractFirDiagnostic + +internal class LateinitIntrinsicCallOnNonAccessiblePropertyImpl( + override val declaration: KtSymbol, + override val firDiagnostic: KtPsiDiagnostic, + override val token: KtLifetimeToken, +) : KtFirDiagnostic.LateinitIntrinsicCallOnNonAccessibleProperty(), KtAbstractFirDiagnostic + internal class ExpectedDeclarationWithBodyImpl( override val firDiagnostic: KtPsiDiagnostic, override val token: KtLifetimeToken, diff --git a/compiler/fir/checkers/checkers-component-generator/src/org/jetbrains/kotlin/fir/checkers/generator/diagnostics/FirDiagnosticsList.kt b/compiler/fir/checkers/checkers-component-generator/src/org/jetbrains/kotlin/fir/checkers/generator/diagnostics/FirDiagnosticsList.kt index d34e41abd56..b90a670ca97 100644 --- a/compiler/fir/checkers/checkers-component-generator/src/org/jetbrains/kotlin/fir/checkers/generator/diagnostics/FirDiagnosticsList.kt +++ b/compiler/fir/checkers/checkers-component-generator/src/org/jetbrains/kotlin/fir/checkers/generator/diagnostics/FirDiagnosticsList.kt @@ -1018,6 +1018,13 @@ object DIAGNOSTICS_LIST : DiagnosticList("FirErrors") { val LOCAL_VARIABLE_WITH_TYPE_PARAMETERS_WARNING by warning(PositioningStrategy.TYPE_PARAMETERS_LIST) val LOCAL_VARIABLE_WITH_TYPE_PARAMETERS by error(PositioningStrategy.TYPE_PARAMETERS_LIST) val EXPLICIT_TYPE_ARGUMENTS_IN_PROPERTY_ACCESS by error(PositioningStrategy.REFERENCED_NAME_BY_QUALIFIED) + + val LATEINIT_INTRINSIC_CALL_ON_NON_LITERAL by error() + val LATEINIT_INTRINSIC_CALL_ON_NON_LATEINIT by error() + val LATEINIT_INTRINSIC_CALL_IN_INLINE_FUNCTION by error() + val LATEINIT_INTRINSIC_CALL_ON_NON_ACCESSIBLE_PROPERTY by error() { + parameter("declaration") + } } val MPP_PROJECTS by object : DiagnosticGroup("Multi-platform projects") { diff --git a/compiler/fir/checkers/gen/org/jetbrains/kotlin/fir/analysis/diagnostics/FirErrors.kt b/compiler/fir/checkers/gen/org/jetbrains/kotlin/fir/analysis/diagnostics/FirErrors.kt index a44a3ce7e83..0deb1a06694 100644 --- a/compiler/fir/checkers/gen/org/jetbrains/kotlin/fir/analysis/diagnostics/FirErrors.kt +++ b/compiler/fir/checkers/gen/org/jetbrains/kotlin/fir/analysis/diagnostics/FirErrors.kt @@ -557,6 +557,10 @@ object FirErrors { val LOCAL_VARIABLE_WITH_TYPE_PARAMETERS_WARNING by warning0(SourceElementPositioningStrategies.TYPE_PARAMETERS_LIST) val LOCAL_VARIABLE_WITH_TYPE_PARAMETERS by error0(SourceElementPositioningStrategies.TYPE_PARAMETERS_LIST) val EXPLICIT_TYPE_ARGUMENTS_IN_PROPERTY_ACCESS by error0(SourceElementPositioningStrategies.REFERENCED_NAME_BY_QUALIFIED) + val LATEINIT_INTRINSIC_CALL_ON_NON_LITERAL by error0() + val LATEINIT_INTRINSIC_CALL_ON_NON_LATEINIT by error0() + val LATEINIT_INTRINSIC_CALL_IN_INLINE_FUNCTION by error0() + val LATEINIT_INTRINSIC_CALL_ON_NON_ACCESSIBLE_PROPERTY by error1>() // Multi-platform projects val EXPECTED_DECLARATION_WITH_BODY by error0(SourceElementPositioningStrategies.DECLARATION_SIGNATURE) diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/CommonExpressionCheckers.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/CommonExpressionCheckers.kt index 6a7173da933..597ef84b4ef 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/CommonExpressionCheckers.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/CommonExpressionCheckers.kt @@ -46,6 +46,7 @@ object CommonExpressionCheckers : ExpressionCheckers() { FirFunInterfaceConstructorReferenceChecker, FirReifiedChecker, FirSuspendCallChecker, + FirLateinitIntrinsicApplicabilityChecker, ) override val callCheckers: Set diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirLateinitIntrinsicApplicabilityChecker.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirLateinitIntrinsicApplicabilityChecker.kt new file mode 100644 index 00000000000..15a0001efd0 --- /dev/null +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirLateinitIntrinsicApplicabilityChecker.kt @@ -0,0 +1,80 @@ +/* + * Copyright 2010-2023 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.fir.analysis.checkers.expression + +import org.jetbrains.kotlin.diagnostics.DiagnosticReporter +import org.jetbrains.kotlin.diagnostics.reportOn +import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext +import org.jetbrains.kotlin.fir.analysis.checkers.getContainingClassSymbol +import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors +import org.jetbrains.kotlin.fir.declarations.FirDeclaration +import org.jetbrains.kotlin.fir.declarations.FirFunction +import org.jetbrains.kotlin.fir.declarations.hasAnnotation +import org.jetbrains.kotlin.fir.declarations.utils.isInline +import org.jetbrains.kotlin.fir.declarations.utils.isLateInit +import org.jetbrains.kotlin.fir.expressions.FirCallableReferenceAccess +import org.jetbrains.kotlin.fir.expressions.FirQualifiedAccessExpression +import org.jetbrains.kotlin.fir.references.toResolvedPropertySymbol +import org.jetbrains.kotlin.fir.resolve.providers.firProvider +import org.jetbrains.kotlin.fir.symbols.SymbolInternals +import org.jetbrains.kotlin.fir.symbols.impl.FirPropertySymbol +import org.jetbrains.kotlin.name.StandardClassIds.Annotations + +object FirLateinitIntrinsicApplicabilityChecker : FirQualifiedAccessExpressionChecker() { + override fun check(expression: FirQualifiedAccessExpression, context: CheckerContext, reporter: DiagnosticReporter) { + + val resolvedSymbol = expression.calleeReference.toResolvedPropertySymbol() ?: return + + // An optimization + if (resolvedSymbol.name.identifierOrNullIfSpecial != "isInitialized") return + + val receiverParameter = resolvedSymbol.receiverParameter ?: return + + if (!receiverParameter.hasAnnotation(Annotations.AccessibleLateinitPropertyLiteral, context.session)) return + + val source = expression.calleeReference.source + + val extensionReceiver = expression.extensionReceiver + if (extensionReceiver !is FirCallableReferenceAccess) { + reporter.reportOn(source, FirErrors.LATEINIT_INTRINSIC_CALL_ON_NON_LITERAL, context) + return + } + + val calleePropertySymbol = extensionReceiver.calleeReference.toResolvedPropertySymbol() ?: return + + if (!calleePropertySymbol.isLateInit) { + reporter.reportOn(source, FirErrors.LATEINIT_INTRINSIC_CALL_ON_NON_LATEINIT, context) + return + } + + // property must be declared in one of the outer lexical scopes + if (calleePropertySymbol.containingClassOrFile(context) !in context.containingDeclarations) { + reporter.reportOn( + source, + FirErrors.LATEINIT_INTRINSIC_CALL_ON_NON_ACCESSIBLE_PROPERTY, + calleePropertySymbol, + context + ) + return + } + + val closestOwnFunction = context.containingDeclarations.lastOrNull() + if (closestOwnFunction is FirFunction && closestOwnFunction.isInline) { + reporter.reportOn(source, FirErrors.LATEINIT_INTRINSIC_CALL_IN_INLINE_FUNCTION, context) + } + } + + /** + * Returns the containing class or file if the property is top-level. + */ + @OptIn(SymbolInternals::class) + private fun FirPropertySymbol.containingClassOrFile( + context: CheckerContext + ): FirDeclaration? { + return getContainingClassSymbol(context.session)?.fir + ?: context.session.firProvider.getFirCallableContainerFile(this) + } +} diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirErrorsDefaultMessages.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirErrorsDefaultMessages.kt index 5218940ac28..d9492579a6a 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirErrorsDefaultMessages.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirErrorsDefaultMessages.kt @@ -289,6 +289,10 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.ITERATOR_MISSING import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.ITERATOR_ON_NULLABLE import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.KCLASS_WITH_NULLABLE_TYPE_PARAMETER_IN_SIGNATURE import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.LATEINIT_FIELD_IN_VAL_PROPERTY +import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.LATEINIT_INTRINSIC_CALL_ON_NON_LITERAL +import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.LATEINIT_INTRINSIC_CALL_ON_NON_LATEINIT +import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.LATEINIT_INTRINSIC_CALL_ON_NON_ACCESSIBLE_PROPERTY +import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.LATEINIT_INTRINSIC_CALL_IN_INLINE_FUNCTION import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.LATEINIT_NULLABLE_BACKING_FIELD import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.LATEINIT_PROPERTY_FIELD_DECLARATION_WITH_INITIALIZER import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.LEAKED_IN_PLACE_LAMBDA @@ -1646,6 +1650,11 @@ object FirErrorsDefaultMessages : BaseDiagnosticRendererFactory() { map.put(LOCAL_VARIABLE_WITH_TYPE_PARAMETERS, "Local variables are not allowed to have type parameters") map.put(EXPLICIT_TYPE_ARGUMENTS_IN_PROPERTY_ACCESS, "A property access cannot have explicit type arguments") + map.put(LATEINIT_INTRINSIC_CALL_ON_NON_LITERAL, "This declaration can only be called on a property literal (e.g. 'Foo::bar')") + map.put(LATEINIT_INTRINSIC_CALL_ON_NON_LATEINIT, "This declaration can only be called on a reference to a lateinit property") + map.put(LATEINIT_INTRINSIC_CALL_IN_INLINE_FUNCTION, "This declaration can not be used inside an inline function") + map.put(LATEINIT_INTRINSIC_CALL_ON_NON_ACCESSIBLE_PROPERTY, "Backing field of ''{0}'' is not accessible at this point", SYMBOL) + map.put(CONST_VAL_NOT_TOP_LEVEL_OR_OBJECT, "Const 'val' are only allowed on top level, in named objects, or in companion objects") map.put(CONST_VAL_WITH_GETTER, "Const 'val' should not have a getter") map.put(CONST_VAL_WITH_DELEGATE, "Const 'val' should not have a delegate") diff --git a/compiler/fir/providers/src/org/jetbrains/kotlin/fir/declarations/FirAnnotationUtils.kt b/compiler/fir/providers/src/org/jetbrains/kotlin/fir/declarations/FirAnnotationUtils.kt index 590d500f8b0..6fbcf28da78 100644 --- a/compiler/fir/providers/src/org/jetbrains/kotlin/fir/declarations/FirAnnotationUtils.kt +++ b/compiler/fir/providers/src/org/jetbrains/kotlin/fir/declarations/FirAnnotationUtils.kt @@ -113,6 +113,10 @@ fun FirBasedSymbol<*>.hasAnnotation(classId: ClassId, session: FirSession): Bool return resolvedAnnotationsWithClassIds.hasAnnotation(classId, session) } +fun FirAnnotationContainer.hasAnnotation(classId: ClassId, session: FirSession): Boolean { + return annotations.hasAnnotation(classId, session) +} + fun List.hasAnnotation(classId: ClassId, session: FirSession): Boolean { return this.any { it.toAnnotationClassId(session) == classId } } diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/checkers/LateinitIntrinsicApplicabilityChecker.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/checkers/LateinitIntrinsicApplicabilityChecker.kt index 84dd7ea4f02..60993b4a117 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/checkers/LateinitIntrinsicApplicabilityChecker.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/checkers/LateinitIntrinsicApplicabilityChecker.kt @@ -17,30 +17,28 @@ package org.jetbrains.kotlin.resolve.calls.checkers import com.intellij.psi.PsiElement +import org.jetbrains.kotlin.builtins.StandardNames.FqNames import org.jetbrains.kotlin.config.LanguageFeature import org.jetbrains.kotlin.descriptors.DeclarationDescriptor import org.jetbrains.kotlin.descriptors.FunctionDescriptor import org.jetbrains.kotlin.descriptors.PropertyDescriptor import org.jetbrains.kotlin.diagnostics.Errors.* -import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.psi.KtCallableReferenceExpression import org.jetbrains.kotlin.psi.KtPsiUtil import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils import org.jetbrains.kotlin.resolve.OverridingUtil -import org.jetbrains.kotlin.resolve.calls.util.getResolvedCall import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall +import org.jetbrains.kotlin.resolve.calls.util.getResolvedCall import org.jetbrains.kotlin.resolve.scopes.receivers.ExpressionReceiver class LateinitIntrinsicApplicabilityChecker(val isWarningInPre19: Boolean) : CallChecker { - private val ACCESSIBLE_LATEINIT_PROPERTY_LITERAL = FqName("kotlin.internal.AccessibleLateinitPropertyLiteral") - override fun check(resolvedCall: ResolvedCall<*>, reportOn: PsiElement, context: CallCheckerContext) { val descriptor = resolvedCall.resultingDescriptor // An optimization if (descriptor.name.asString() != "isInitialized") return - if (descriptor.extensionReceiverParameter?.annotations?.hasAnnotation(ACCESSIBLE_LATEINIT_PROPERTY_LITERAL) != true) return + if (descriptor.extensionReceiverParameter?.annotations?.hasAnnotation(FqNames.accessibleLateinitPropertyLiteral) != true) return val expression = (resolvedCall.extensionReceiver as? ExpressionReceiver)?.expression?.let(KtPsiUtil::safeDeparenthesize) fun chooseDiagnostic(ifWarning: T, ifError: T) = diff --git a/compiler/testData/codegen/box/properties/lateinit/isInitializedAndDeinitialize/isInitializedMultiFile.kt b/compiler/testData/codegen/box/properties/lateinit/isInitializedAndDeinitialize/isInitializedMultiFile.kt index 29765d67a0b..afb0a707037 100644 --- a/compiler/testData/codegen/box/properties/lateinit/isInitializedAndDeinitialize/isInitializedMultiFile.kt +++ b/compiler/testData/codegen/box/properties/lateinit/isInitializedAndDeinitialize/isInitializedMultiFile.kt @@ -1,6 +1,8 @@ // WITH_STDLIB // On JVM, isInitialized on a property from another file is forbidden because lateinit-ness is not included in the an ABI of a property. // IGNORE_BACKEND_K1: JVM, JVM_IR +// In K2, isInitialized on a property from another file is forbidden for all backends. +// IGNORE_BACKEND_K2: JVM_IR // IGNORE_LIGHT_ANALYSIS // FILE: A.kt diff --git a/compiler/testData/diagnostics/nativeTests/isInitialized.fir.kt b/compiler/testData/diagnostics/nativeTests/isInitialized.fir.kt index 1ce15acc4a4..1a4db47f96d 100644 --- a/compiler/testData/diagnostics/nativeTests/isInitialized.fir.kt +++ b/compiler/testData/diagnostics/nativeTests/isInitialized.fir.kt @@ -51,15 +51,15 @@ open class Foo : Base { fun onLiteral() { val p = this::x - p.isInitialized + p.isInitialized } fun onNonLateinit() { - this::nonLateInit.isInitialized + this::nonLateInit.isInitialized } inline fun inlineFun() { - this::x.isInitialized + this::x.isInitialized object { val z = this@Foo::x.isInitialized @@ -78,22 +78,22 @@ open class Foo : Base { } fun onNonAccessible() { - Foo()::x.isInitialized + Foo()::x.isInitialized } fun onNonLateinit() { - Foo()::nonLateInit.isInitialized + Foo()::nonLateInit.isInitialized } object Unrelated { fun onNonAccessible() { - Foo()::x.isInitialized + Foo()::x.isInitialized } } class FooImpl : Foo() { fun onNonAccessible() { - this::x.isInitialized + this::x.isInitialized } } @@ -101,6 +101,6 @@ class FooImpl : Foo() { class OtherFooImpl : Foo() { fun onNonAccessible() { - this::x.isInitialized + this::x.isInitialized } } diff --git a/compiler/testData/diagnostics/nativeTests/isInitializedError.fir.kt b/compiler/testData/diagnostics/nativeTests/isInitializedError.fir.kt deleted file mode 100644 index 1ce15acc4a4..00000000000 --- a/compiler/testData/diagnostics/nativeTests/isInitializedError.fir.kt +++ /dev/null @@ -1,106 +0,0 @@ -// !DIAGNOSTICS: -UNUSED_VARIABLE -NOTHING_TO_INLINE -// !LANGUAGE: -NativeJsProhibitLateinitIsInitalizedIntrinsicWithoutPrivateAccess -// FILE: stdlibInternal.kt - -package kotlin.internal - -@Target(AnnotationTarget.VALUE_PARAMETER) -@Retention(AnnotationRetention.BINARY) -internal annotation class AccessibleLateinitPropertyLiteral - -// FILE: stdlib.kt -package kotlin - -import kotlin.internal.AccessibleLateinitPropertyLiteral -import kotlin.reflect.KProperty0 - -inline val @receiver:AccessibleLateinitPropertyLiteral KProperty0<*>.isInitialized: Boolean - get() = true - - -// FILE: test.kt - -interface Base { - var x: String -} - -open class Foo : Base { - override lateinit var x: String - private lateinit var y: String - - var nonLateInit: Int = 1 - - fun ok() { - val b: Boolean = this::x.isInitialized - - val otherInstance = Foo() - otherInstance::x.isInitialized - - (this::x).isInitialized - (@Suppress("ALL") (this::x)).isInitialized - - object { - fun local() { - class Local { - val xx = this@Foo::x.isInitialized - val yy = this@Foo::y.isInitialized - } - } - } - } - - fun onLiteral() { - val p = this::x - p.isInitialized - } - - fun onNonLateinit() { - this::nonLateInit.isInitialized - } - - inline fun inlineFun() { - this::x.isInitialized - - object { - val z = this@Foo::x.isInitialized - } - } - - inner class InnerSubclass : Foo() { - fun innerOk() { - // This is access to Foo.x declared lexically above - this@Foo::x.isInitialized - - // This is access to InnerSubclass.x which is inherited from Foo.x - this::x.isInitialized - } - } -} - -fun onNonAccessible() { - Foo()::x.isInitialized -} - -fun onNonLateinit() { - Foo()::nonLateInit.isInitialized -} - -object Unrelated { - fun onNonAccessible() { - Foo()::x.isInitialized - } -} - -class FooImpl : Foo() { - fun onNonAccessible() { - this::x.isInitialized - } -} - -// FILE: other.kt - -class OtherFooImpl : Foo() { - fun onNonAccessible() { - this::x.isInitialized - } -} diff --git a/compiler/testData/diagnostics/nativeTests/isInitializedError.kt b/compiler/testData/diagnostics/nativeTests/isInitializedError.kt index 1195c876c45..cc178cdef9b 100644 --- a/compiler/testData/diagnostics/nativeTests/isInitializedError.kt +++ b/compiler/testData/diagnostics/nativeTests/isInitializedError.kt @@ -1,3 +1,4 @@ +// FIR_IDENTICAL // !DIAGNOSTICS: -UNUSED_VARIABLE -NOTHING_TO_INLINE // !LANGUAGE: +NativeJsProhibitLateinitIsInitalizedIntrinsicWithoutPrivateAccess // FILE: stdlibInternal.kt diff --git a/compiler/testData/diagnostics/testsWithStdLib/lateinit/isInitialized.fir.kt b/compiler/testData/diagnostics/testsWithStdLib/lateinit/isInitialized.fir.kt deleted file mode 100644 index 681023b0659..00000000000 --- a/compiler/testData/diagnostics/testsWithStdLib/lateinit/isInitialized.fir.kt +++ /dev/null @@ -1,87 +0,0 @@ -// !DIAGNOSTICS: -UNUSED_VARIABLE -NOTHING_TO_INLINE -// FILE: test.kt - -interface Base { - var x: String -} - -open class Foo : Base { - override lateinit var x: String - private lateinit var y: String - - var nonLateInit: Int = 1 - - fun ok() { - val b: Boolean = this::x.isInitialized - - val otherInstance = Foo() - otherInstance::x.isInitialized - - (this::x).isInitialized - (@Suppress("ALL") (this::x)).isInitialized - - object { - fun local() { - class Local { - val xx = this@Foo::x.isInitialized - val yy = this@Foo::y.isInitialized - } - } - } - } - - fun onLiteral() { - val p = this::x - p.isInitialized - } - - fun onNonLateinit() { - this::nonLateInit.isInitialized - } - - inline fun inlineFun() { - this::x.isInitialized - - object { - val z = this@Foo::x.isInitialized - } - } - - inner class InnerSubclass : Foo() { - fun innerOk() { - // This is access to Foo.x declared lexically above - this@Foo::x.isInitialized - - // This is access to InnerSubclass.x which is inherited from Foo.x - this::x.isInitialized - } - } -} - -fun onNonAccessible() { - Foo()::x.isInitialized -} - -fun onNonLateinit() { - Foo()::nonLateInit.isInitialized -} - -object Unrelated { - fun onNonAccessible() { - Foo()::x.isInitialized - } -} - -class FooImpl : Foo() { - fun onNonAccessible() { - this::x.isInitialized - } -} - -// FILE: other.kt - -class OtherFooImpl : Foo() { - fun onNonAccessible() { - this::x.isInitialized - } -} diff --git a/compiler/testData/diagnostics/testsWithStdLib/lateinit/isInitialized.kt b/compiler/testData/diagnostics/testsWithStdLib/lateinit/isInitialized.kt index 8e561ff58a7..fbd9cc51469 100644 --- a/compiler/testData/diagnostics/testsWithStdLib/lateinit/isInitialized.kt +++ b/compiler/testData/diagnostics/testsWithStdLib/lateinit/isInitialized.kt @@ -1,6 +1,9 @@ +// FIR_IDENTICAL // !DIAGNOSTICS: -UNUSED_VARIABLE -NOTHING_TO_INLINE // FILE: test.kt +lateinit var topLevel: String + interface Base { var x: String } @@ -12,6 +15,7 @@ open class Foo : Base { var nonLateInit: Int = 1 fun ok() { + ::topLevel.isInitialized val b: Boolean = this::x.isInitialized val otherInstance = Foo() @@ -83,5 +87,6 @@ class FooImpl : Foo() { class OtherFooImpl : Foo() { fun onNonAccessible() { this::x.isInitialized + ::topLevel.isInitialized } } diff --git a/compiler/testData/diagnostics/testsWithStdLib/lateinit/isInitialized.txt b/compiler/testData/diagnostics/testsWithStdLib/lateinit/isInitialized.txt index 15f0d4edddd..d101f708c5a 100644 --- a/compiler/testData/diagnostics/testsWithStdLib/lateinit/isInitialized.txt +++ b/compiler/testData/diagnostics/testsWithStdLib/lateinit/isInitialized.txt @@ -1,5 +1,6 @@ package +public lateinit var topLevel: kotlin.String public fun onNonAccessible(): kotlin.Unit public fun onNonLateinit(): kotlin.Unit @@ -76,3 +77,4 @@ public object Unrelated { public final fun onNonAccessible(): kotlin.Unit public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String } + diff --git a/core/compiler.common/src/org/jetbrains/kotlin/builtins/StandardNames.kt b/core/compiler.common/src/org/jetbrains/kotlin/builtins/StandardNames.kt index 88c81960950..c489fdd06f2 100644 --- a/core/compiler.common/src/org/jetbrains/kotlin/builtins/StandardNames.kt +++ b/core/compiler.common/src/org/jetbrains/kotlin/builtins/StandardNames.kt @@ -74,6 +74,7 @@ object StandardNames { @JvmField val TEXT_PACKAGE_FQ_NAME = BUILT_INS_PACKAGE_FQ_NAME.child(Name.identifier("text")) + @JvmField val KOTLIN_INTERNAL_FQ_NAME = BUILT_INS_PACKAGE_FQ_NAME.child(Name.identifier("internal")) @JvmField @@ -137,6 +138,7 @@ object StandardNames { @JvmField val mustBeDocumented: FqName = annotationName("MustBeDocumented") @JvmField val unsafeVariance: FqName = fqName("UnsafeVariance") @JvmField val publishedApi: FqName = fqName("PublishedApi") + @JvmField val accessibleLateinitPropertyLiteral: FqName = internalName("AccessibleLateinitPropertyLiteral") @JvmField val iterator: FqName = collectionsFqName("Iterator") @JvmField val iterable: FqName = collectionsFqName("Iterable") @@ -228,6 +230,10 @@ object StandardNames { private fun annotationName(simpleName: String): FqName { return ANNOTATION_PACKAGE_FQ_NAME.child(Name.identifier(simpleName)) } + + private fun internalName(simpleName: String): FqName { + return KOTLIN_INTERNAL_FQ_NAME.child(Name.identifier(simpleName)) + } } @JvmStatic diff --git a/core/compiler.common/src/org/jetbrains/kotlin/name/StandardClassIds.kt b/core/compiler.common/src/org/jetbrains/kotlin/name/StandardClassIds.kt index c0456c3e535..880f6727df7 100644 --- a/core/compiler.common/src/org/jetbrains/kotlin/name/StandardClassIds.kt +++ b/core/compiler.common/src/org/jetbrains/kotlin/name/StandardClassIds.kt @@ -171,6 +171,8 @@ object StandardClassIds { val WasExperimental = "WasExperimental".baseId() + val AccessibleLateinitPropertyLiteral = "AccessibleLateinitPropertyLiteral".internalId() + object Java { val Deprecated = "Deprecated".javaLangId() val Repeatable = "Repeatable".javaAnnotationId() @@ -226,8 +228,8 @@ object StandardClassIds { StandardClassIds.MapEntry to StandardClassIds.MutableMapEntry ) - val mutableCollectionToBaseCollection: Map = - baseCollectionToMutableEquivalent.entries.associateBy({ it.value }) { it.key } + val mutableCollectionToBaseCollection: Map = + baseCollectionToMutableEquivalent.entries.associateBy({ it.value }) { it.key } } }