Value classes: treat @JvmInline value classes as inline classes
Report error on value classes without @JvmInline annotation. Do not check for @JvmInline annotation in value classes since it breaks reflection.
This commit is contained in:
@@ -362,6 +362,7 @@ public interface Errors {
|
||||
DiagnosticFactory0<KtTypeReference> INLINE_CLASS_CANNOT_BE_RECURSIVE = DiagnosticFactory0.create(ERROR);
|
||||
DiagnosticFactory1<PsiElement, String> RESERVED_MEMBER_INSIDE_INLINE_CLASS = DiagnosticFactory1.create(ERROR);
|
||||
DiagnosticFactory0<PsiElement> SECONDARY_CONSTRUCTOR_WITH_BODY_INSIDE_INLINE_CLASS = DiagnosticFactory0.create(ERROR);
|
||||
DiagnosticFactory0<PsiElement> VALUE_CLASS_WITHOUT_JVM_INLINE_ANNOTATION = DiagnosticFactory0.create(ERROR);
|
||||
|
||||
// Result class
|
||||
|
||||
|
||||
+1
@@ -717,6 +717,7 @@ public class DefaultErrorMessages {
|
||||
MAP.put(INLINE_CLASS_CANNOT_BE_RECURSIVE, "Inline class cannot be recursive");
|
||||
MAP.put(RESERVED_MEMBER_INSIDE_INLINE_CLASS, "Member with the name ''{0}'' is reserved for future releases", STRING);
|
||||
MAP.put(SECONDARY_CONSTRUCTOR_WITH_BODY_INSIDE_INLINE_CLASS, "Secondary constructors with bodies are reserved for for future releases");
|
||||
MAP.put(VALUE_CLASS_WITHOUT_JVM_INLINE_ANNOTATION, "Value classes without @JvmInline annotation are not supported yet");
|
||||
|
||||
MAP.put(RESULT_CLASS_IN_RETURN_TYPE, "'kotlin.Result' cannot be used as a return type");
|
||||
MAP.put(RESULT_CLASS_WITH_NULLABLE_OPERATOR, "Expression of type 'kotlin.Result' cannot be used as a left operand of ''{0}''", STRING);
|
||||
|
||||
@@ -270,7 +270,7 @@ class DeclarationsChecker(
|
||||
|
||||
if (declaration is KtPrimaryConstructor &&
|
||||
!DescriptorUtils.isAnnotationClass(constructorDescriptor.constructedClass) &&
|
||||
!constructorDescriptor.constructedClass.isInline
|
||||
!constructorDescriptor.constructedClass.isInlineClass()
|
||||
) {
|
||||
for (parameter in declaration.valueParameters) {
|
||||
if (parameter.hasValOrVar()) {
|
||||
|
||||
@@ -107,7 +107,8 @@ object ModifierCheckerCore {
|
||||
ANNOTATION_CLASS,
|
||||
TYPEALIAS
|
||||
),
|
||||
FUN_KEYWORD to EnumSet.of(INTERFACE)
|
||||
FUN_KEYWORD to EnumSet.of(INTERFACE),
|
||||
VALUE_KEYWORD to EnumSet.of(CLASS_ONLY)
|
||||
)
|
||||
|
||||
private val featureDependencies = mapOf(
|
||||
@@ -118,7 +119,8 @@ object ModifierCheckerCore {
|
||||
EXPECT_KEYWORD to listOf(LanguageFeature.MultiPlatformProjects),
|
||||
ACTUAL_KEYWORD to listOf(LanguageFeature.MultiPlatformProjects),
|
||||
LATEINIT_KEYWORD to listOf(LanguageFeature.LateinitTopLevelProperties, LanguageFeature.LateinitLocalVariables),
|
||||
FUN_KEYWORD to listOf(LanguageFeature.FunctionalInterfaceConversion)
|
||||
FUN_KEYWORD to listOf(LanguageFeature.FunctionalInterfaceConversion),
|
||||
VALUE_KEYWORD to listOf(LanguageFeature.InlineClasses)
|
||||
)
|
||||
|
||||
private val featureDependenciesTargets = mapOf(
|
||||
@@ -185,12 +187,13 @@ object ModifierCheckerCore {
|
||||
result += incompatibilityRegister(PRIVATE_KEYWORD, PROTECTED_KEYWORD, PUBLIC_KEYWORD, INTERNAL_KEYWORD)
|
||||
// Abstract + open + final + sealed: incompatible
|
||||
result += incompatibilityRegister(ABSTRACT_KEYWORD, OPEN_KEYWORD, FINAL_KEYWORD, SEALED_KEYWORD)
|
||||
// data + open, data + inner, data + abstract, data + sealed, data + inline
|
||||
// data + open, data + inner, data + abstract, data + sealed, data + inline, data + value
|
||||
result += incompatibilityRegister(DATA_KEYWORD, OPEN_KEYWORD)
|
||||
result += incompatibilityRegister(DATA_KEYWORD, INNER_KEYWORD)
|
||||
result += incompatibilityRegister(DATA_KEYWORD, ABSTRACT_KEYWORD)
|
||||
result += incompatibilityRegister(DATA_KEYWORD, SEALED_KEYWORD)
|
||||
result += incompatibilityRegister(DATA_KEYWORD, INLINE_KEYWORD)
|
||||
result += incompatibilityRegister(DATA_KEYWORD, VALUE_KEYWORD)
|
||||
// open is redundant to abstract & override
|
||||
result += redundantRegister(ABSTRACT_KEYWORD, OPEN_KEYWORD)
|
||||
// abstract is redundant to sealed
|
||||
|
||||
+11
-6
@@ -9,9 +9,9 @@ import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.diagnostics.Errors
|
||||
import org.jetbrains.kotlin.lexer.KtTokens
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.psi.psiUtil.modalityModifier
|
||||
import org.jetbrains.kotlin.psi.psiUtil.visibilityModifier
|
||||
import org.jetbrains.kotlin.resolve.*
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
import org.jetbrains.kotlin.types.typeUtil.isNothing
|
||||
@@ -22,15 +22,16 @@ import org.jetbrains.kotlin.utils.addToStdlib.safeAs
|
||||
object InlineClassDeclarationChecker : DeclarationChecker {
|
||||
override fun check(declaration: KtDeclaration, descriptor: DeclarationDescriptor, context: DeclarationCheckerContext) {
|
||||
if (declaration !is KtClass) return
|
||||
if (descriptor !is ClassDescriptor || !descriptor.isInline) return
|
||||
if (descriptor !is ClassDescriptor || !descriptor.isInline && !descriptor.isValue) return
|
||||
if (descriptor.kind != ClassKind.CLASS) return
|
||||
|
||||
val inlineKeyword = declaration.modifierList?.getModifier(KtTokens.INLINE_KEYWORD)
|
||||
require(inlineKeyword != null) { "Declaration of inline class must have 'inline' keyword" }
|
||||
val inlineOrValueKeyword = declaration.modifierList?.getModifier(KtTokens.INLINE_KEYWORD)
|
||||
?: declaration.modifierList?.getModifier(KtTokens.VALUE_KEYWORD)
|
||||
require(inlineOrValueKeyword != null) { "Declaration of inline class must have 'inline' keyword" }
|
||||
|
||||
val trace = context.trace
|
||||
if (!DescriptorUtils.isTopLevelDeclaration(descriptor)) {
|
||||
trace.report(Errors.INLINE_CLASS_NOT_TOP_LEVEL.on(inlineKeyword))
|
||||
trace.report(Errors.INLINE_CLASS_NOT_TOP_LEVEL.on(inlineOrValueKeyword))
|
||||
return
|
||||
}
|
||||
|
||||
@@ -42,7 +43,7 @@ object InlineClassDeclarationChecker : DeclarationChecker {
|
||||
|
||||
val primaryConstructor = declaration.primaryConstructor
|
||||
if (primaryConstructor == null) {
|
||||
trace.report(Errors.ABSENCE_OF_PRIMARY_CONSTRUCTOR_FOR_INLINE_CLASS.on(inlineKeyword))
|
||||
trace.report(Errors.ABSENCE_OF_PRIMARY_CONSTRUCTOR_FOR_INLINE_CLASS.on(inlineOrValueKeyword))
|
||||
return
|
||||
}
|
||||
|
||||
@@ -87,6 +88,10 @@ object InlineClassDeclarationChecker : DeclarationChecker {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (descriptor.isValue && !descriptor.annotations.hasAnnotation(JVM_INLINE_ANNOTATION)) {
|
||||
trace.report(Errors.VALUE_CLASS_WITHOUT_JVM_INLINE_ANNOTATION.on(inlineOrValueKeyword))
|
||||
}
|
||||
}
|
||||
|
||||
private fun KotlinType.isInapplicableParameterType() =
|
||||
|
||||
+1
-1
@@ -258,7 +258,7 @@ open class LazyClassMemberScope(
|
||||
name: Name,
|
||||
fromSupertypes: List<SimpleFunctionDescriptor>
|
||||
) {
|
||||
if (!thisDescriptor.isInline) return
|
||||
if (!thisDescriptor.isInlineClass()) return
|
||||
addFunctionFromAnyIfNeeded(result, name, fromSupertypes)
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user