Value Classes: Forbid var properties with value class receivers

This commit is contained in:
Ilmir Usmanov
2020-11-27 20:36:38 +01:00
parent 19b16da183
commit f43899086a
14 changed files with 79 additions and 18 deletions
@@ -12957,6 +12957,11 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirOldFronte
runTest("compiler/testData/diagnostics/tests/inlineClasses/unsignedLiteralsWithoutArtifactOnClasspath.kt"); runTest("compiler/testData/diagnostics/tests/inlineClasses/unsignedLiteralsWithoutArtifactOnClasspath.kt");
} }
@TestMetadata("varPropertyWithInlineClassReceiver.kt")
public void testVarPropertyWithInlineClassReceiver() throws Exception {
runTest("compiler/testData/diagnostics/tests/inlineClasses/varPropertyWithInlineClassReceiver.kt");
}
@TestMetadata("varargsOnParametersOfInlineClassType.kt") @TestMetadata("varargsOnParametersOfInlineClassType.kt")
public void testVarargsOnParametersOfInlineClassType() throws Exception { public void testVarargsOnParametersOfInlineClassType() throws Exception {
runTest("compiler/testData/diagnostics/tests/inlineClasses/varargsOnParametersOfInlineClassType.kt"); runTest("compiler/testData/diagnostics/tests/inlineClasses/varargsOnParametersOfInlineClassType.kt");
@@ -347,7 +347,7 @@ public interface Errors {
DiagnosticFactory0<PsiElement> NON_PRIVATE_CONSTRUCTOR_IN_ENUM = DiagnosticFactory0.create(ERROR); DiagnosticFactory0<PsiElement> NON_PRIVATE_CONSTRUCTOR_IN_ENUM = DiagnosticFactory0.create(ERROR);
DiagnosticFactory0<PsiElement> NON_PRIVATE_CONSTRUCTOR_IN_SEALED = DiagnosticFactory0.create(ERROR); DiagnosticFactory0<PsiElement> NON_PRIVATE_CONSTRUCTOR_IN_SEALED = DiagnosticFactory0.create(ERROR);
// Inline classes // Inline and value classes
DiagnosticFactory0<PsiElement> INLINE_CLASS_NOT_TOP_LEVEL = DiagnosticFactory0.create(ERROR); DiagnosticFactory0<PsiElement> INLINE_CLASS_NOT_TOP_LEVEL = DiagnosticFactory0.create(ERROR);
DiagnosticFactory0<PsiElement> INLINE_CLASS_NOT_FINAL = DiagnosticFactory0.create(ERROR); DiagnosticFactory0<PsiElement> INLINE_CLASS_NOT_FINAL = DiagnosticFactory0.create(ERROR);
@@ -355,6 +355,7 @@ public interface Errors {
DiagnosticFactory0<KtElement> INLINE_CLASS_CONSTRUCTOR_WRONG_PARAMETERS_SIZE = DiagnosticFactory0.create(ERROR); DiagnosticFactory0<KtElement> INLINE_CLASS_CONSTRUCTOR_WRONG_PARAMETERS_SIZE = DiagnosticFactory0.create(ERROR);
DiagnosticFactory0<KtParameter> INLINE_CLASS_CONSTRUCTOR_NOT_FINAL_READ_ONLY_PARAMETER = DiagnosticFactory0.create(ERROR); DiagnosticFactory0<KtParameter> INLINE_CLASS_CONSTRUCTOR_NOT_FINAL_READ_ONLY_PARAMETER = DiagnosticFactory0.create(ERROR);
DiagnosticFactory0<KtProperty> PROPERTY_WITH_BACKING_FIELD_INSIDE_INLINE_CLASS = DiagnosticFactory0.create(ERROR, DECLARATION_SIGNATURE); DiagnosticFactory0<KtProperty> PROPERTY_WITH_BACKING_FIELD_INSIDE_INLINE_CLASS = DiagnosticFactory0.create(ERROR, DECLARATION_SIGNATURE);
DiagnosticFactory0<PsiElement> RESERVED_VAR_PROPERTY_OF_VALUE_CLASS = DiagnosticFactory0.create(WARNING);
DiagnosticFactory0<PsiElement> DELEGATED_PROPERTY_INSIDE_INLINE_CLASS = DiagnosticFactory0.create(ERROR); DiagnosticFactory0<PsiElement> DELEGATED_PROPERTY_INSIDE_INLINE_CLASS = DiagnosticFactory0.create(ERROR);
DiagnosticFactory1<KtTypeReference, KotlinType> INLINE_CLASS_HAS_INAPPLICABLE_PARAMETER_TYPE = DiagnosticFactory1.create(ERROR); DiagnosticFactory1<KtTypeReference, KotlinType> INLINE_CLASS_HAS_INAPPLICABLE_PARAMETER_TYPE = DiagnosticFactory1.create(ERROR);
DiagnosticFactory0<PsiElement> INLINE_CLASS_CANNOT_IMPLEMENT_INTERFACE_BY_DELEGATION = DiagnosticFactory0.create(ERROR); DiagnosticFactory0<PsiElement> INLINE_CLASS_CANNOT_IMPLEMENT_INTERFACE_BY_DELEGATION = DiagnosticFactory0.create(ERROR);
@@ -710,6 +710,7 @@ public class DefaultErrorMessages {
MAP.put(INLINE_CLASS_CONSTRUCTOR_WRONG_PARAMETERS_SIZE, "Inline class must have exactly one primary constructor parameter"); MAP.put(INLINE_CLASS_CONSTRUCTOR_WRONG_PARAMETERS_SIZE, "Inline class must have exactly one primary constructor parameter");
MAP.put(INLINE_CLASS_CONSTRUCTOR_NOT_FINAL_READ_ONLY_PARAMETER, "Value class primary constructor must have only final read-only (val) property parameter"); MAP.put(INLINE_CLASS_CONSTRUCTOR_NOT_FINAL_READ_ONLY_PARAMETER, "Value class primary constructor must have only final read-only (val) property parameter");
MAP.put(PROPERTY_WITH_BACKING_FIELD_INSIDE_INLINE_CLASS, "Inline class cannot have properties with backing fields"); MAP.put(PROPERTY_WITH_BACKING_FIELD_INSIDE_INLINE_CLASS, "Inline class cannot have properties with backing fields");
MAP.put(RESERVED_VAR_PROPERTY_OF_VALUE_CLASS, "'var' properties with value class receivers are reserved for future use");
MAP.put(DELEGATED_PROPERTY_INSIDE_INLINE_CLASS, "Inline class cannot have delegated properties"); MAP.put(DELEGATED_PROPERTY_INSIDE_INLINE_CLASS, "Inline class cannot have delegated properties");
MAP.put(INLINE_CLASS_HAS_INAPPLICABLE_PARAMETER_TYPE, "Inline class cannot have value parameter of type ''{0}''", RENDER_TYPE); MAP.put(INLINE_CLASS_HAS_INAPPLICABLE_PARAMETER_TYPE, "Inline class cannot have value parameter of type ''{0}''", RENDER_TYPE);
MAP.put(INLINE_CLASS_CANNOT_IMPLEMENT_INTERFACE_BY_DELEGATION, "Inline class cannot implement an interface by delegation"); MAP.put(INLINE_CLASS_CANNOT_IMPLEMENT_INTERFACE_BY_DELEGATION, "Inline class cannot implement an interface by delegation");
@@ -27,8 +27,8 @@ private val DEFAULT_DECLARATION_CHECKERS = listOf(
KClassWithIncorrectTypeArgumentChecker, KClassWithIncorrectTypeArgumentChecker,
SuspendLimitationsChecker, SuspendLimitationsChecker,
InlineClassDeclarationChecker, InlineClassDeclarationChecker,
PropertiesWithBackingFieldsInsideInlineClass(),
InnerClassInsideInlineClass(), InnerClassInsideInlineClass(),
PropertiesWithInlineClassAsReceiver(),
AnnotationClassTargetAndRetentionChecker(), AnnotationClassTargetAndRetentionChecker(),
ReservedMembersAndConstructsForInlineClass(), ReservedMembersAndConstructsForInlineClass(),
ResultClassInReturnTypeChecker(), ResultClassInReturnTypeChecker(),
@@ -107,19 +107,27 @@ object InlineClassDeclarationChecker : DeclarationChecker {
} }
} }
class PropertiesWithBackingFieldsInsideInlineClass : DeclarationChecker { class PropertiesWithInlineClassAsReceiver : DeclarationChecker {
override fun check(declaration: KtDeclaration, descriptor: DeclarationDescriptor, context: DeclarationCheckerContext) { override fun check(declaration: KtDeclaration, descriptor: DeclarationDescriptor, context: DeclarationCheckerContext) {
if (declaration !is KtProperty) return if (declaration !is KtProperty) return
if (descriptor !is PropertyDescriptor) return if (descriptor !is PropertyDescriptor) return
if (!descriptor.containingDeclaration.isInlineClass()) return if (descriptor.containingDeclaration.isInlineClass()) {
if (context.trace.get(BindingContext.BACKING_FIELD_REQUIRED, descriptor) == true) {
context.trace.report(Errors.PROPERTY_WITH_BACKING_FIELD_INSIDE_INLINE_CLASS.on(declaration))
}
if (context.trace.get(BindingContext.BACKING_FIELD_REQUIRED, descriptor) == true) { declaration.delegate?.let {
context.trace.report(Errors.PROPERTY_WITH_BACKING_FIELD_INSIDE_INLINE_CLASS.on(declaration)) context.trace.report(Errors.DELEGATED_PROPERTY_INSIDE_INLINE_CLASS.on(it))
}
} }
declaration.delegate?.let { if (!descriptor.isVar) return
context.trace.report(Errors.DELEGATED_PROPERTY_INSIDE_INLINE_CLASS.on(it))
if (descriptor.containingDeclaration.isInlineClass() ||
descriptor.extensionReceiverParameter?.type?.isInlineClassType() == true
) {
context.trace.report(Errors.RESERVED_VAR_PROPERTY_OF_VALUE_CLASS.on(declaration.valOrVarKeyword))
} }
} }
} }
@@ -21,8 +21,8 @@ object VarObject {
inline class Z(val data: Int) { inline class Z(val data: Int) {
val testVal <!DELEGATED_PROPERTY_INSIDE_INLINE_CLASS!>by Val()<!> val testVal <!DELEGATED_PROPERTY_INSIDE_INLINE_CLASS!>by Val()<!>
var testVar <!DELEGATED_PROPERTY_INSIDE_INLINE_CLASS!>by Var()<!> <!RESERVED_VAR_PROPERTY_OF_VALUE_CLASS!>var<!> testVar <!DELEGATED_PROPERTY_INSIDE_INLINE_CLASS!>by Var()<!>
val testValBySingleton <!DELEGATED_PROPERTY_INSIDE_INLINE_CLASS!>by ValObject<!> val testValBySingleton <!DELEGATED_PROPERTY_INSIDE_INLINE_CLASS!>by ValObject<!>
var testVarBySingleton <!DELEGATED_PROPERTY_INSIDE_INLINE_CLASS!>by VarObject<!> <!RESERVED_VAR_PROPERTY_OF_VALUE_CLASS!>var<!> testVarBySingleton <!DELEGATED_PROPERTY_INSIDE_INLINE_CLASS!>by VarObject<!>
} }
@@ -15,11 +15,11 @@ inline class Foo(val x: Int) : A, B {
<!PROPERTY_WITH_BACKING_FIELD_INSIDE_INLINE_CLASS!>val a1<!> = 0 <!PROPERTY_WITH_BACKING_FIELD_INSIDE_INLINE_CLASS!>val a1<!> = 0
var a2: Int <!RESERVED_VAR_PROPERTY_OF_VALUE_CLASS!>var<!> a2: Int
get() = 1 get() = 1
set(value) {} set(value) {}
<!PROPERTY_WITH_BACKING_FIELD_INSIDE_INLINE_CLASS!>var a3: Int<!> = 0 <!PROPERTY_WITH_BACKING_FIELD_INSIDE_INLINE_CLASS!><!RESERVED_VAR_PROPERTY_OF_VALUE_CLASS!>var<!> a3: Int<!> = 0
get() = 1 get() = 1
set(value) { set(value) {
field = value field = value
@@ -30,5 +30,5 @@ inline class Foo(val x: Int) : A, B {
<!PROPERTY_WITH_BACKING_FIELD_INSIDE_INLINE_CLASS!>override val badSize: Int<!> = 0 <!PROPERTY_WITH_BACKING_FIELD_INSIDE_INLINE_CLASS!>override val badSize: Int<!> = 0
<!PROPERTY_WITH_BACKING_FIELD_INSIDE_INLINE_CLASS!>lateinit var lateinitProperty: String<!> <!PROPERTY_WITH_BACKING_FIELD_INSIDE_INLINE_CLASS!>lateinit <!RESERVED_VAR_PROPERTY_OF_VALUE_CLASS!>var<!> lateinitProperty: String<!>
} }
@@ -0,0 +1,12 @@
// !LANGUAGE: +InlineClasses
// !DIAGNOSTICS: -UNUSED_PARAMETER
inline class IC(val a: Any) {
var member: Any
get() = a
set(value) {}
}
var IC.extension: Any
get() = a
set(value) {}
@@ -0,0 +1,12 @@
// !LANGUAGE: +InlineClasses
// !DIAGNOSTICS: -UNUSED_PARAMETER
inline class IC(val a: Any) {
<!RESERVED_VAR_PROPERTY_OF_VALUE_CLASS!>var<!> member: Any
get() = a
set(value) {}
}
<!RESERVED_VAR_PROPERTY_OF_VALUE_CLASS!>var<!> IC.extension: Any
get() = a
set(value) {}
@@ -0,0 +1,12 @@
package
public var IC.extension: kotlin.Any
public final inline class IC {
public constructor IC(/*0*/ a: kotlin.Any)
public final val a: kotlin.Any
public final var member: 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
}
@@ -26,8 +26,8 @@ object VarObject {
@JvmInline @JvmInline
value class Z(val data: Int) { value class Z(val data: Int) {
val testVal <!DELEGATED_PROPERTY_INSIDE_INLINE_CLASS!>by Val()<!> val testVal <!DELEGATED_PROPERTY_INSIDE_INLINE_CLASS!>by Val()<!>
var testVar <!DELEGATED_PROPERTY_INSIDE_INLINE_CLASS!>by Var()<!> <!RESERVED_VAR_PROPERTY_OF_VALUE_CLASS!>var<!> testVar <!DELEGATED_PROPERTY_INSIDE_INLINE_CLASS!>by Var()<!>
val testValBySingleton <!DELEGATED_PROPERTY_INSIDE_INLINE_CLASS!>by ValObject<!> val testValBySingleton <!DELEGATED_PROPERTY_INSIDE_INLINE_CLASS!>by ValObject<!>
var testVarBySingleton <!DELEGATED_PROPERTY_INSIDE_INLINE_CLASS!>by VarObject<!> <!RESERVED_VAR_PROPERTY_OF_VALUE_CLASS!>var<!> testVarBySingleton <!DELEGATED_PROPERTY_INSIDE_INLINE_CLASS!>by VarObject<!>
} }
@@ -20,11 +20,11 @@ value class Foo(val x: Int) : A, B {
<!PROPERTY_WITH_BACKING_FIELD_INSIDE_INLINE_CLASS!>val a1<!> = 0 <!PROPERTY_WITH_BACKING_FIELD_INSIDE_INLINE_CLASS!>val a1<!> = 0
var a2: Int <!RESERVED_VAR_PROPERTY_OF_VALUE_CLASS!>var<!> a2: Int
get() = 1 get() = 1
set(value) {} set(value) {}
<!PROPERTY_WITH_BACKING_FIELD_INSIDE_INLINE_CLASS!>var a3: Int<!> = 0 <!PROPERTY_WITH_BACKING_FIELD_INSIDE_INLINE_CLASS!><!RESERVED_VAR_PROPERTY_OF_VALUE_CLASS!>var<!> a3: Int<!> = 0
get() = 1 get() = 1
set(value) { set(value) {
field = value field = value
@@ -35,5 +35,5 @@ value class Foo(val x: Int) : A, B {
<!PROPERTY_WITH_BACKING_FIELD_INSIDE_INLINE_CLASS!>override val badSize: Int<!> = 0 <!PROPERTY_WITH_BACKING_FIELD_INSIDE_INLINE_CLASS!>override val badSize: Int<!> = 0
<!PROPERTY_WITH_BACKING_FIELD_INSIDE_INLINE_CLASS!>lateinit var lateinitProperty: String<!> <!PROPERTY_WITH_BACKING_FIELD_INSIDE_INLINE_CLASS!>lateinit <!RESERVED_VAR_PROPERTY_OF_VALUE_CLASS!>var<!> lateinitProperty: String<!>
} }
@@ -12964,6 +12964,11 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTestWithFirVali
runTest("compiler/testData/diagnostics/tests/inlineClasses/unsignedLiteralsWithoutArtifactOnClasspath.kt"); runTest("compiler/testData/diagnostics/tests/inlineClasses/unsignedLiteralsWithoutArtifactOnClasspath.kt");
} }
@TestMetadata("varPropertyWithInlineClassReceiver.kt")
public void testVarPropertyWithInlineClassReceiver() throws Exception {
runTest("compiler/testData/diagnostics/tests/inlineClasses/varPropertyWithInlineClassReceiver.kt");
}
@TestMetadata("varargsOnParametersOfInlineClassType.kt") @TestMetadata("varargsOnParametersOfInlineClassType.kt")
public void testVarargsOnParametersOfInlineClassType() throws Exception { public void testVarargsOnParametersOfInlineClassType() throws Exception {
runTest("compiler/testData/diagnostics/tests/inlineClasses/varargsOnParametersOfInlineClassType.kt"); runTest("compiler/testData/diagnostics/tests/inlineClasses/varargsOnParametersOfInlineClassType.kt");
@@ -12959,6 +12959,11 @@ public class DiagnosticsUsingJavacTestGenerated extends AbstractDiagnosticsUsing
runTest("compiler/testData/diagnostics/tests/inlineClasses/unsignedLiteralsWithoutArtifactOnClasspath.kt"); runTest("compiler/testData/diagnostics/tests/inlineClasses/unsignedLiteralsWithoutArtifactOnClasspath.kt");
} }
@TestMetadata("varPropertyWithInlineClassReceiver.kt")
public void testVarPropertyWithInlineClassReceiver() throws Exception {
runTest("compiler/testData/diagnostics/tests/inlineClasses/varPropertyWithInlineClassReceiver.kt");
}
@TestMetadata("varargsOnParametersOfInlineClassType.kt") @TestMetadata("varargsOnParametersOfInlineClassType.kt")
public void testVarargsOnParametersOfInlineClassType() throws Exception { public void testVarargsOnParametersOfInlineClassType() throws Exception {
runTest("compiler/testData/diagnostics/tests/inlineClasses/varargsOnParametersOfInlineClassType.kt"); runTest("compiler/testData/diagnostics/tests/inlineClasses/varargsOnParametersOfInlineClassType.kt");