K2: implement FirLateinitIntrinsicApplicabilityChecker ^KT-55495 Fixed
This commit is contained in:
committed by
Space Team
parent
cfe8bc682c
commit
721a37f7e7
+25
@@ -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,
|
||||
|
||||
+17
@@ -2031,6 +2031,23 @@ sealed class KtFirDiagnostic<PSI : PsiElement> : KtDiagnosticWithPsi<PSI> {
|
||||
override val diagnosticClass get() = ExplicitTypeArgumentsInPropertyAccess::class
|
||||
}
|
||||
|
||||
abstract class LateinitIntrinsicCallOnNonLiteral : KtFirDiagnostic<PsiElement>() {
|
||||
override val diagnosticClass get() = LateinitIntrinsicCallOnNonLiteral::class
|
||||
}
|
||||
|
||||
abstract class LateinitIntrinsicCallOnNonLateinit : KtFirDiagnostic<PsiElement>() {
|
||||
override val diagnosticClass get() = LateinitIntrinsicCallOnNonLateinit::class
|
||||
}
|
||||
|
||||
abstract class LateinitIntrinsicCallInInlineFunction : KtFirDiagnostic<PsiElement>() {
|
||||
override val diagnosticClass get() = LateinitIntrinsicCallInInlineFunction::class
|
||||
}
|
||||
|
||||
abstract class LateinitIntrinsicCallOnNonAccessibleProperty : KtFirDiagnostic<PsiElement>() {
|
||||
override val diagnosticClass get() = LateinitIntrinsicCallOnNonAccessibleProperty::class
|
||||
abstract val declaration: KtSymbol
|
||||
}
|
||||
|
||||
abstract class ExpectedDeclarationWithBody : KtFirDiagnostic<KtDeclaration>() {
|
||||
override val diagnosticClass get() = ExpectedDeclarationWithBody::class
|
||||
}
|
||||
|
||||
+21
@@ -2446,6 +2446,27 @@ internal class ExplicitTypeArgumentsInPropertyAccessImpl(
|
||||
override val token: KtLifetimeToken,
|
||||
) : KtFirDiagnostic.ExplicitTypeArgumentsInPropertyAccess(), KtAbstractFirDiagnostic<KtExpression>
|
||||
|
||||
internal class LateinitIntrinsicCallOnNonLiteralImpl(
|
||||
override val firDiagnostic: KtPsiDiagnostic,
|
||||
override val token: KtLifetimeToken,
|
||||
) : KtFirDiagnostic.LateinitIntrinsicCallOnNonLiteral(), KtAbstractFirDiagnostic<PsiElement>
|
||||
|
||||
internal class LateinitIntrinsicCallOnNonLateinitImpl(
|
||||
override val firDiagnostic: KtPsiDiagnostic,
|
||||
override val token: KtLifetimeToken,
|
||||
) : KtFirDiagnostic.LateinitIntrinsicCallOnNonLateinit(), KtAbstractFirDiagnostic<PsiElement>
|
||||
|
||||
internal class LateinitIntrinsicCallInInlineFunctionImpl(
|
||||
override val firDiagnostic: KtPsiDiagnostic,
|
||||
override val token: KtLifetimeToken,
|
||||
) : KtFirDiagnostic.LateinitIntrinsicCallInInlineFunction(), KtAbstractFirDiagnostic<PsiElement>
|
||||
|
||||
internal class LateinitIntrinsicCallOnNonAccessiblePropertyImpl(
|
||||
override val declaration: KtSymbol,
|
||||
override val firDiagnostic: KtPsiDiagnostic,
|
||||
override val token: KtLifetimeToken,
|
||||
) : KtFirDiagnostic.LateinitIntrinsicCallOnNonAccessibleProperty(), KtAbstractFirDiagnostic<PsiElement>
|
||||
|
||||
internal class ExpectedDeclarationWithBodyImpl(
|
||||
override val firDiagnostic: KtPsiDiagnostic,
|
||||
override val token: KtLifetimeToken,
|
||||
|
||||
+7
@@ -1018,6 +1018,13 @@ object DIAGNOSTICS_LIST : DiagnosticList("FirErrors") {
|
||||
val LOCAL_VARIABLE_WITH_TYPE_PARAMETERS_WARNING by warning<KtProperty>(PositioningStrategy.TYPE_PARAMETERS_LIST)
|
||||
val LOCAL_VARIABLE_WITH_TYPE_PARAMETERS by error<KtProperty>(PositioningStrategy.TYPE_PARAMETERS_LIST)
|
||||
val EXPLICIT_TYPE_ARGUMENTS_IN_PROPERTY_ACCESS by error<KtExpression>(PositioningStrategy.REFERENCED_NAME_BY_QUALIFIED)
|
||||
|
||||
val LATEINIT_INTRINSIC_CALL_ON_NON_LITERAL by error<PsiElement>()
|
||||
val LATEINIT_INTRINSIC_CALL_ON_NON_LATEINIT by error<PsiElement>()
|
||||
val LATEINIT_INTRINSIC_CALL_IN_INLINE_FUNCTION by error<PsiElement>()
|
||||
val LATEINIT_INTRINSIC_CALL_ON_NON_ACCESSIBLE_PROPERTY by error<PsiElement>() {
|
||||
parameter<Symbol>("declaration")
|
||||
}
|
||||
}
|
||||
|
||||
val MPP_PROJECTS by object : DiagnosticGroup("Multi-platform projects") {
|
||||
|
||||
@@ -557,6 +557,10 @@ object FirErrors {
|
||||
val LOCAL_VARIABLE_WITH_TYPE_PARAMETERS_WARNING by warning0<KtProperty>(SourceElementPositioningStrategies.TYPE_PARAMETERS_LIST)
|
||||
val LOCAL_VARIABLE_WITH_TYPE_PARAMETERS by error0<KtProperty>(SourceElementPositioningStrategies.TYPE_PARAMETERS_LIST)
|
||||
val EXPLICIT_TYPE_ARGUMENTS_IN_PROPERTY_ACCESS by error0<KtExpression>(SourceElementPositioningStrategies.REFERENCED_NAME_BY_QUALIFIED)
|
||||
val LATEINIT_INTRINSIC_CALL_ON_NON_LITERAL by error0<PsiElement>()
|
||||
val LATEINIT_INTRINSIC_CALL_ON_NON_LATEINIT by error0<PsiElement>()
|
||||
val LATEINIT_INTRINSIC_CALL_IN_INLINE_FUNCTION by error0<PsiElement>()
|
||||
val LATEINIT_INTRINSIC_CALL_ON_NON_ACCESSIBLE_PROPERTY by error1<PsiElement, FirBasedSymbol<*>>()
|
||||
|
||||
// Multi-platform projects
|
||||
val EXPECTED_DECLARATION_WITH_BODY by error0<KtDeclaration>(SourceElementPositioningStrategies.DECLARATION_SIGNATURE)
|
||||
|
||||
+1
@@ -46,6 +46,7 @@ object CommonExpressionCheckers : ExpressionCheckers() {
|
||||
FirFunInterfaceConstructorReferenceChecker,
|
||||
FirReifiedChecker,
|
||||
FirSuspendCallChecker,
|
||||
FirLateinitIntrinsicApplicabilityChecker,
|
||||
)
|
||||
|
||||
override val callCheckers: Set<FirCallChecker>
|
||||
|
||||
+80
@@ -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)
|
||||
}
|
||||
}
|
||||
+9
@@ -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")
|
||||
|
||||
@@ -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<FirAnnotation>.hasAnnotation(classId: ClassId, session: FirSession): Boolean {
|
||||
return this.any { it.toAnnotationClassId(session) == classId }
|
||||
}
|
||||
|
||||
+3
-5
@@ -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 <T> chooseDiagnostic(ifWarning: T, ifError: T) =
|
||||
|
||||
+2
@@ -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
|
||||
|
||||
@@ -51,15 +51,15 @@ open class Foo : Base {
|
||||
|
||||
fun onLiteral() {
|
||||
val p = this::x
|
||||
p.isInitialized
|
||||
p.<!LATEINIT_INTRINSIC_CALL_ON_NON_LITERAL!>isInitialized<!>
|
||||
}
|
||||
|
||||
fun onNonLateinit() {
|
||||
this::nonLateInit.isInitialized
|
||||
this::nonLateInit.<!LATEINIT_INTRINSIC_CALL_ON_NON_LATEINIT!>isInitialized<!>
|
||||
}
|
||||
|
||||
inline fun inlineFun() {
|
||||
this::x.isInitialized
|
||||
this::x.<!LATEINIT_INTRINSIC_CALL_IN_INLINE_FUNCTION!>isInitialized<!>
|
||||
|
||||
object {
|
||||
val z = this@Foo::x.isInitialized
|
||||
@@ -78,22 +78,22 @@ open class Foo : Base {
|
||||
}
|
||||
|
||||
fun onNonAccessible() {
|
||||
Foo()::x.isInitialized
|
||||
Foo()::x.<!LATEINIT_INTRINSIC_CALL_ON_NON_ACCESSIBLE_PROPERTY!>isInitialized<!>
|
||||
}
|
||||
|
||||
fun onNonLateinit() {
|
||||
Foo()::nonLateInit.isInitialized
|
||||
Foo()::nonLateInit.<!LATEINIT_INTRINSIC_CALL_ON_NON_LATEINIT!>isInitialized<!>
|
||||
}
|
||||
|
||||
object Unrelated {
|
||||
fun onNonAccessible() {
|
||||
Foo()::x.isInitialized
|
||||
Foo()::x.<!LATEINIT_INTRINSIC_CALL_ON_NON_ACCESSIBLE_PROPERTY!>isInitialized<!>
|
||||
}
|
||||
}
|
||||
|
||||
class FooImpl : Foo() {
|
||||
fun onNonAccessible() {
|
||||
this::x.isInitialized
|
||||
this::x.<!LATEINIT_INTRINSIC_CALL_ON_NON_ACCESSIBLE_PROPERTY!>isInitialized<!>
|
||||
}
|
||||
}
|
||||
|
||||
@@ -101,6 +101,6 @@ class FooImpl : Foo() {
|
||||
|
||||
class OtherFooImpl : Foo() {
|
||||
fun onNonAccessible() {
|
||||
this::x.isInitialized
|
||||
this::x.<!LATEINIT_INTRINSIC_CALL_ON_NON_ACCESSIBLE_PROPERTY!>isInitialized<!>
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
@@ -1,3 +1,4 @@
|
||||
// FIR_IDENTICAL
|
||||
// !DIAGNOSTICS: -UNUSED_VARIABLE -NOTHING_TO_INLINE
|
||||
// !LANGUAGE: +NativeJsProhibitLateinitIsInitalizedIntrinsicWithoutPrivateAccess
|
||||
// FILE: stdlibInternal.kt
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
@@ -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.<!LATEINIT_INTRINSIC_CALL_ON_NON_ACCESSIBLE_PROPERTY!>isInitialized<!>
|
||||
::topLevel.<!LATEINIT_INTRINSIC_CALL_ON_NON_ACCESSIBLE_PROPERTY!>isInitialized<!>
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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<ClassId, ClassId> =
|
||||
baseCollectionToMutableEquivalent.entries.associateBy({ it.value }) { it.key }
|
||||
val mutableCollectionToBaseCollection: Map<ClassId, ClassId> =
|
||||
baseCollectionToMutableEquivalent.entries.associateBy({ it.value }) { it.key }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user