Value classes: Add JvmInlineValueClasses language feature

This commit is contained in:
Ilmir Usmanov
2020-12-17 20:27:32 +01:00
parent 48d9812d9e
commit f922ebbfc3
9 changed files with 71 additions and 7 deletions
@@ -119,8 +119,7 @@ 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),
VALUE_KEYWORD to listOf(LanguageFeature.InlineClasses)
FUN_KEYWORD to listOf(LanguageFeature.FunctionalInterfaceConversion)
)
private val featureDependenciesTargets = mapOf(
@@ -128,6 +127,7 @@ object ModifierCheckerCore {
LanguageFeature.LateinitLocalVariables to setOf(LOCAL_VARIABLE),
LanguageFeature.LateinitTopLevelProperties to setOf(TOP_LEVEL_PROPERTY),
LanguageFeature.InlineClasses to setOf(CLASS_ONLY),
LanguageFeature.JvmInlineValueClasses to setOf(CLASS_ONLY),
LanguageFeature.FunctionalInterfaceConversion to setOf(INTERFACE)
)
@@ -7,6 +7,7 @@ package org.jetbrains.kotlin.resolve.checkers
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.builtins.StandardNames
import org.jetbrains.kotlin.config.LanguageFeature
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.diagnostics.Errors
import org.jetbrains.kotlin.lexer.KtTokens
@@ -32,11 +33,28 @@ object InlineClassDeclarationChecker : DeclarationChecker {
if (descriptor !is ClassDescriptor || !descriptor.isInline && !descriptor.isValue) return
if (descriptor.kind != ClassKind.CLASS) return
val inlineOrValueKeyword = declaration.modifierList?.getModifier(KtTokens.INLINE_KEYWORD)
?: declaration.modifierList?.getModifier(KtTokens.VALUE_KEYWORD)
val trace = context.trace
val valueKeyword = declaration.modifierList?.getModifier(KtTokens.VALUE_KEYWORD)
// The check cannot be done in ModifierCheckerCore, since `value` keyword is enabled by one of two features, not by both of
// them simultaneously
if (valueKeyword != null) {
if (!context.languageVersionSettings.supportsFeature(LanguageFeature.JvmInlineValueClasses) &&
!context.languageVersionSettings.supportsFeature(LanguageFeature.InlineClasses)
) {
trace.report(
Errors.UNSUPPORTED_FEATURE.on(
valueKeyword, LanguageFeature.JvmInlineValueClasses to context.languageVersionSettings
)
)
return
}
}
val inlineOrValueKeyword = declaration.modifierList?.getModifier(KtTokens.INLINE_KEYWORD) ?: valueKeyword
require(inlineOrValueKeyword != null) { "Declaration of inline class must have 'inline' keyword" }
val trace = context.trace
if (descriptor.isInner || DescriptorUtils.isLocal(descriptor)) {
trace.report(Errors.INLINE_CLASS_NOT_TOP_LEVEL.on(inlineOrValueKeyword))
return
@@ -21,7 +21,8 @@ class ResultClassInReturnTypeChecker : DeclarationChecker {
val languageVersionSettings = context.languageVersionSettings
if (
languageVersionSettings.getFlag(AnalysisFlags.allowResultReturnType) ||
languageVersionSettings.getFeatureSupport(LanguageFeature.InlineClasses) == LanguageFeature.State.ENABLED &&
(languageVersionSettings.getFeatureSupport(LanguageFeature.InlineClasses) == LanguageFeature.State.ENABLED ||
languageVersionSettings.supportsFeature(LanguageFeature.JvmInlineValueClasses)) &&
languageVersionSettings.supportsFeature(LanguageFeature.AllowResultInReturnType)
) return
@@ -13,4 +13,4 @@ annotation class JvmInline
<!VALUE_CLASS_WITHOUT_JVM_INLINE_ANNOTATION, WRONG_MODIFIER_TARGET!>value<!> enum class InlineEnum
@JvmInline
<!UNSUPPORTED_FEATURE!>value<!> class NotVal(<!INLINE_CLASS_CONSTRUCTOR_NOT_FINAL_READ_ONLY_PARAMETER!>x: Int<!>)
<!UNSUPPORTED_FEATURE!>value<!> class NotVal(x: Int)
@@ -0,0 +1,9 @@
// !LANGUAGE: +JvmInlineValueClasses
// WITH_RUNTIME
package kotlin.jvm
annotation class JvmInline
@JvmInline
value class VC(val a: Any)
@@ -0,0 +1,23 @@
package
package kotlin {
package kotlin.jvm {
public final annotation class JvmInline : kotlin.Annotation {
public constructor JvmInline()
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
@kotlin.jvm.JvmInline public final value class VC {
public constructor VC(/*0*/ a: kotlin.Any)
public final val a: kotlin.Any
public open override /*1*/ /*synthesized*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*synthesized*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*synthesized*/ fun toString(): kotlin.String
}
}
}
@@ -43,6 +43,12 @@ public class DiagnosticsTestWithJvmIrBackendGenerated extends AbstractDiagnostic
runTest("compiler/testData/diagnostics/testsWithJvmBackend/multipleBigArityFunsImplemented_ir.kt");
}
@Test
@TestMetadata("noWarningInLV1_5.kt")
public void testNoWarningInLV1_5() throws Exception {
runTest("compiler/testData/diagnostics/testsWithJvmBackend/noWarningInLV1_5.kt");
}
@Test
@TestMetadata("suspendInlineCycle_ir.kt")
public void testSuspendInlineCycle_ir() throws Exception {
@@ -43,6 +43,12 @@ public class DiagnosticsTestWithOldJvmBackendGenerated extends AbstractDiagnosti
runTest("compiler/testData/diagnostics/testsWithJvmBackend/multipleBigArityFunsImplemented.kt");
}
@Test
@TestMetadata("noWarningInLV1_5.kt")
public void testNoWarningInLV1_5() throws Exception {
runTest("compiler/testData/diagnostics/testsWithJvmBackend/noWarningInLV1_5.kt");
}
@Test
@TestMetadata("suspendInlineCycle.kt")
public void testSuspendInlineCycle() throws Exception {
@@ -194,6 +194,7 @@ enum class LanguageFeature(
// Next features can be enabled regardless of new inference
InlineClasses(sinceVersion = KOTLIN_1_3, defaultState = State.ENABLED_WITH_WARNING, kind = UNSTABLE_FEATURE),
JvmInlineValueClasses(sinceVersion = KOTLIN_1_5, defaultState = State.ENABLED, kind = OTHER),
;
val presentableName: String