Improve support of 'lateinit' modifier
- Allow 'lateinit' for inline classes which underlying type is suitable for 'lateinit' - K2: report all problems related to 'lateinit' modifier ^KT-55052: Fixed
This commit is contained in:
committed by
teamcity
parent
e0c13e5276
commit
cd6e865fb3
@@ -495,7 +495,7 @@ class DeclarationsChecker(
|
||||
for (parameter in declaration.valueParameters) {
|
||||
trace.get(PRIMARY_CONSTRUCTOR_PARAMETER, parameter)?.let {
|
||||
modifiersChecker.checkModifiersForDeclaration(parameter, it)
|
||||
LateinitModifierApplicabilityChecker.checkLateinitModifierApplicability(trace, parameter, it)
|
||||
LateinitModifierApplicabilityChecker.checkLateinitModifierApplicability(trace, parameter, it, languageVersionSettings)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -610,7 +610,7 @@ class DeclarationsChecker(
|
||||
if (containingDeclaration is ClassDescriptor) {
|
||||
checkMemberProperty(property, propertyDescriptor, containingDeclaration)
|
||||
}
|
||||
LateinitModifierApplicabilityChecker.checkLateinitModifierApplicability(trace, property, propertyDescriptor)
|
||||
LateinitModifierApplicabilityChecker.checkLateinitModifierApplicability(trace, property, propertyDescriptor, languageVersionSettings)
|
||||
checkPropertyInitializer(property, propertyDescriptor)
|
||||
checkAccessors(property, propertyDescriptor)
|
||||
checkTypeParameterConstraints(property)
|
||||
|
||||
+61
-6
@@ -18,6 +18,9 @@ package org.jetbrains.kotlin.resolve
|
||||
|
||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||
import org.jetbrains.kotlin.builtins.UnsignedTypes
|
||||
import org.jetbrains.kotlin.config.LanguageFeature
|
||||
import org.jetbrains.kotlin.config.LanguageVersionSettings
|
||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.Modality
|
||||
import org.jetbrains.kotlin.descriptors.PropertyDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.VariableDescriptor
|
||||
@@ -28,10 +31,18 @@ import org.jetbrains.kotlin.psi.KtCallableDeclaration
|
||||
import org.jetbrains.kotlin.psi.KtParameter
|
||||
import org.jetbrains.kotlin.psi.KtProperty
|
||||
import org.jetbrains.kotlin.resolve.DeclarationsChecker.Companion.hasAccessorImplementation
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.inlineClassRepresentation
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
import org.jetbrains.kotlin.types.TypeUtils
|
||||
import org.jetbrains.kotlin.types.typeUtil.isUnsignedNumberType
|
||||
|
||||
object LateinitModifierApplicabilityChecker {
|
||||
fun checkLateinitModifierApplicability(trace: BindingTrace, ktDeclaration: KtCallableDeclaration, descriptor: VariableDescriptor) {
|
||||
fun checkLateinitModifierApplicability(
|
||||
trace: BindingTrace,
|
||||
ktDeclaration: KtCallableDeclaration,
|
||||
descriptor: VariableDescriptor,
|
||||
languageVersionSettings: LanguageVersionSettings
|
||||
) {
|
||||
if (!ktDeclaration.hasModifier(KtTokens.LATEINIT_KEYWORD)) return
|
||||
|
||||
val variables = when (descriptor) {
|
||||
@@ -47,10 +58,27 @@ object LateinitModifierApplicabilityChecker {
|
||||
}
|
||||
|
||||
if (type.isInlineClassType()) {
|
||||
if (UnsignedTypes.isUnsignedType(type)) {
|
||||
trace.report(Errors.INAPPLICABLE_LATEINIT_MODIFIER.on(ktDeclaration, "is not allowed on $variables of unsigned types"))
|
||||
} else {
|
||||
trace.report(Errors.INAPPLICABLE_LATEINIT_MODIFIER.on(ktDeclaration, "is not allowed on $variables of inline class types"))
|
||||
when {
|
||||
type.isUnsignedNumberType() -> trace.report(
|
||||
Errors.INAPPLICABLE_LATEINIT_MODIFIER.on(
|
||||
ktDeclaration,
|
||||
"is not allowed on $variables of unsigned types"
|
||||
)
|
||||
)
|
||||
!languageVersionSettings.supportsFeature(LanguageFeature.InlineLateinit) ->
|
||||
trace.report(
|
||||
Errors.INAPPLICABLE_LATEINIT_MODIFIER.on(
|
||||
ktDeclaration,
|
||||
"is not allowed on $variables of inline class types"
|
||||
)
|
||||
)
|
||||
hasUnderlyingTypeForbiddenForLateinit(type) ->
|
||||
trace.report(
|
||||
Errors.INAPPLICABLE_LATEINIT_MODIFIER.on(
|
||||
ktDeclaration,
|
||||
"is not allowed on $variables of inline type with underlying type not suitable for lateinit declaration"
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -100,7 +128,12 @@ object LateinitModifierApplicabilityChecker {
|
||||
)
|
||||
)
|
||||
} else if (!isAbstract && !hasBackingField) {
|
||||
trace.report(Errors.INAPPLICABLE_LATEINIT_MODIFIER.on(ktDeclaration, "is not allowed on properties without backing field"))
|
||||
trace.report(
|
||||
Errors.INAPPLICABLE_LATEINIT_MODIFIER.on(
|
||||
ktDeclaration,
|
||||
"is not allowed on properties without backing field"
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -109,4 +142,26 @@ object LateinitModifierApplicabilityChecker {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun hasUnderlyingTypeForbiddenForLateinit(type: KotlinType): Boolean {
|
||||
|
||||
fun getUnderlyingType(type: KotlinType): KotlinType {
|
||||
return (type.constructor.declarationDescriptor as ClassDescriptor).inlineClassRepresentation!!.underlyingType
|
||||
}
|
||||
|
||||
fun isForbiddenForLateinit(type: KotlinType): Boolean {
|
||||
if (type.isMarkedNullable || TypeUtils.isNullableType(type)) return true
|
||||
if (KotlinBuiltIns.isPrimitiveType(type)) return true
|
||||
if (type.isInlineClassType()) {
|
||||
return isForbiddenForLateinit(getUnderlyingType(type))
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// prevent infinite recursion
|
||||
if (type.isRecursiveInlineOrValueClassType()) return false
|
||||
return isForbiddenForLateinit(getUnderlyingType(type))
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -150,7 +150,7 @@ class LocalVariableResolver(
|
||||
modifiersChecker.withTrace(context.trace).checkModifiersForLocalDeclaration(ktProperty, descriptor)
|
||||
identifierChecker.checkDeclaration(ktProperty, context.trace)
|
||||
|
||||
LateinitModifierApplicabilityChecker.checkLateinitModifierApplicability(context.trace, ktProperty, descriptor)
|
||||
LateinitModifierApplicabilityChecker.checkLateinitModifierApplicability(context.trace, ktProperty, descriptor, languageVersionSettings)
|
||||
}
|
||||
|
||||
private fun resolveLocalVariableDescriptor(
|
||||
|
||||
Reference in New Issue
Block a user