[IR] Forbid MFVC primary constructors default arguments

Signed-off-by: Evgeniy.Zhelenskiy <Evgeniy.Zhelenskiy@jetbrains.com>

#KT-1179
This commit is contained in:
Evgeniy.Zhelenskiy
2022-10-20 18:36:41 +02:00
committed by Space Team
parent c6e54e6433
commit adee33d3e5
20 changed files with 111 additions and 44 deletions
@@ -1369,6 +1369,12 @@ internal val KT_DIAGNOSTIC_CONVERTER = KtDiagnosticConverterBuilder.buildConvert
token,
)
}
add(FirErrors.MULTI_FIELD_VALUE_CLASS_PRIMARY_CONSTRUCTOR_DEFAULT_PARAMETER) { firDiagnostic ->
MultiFieldValueClassPrimaryConstructorDefaultParameterImpl(
firDiagnostic as KtPsiDiagnostic,
token,
)
}
add(FirErrors.SECONDARY_CONSTRUCTOR_WITH_BODY_INSIDE_VALUE_CLASS) { firDiagnostic ->
SecondaryConstructorWithBodyInsideValueClassImpl(
firDiagnostic as KtPsiDiagnostic,
@@ -987,6 +987,10 @@ sealed class KtFirDiagnostic<PSI : PsiElement> : KtDiagnosticWithPsi<PSI> {
override val diagnosticClass get() = ValueClassCannotBeRecursive::class
}
abstract class MultiFieldValueClassPrimaryConstructorDefaultParameter : KtFirDiagnostic<KtExpression>() {
override val diagnosticClass get() = MultiFieldValueClassPrimaryConstructorDefaultParameter::class
}
abstract class SecondaryConstructorWithBodyInsideValueClass : KtFirDiagnostic<PsiElement>() {
override val diagnosticClass get() = SecondaryConstructorWithBodyInsideValueClass::class
}
@@ -1183,6 +1183,11 @@ internal class ValueClassCannotBeRecursiveImpl(
override val token: KtLifetimeToken,
) : KtFirDiagnostic.ValueClassCannotBeRecursive(), KtAbstractFirDiagnostic<KtTypeReference>
internal class MultiFieldValueClassPrimaryConstructorDefaultParameterImpl(
override val firDiagnostic: KtPsiDiagnostic,
override val token: KtLifetimeToken,
) : KtFirDiagnostic.MultiFieldValueClassPrimaryConstructorDefaultParameter(), KtAbstractFirDiagnostic<KtExpression>
internal class SecondaryConstructorWithBodyInsideValueClassImpl(
override val firDiagnostic: KtPsiDiagnostic,
override val token: KtLifetimeToken,
@@ -33630,6 +33630,12 @@ public class DiagnosisCompilerTestFE10TestdataTestGenerated extends AbstractDiag
runTest("compiler/testData/diagnostics/tests/valueClasses/constructorsJvmSignaturesClash.kt");
}
@Test
@TestMetadata("defaultParameters.kt")
public void testDefaultParameters() throws Exception {
runTest("compiler/testData/diagnostics/tests/valueClasses/defaultParameters.kt", TransformersFunctions.getReplaceOptionalJvmInlineAnnotationWithUniversal());
}
@Test
@TestMetadata("delegatedPropertyInValueClass.kt")
public void testDelegatedPropertyInValueClass() throws Exception {
@@ -33726,6 +33726,12 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirDiagnosti
runTest("compiler/testData/diagnostics/tests/valueClasses/constructorsJvmSignaturesClash.kt");
}
@Test
@TestMetadata("defaultParameters.kt")
public void testDefaultParameters() throws Exception {
runTest("compiler/testData/diagnostics/tests/valueClasses/defaultParameters.kt", TransformersFunctions.getReplaceOptionalJvmInlineAnnotationWithUniversal());
}
@Test
@TestMetadata("delegatedPropertyInValueClass.kt")
public void testDelegatedPropertyInValueClass() throws Exception {
@@ -33630,6 +33630,12 @@ public class FirOldFrontendDiagnosticsWithLightTreeTestGenerated extends Abstrac
runTest("compiler/testData/diagnostics/tests/valueClasses/constructorsJvmSignaturesClash.kt");
}
@Test
@TestMetadata("defaultParameters.kt")
public void testDefaultParameters() throws Exception {
runTest("compiler/testData/diagnostics/tests/valueClasses/defaultParameters.kt", TransformersFunctions.getReplaceOptionalJvmInlineAnnotationWithUniversal());
}
@Test
@TestMetadata("delegatedPropertyInValueClass.kt")
public void testDelegatedPropertyInValueClass() throws Exception {
@@ -426,6 +426,7 @@ object DIAGNOSTICS_LIST : DiagnosticList("FirErrors") {
val VALUE_CLASS_CANNOT_IMPLEMENT_INTERFACE_BY_DELEGATION by error<PsiElement>()
val VALUE_CLASS_CANNOT_EXTEND_CLASSES by error<KtTypeReference>()
val VALUE_CLASS_CANNOT_BE_RECURSIVE by error<KtTypeReference>()
val MULTI_FIELD_VALUE_CLASS_PRIMARY_CONSTRUCTOR_DEFAULT_PARAMETER by error<KtExpression>()
val SECONDARY_CONSTRUCTOR_WITH_BODY_INSIDE_VALUE_CLASS by error<PsiElement>()
val RESERVED_MEMBER_INSIDE_VALUE_CLASS by error<KtFunction>(PositioningStrategy.DECLARATION_NAME) {
parameter<String>("name")
@@ -321,6 +321,7 @@ object FirErrors {
val VALUE_CLASS_CANNOT_IMPLEMENT_INTERFACE_BY_DELEGATION by error0<PsiElement>()
val VALUE_CLASS_CANNOT_EXTEND_CLASSES by error0<KtTypeReference>()
val VALUE_CLASS_CANNOT_BE_RECURSIVE by error0<KtTypeReference>()
val MULTI_FIELD_VALUE_CLASS_PRIMARY_CONSTRUCTOR_DEFAULT_PARAMETER by error0<KtExpression>()
val SECONDARY_CONSTRUCTOR_WITH_BODY_INSIDE_VALUE_CLASS by error0<PsiElement>()
val RESERVED_MEMBER_INSIDE_VALUE_CLASS by error1<KtFunction, String>(SourceElementPositioningStrategies.DECLARATION_NAME)
val TYPE_ARGUMENT_ON_TYPED_VALUE_CLASS_EQUALS by error0<KtTypeReference>()
@@ -109,7 +109,7 @@ object CommonDeclarationCheckers : DeclarationCheckers() {
FirPrimaryConstructorSuperTypeChecker,
FirFunInterfaceDeclarationChecker,
FirNestedClassChecker,
FirInlineClassDeclarationChecker,
FirValueClassDeclarationChecker,
FirOuterClassArgumentsRequiredChecker,
FirPropertyInitializationChecker,
)
@@ -32,7 +32,7 @@ import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.name.StandardClassIds
object FirInlineClassDeclarationChecker : FirRegularClassChecker() {
object FirValueClassDeclarationChecker : FirRegularClassChecker() {
private val boxAndUnboxNames = setOf("box", "unbox")
private val equalsAndHashCodeNames = setOf("equals", "hashCode")
@@ -203,6 +203,15 @@ object FirInlineClassDeclarationChecker : FirRegularClassChecker() {
context
)
}
declaration.multiFieldValueClassRepresentation != null && primaryConstructorParameter.defaultValue != null -> {
// todo fix when inline arguments are supported
reporter.reportOn(
primaryConstructorParameter.defaultValue!!.source,
FirErrors.MULTI_FIELD_VALUE_CLASS_PRIMARY_CONSTRUCTOR_DEFAULT_PARAMETER,
context
)
}
}
}
@@ -309,6 +309,7 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.MODIFIER_FORM_FOR
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.MODIFIER_FORM_FOR_NON_BUILT_IN_SUSPEND_FUN
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.MULTIPLE_ARGUMENTS_APPLICABLE_FOR_CONTEXT_RECEIVER
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.MULTIPLE_VARARG_PARAMETERS
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.MULTI_FIELD_VALUE_CLASS_PRIMARY_CONSTRUCTOR_DEFAULT_PARAMETER
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.MUST_BE_INITIALIZED
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.MUST_BE_INITIALIZED_OR_BE_ABSTRACT
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NAMED_ARGUMENTS_NOT_ALLOWED
@@ -1271,6 +1272,10 @@ object FirErrorsDefaultMessages : BaseDiagnosticRendererFactory() {
map.put(VALUE_CLASS_CANNOT_IMPLEMENT_INTERFACE_BY_DELEGATION, "Value class cannot implement an interface by delegation")
map.put(VALUE_CLASS_CANNOT_EXTEND_CLASSES, "Value class cannot extend classes")
map.put(VALUE_CLASS_CANNOT_BE_RECURSIVE, "Value class cannot be recursive")
map.put(
MULTI_FIELD_VALUE_CLASS_PRIMARY_CONSTRUCTOR_DEFAULT_PARAMETER,
"Default parameters are not supported in the primary constructor of a multi-field value class"
)
map.put(
INVALID_DEFAULT_FUNCTIONAL_PARAMETER_FOR_INLINE,
"Invalid default value for inline parameter: ''{0}''. Only lambdas, anonymous functions, and callable references are supported",
@@ -420,6 +420,7 @@ public interface Errors {
DiagnosticFactory0<PsiElement> VALUE_CLASS_CANNOT_IMPLEMENT_INTERFACE_BY_DELEGATION = DiagnosticFactory0.create(ERROR);
DiagnosticFactory0<KtTypeReference> VALUE_CLASS_CANNOT_EXTEND_CLASSES = DiagnosticFactory0.create(ERROR);
DiagnosticFactory0<KtTypeReference> VALUE_CLASS_CANNOT_BE_RECURSIVE = DiagnosticFactory0.create(ERROR);
DiagnosticFactory0<KtExpression> MULTI_FIELD_VALUE_CLASS_PRIMARY_CONSTRUCTOR_DEFAULT_PARAMETER = DiagnosticFactory0.create(ERROR);
DiagnosticFactory0<PsiElement> SECONDARY_CONSTRUCTOR_WITH_BODY_INSIDE_VALUE_CLASS = DiagnosticFactory0.create(ERROR);
DiagnosticFactory1<PsiElement, String> RESERVED_MEMBER_INSIDE_VALUE_CLASS = DiagnosticFactory1.create(ERROR);
DiagnosticFactory0<KtTypeReference> TYPE_ARGUMENT_ON_TYPED_VALUE_CLASS_EQUALS = DiagnosticFactory0.create(ERROR);
@@ -795,6 +795,7 @@ public class DefaultErrorMessages {
MAP.put(VALUE_CLASS_CANNOT_IMPLEMENT_INTERFACE_BY_DELEGATION, "Value class cannot implement an interface by delegation if expression is not a parameter");
MAP.put(VALUE_CLASS_CANNOT_EXTEND_CLASSES, "Value class cannot extend classes");
MAP.put(VALUE_CLASS_CANNOT_BE_RECURSIVE, "Value class cannot be recursive");
MAP.put(MULTI_FIELD_VALUE_CLASS_PRIMARY_CONSTRUCTOR_DEFAULT_PARAMETER, "Default parameters are not supported in the primary constructor of a multi-field value class");
MAP.put(SECONDARY_CONSTRUCTOR_WITH_BODY_INSIDE_VALUE_CLASS, "Secondary constructors with bodies are reserved for for future releases");
MAP.put(RESERVED_MEMBER_INSIDE_VALUE_CLASS, "Member with the name ''{0}'' is reserved for future releases", STRING);
MAP.put(TYPE_ARGUMENT_ON_TYPED_VALUE_CLASS_EQUALS, "Type arguments for typed value class equals must be only star projections");
@@ -26,11 +26,11 @@ private val DEFAULT_DECLARATION_CHECKERS = listOf(
DelegationChecker(),
KClassWithIncorrectTypeArgumentChecker,
SuspendLimitationsChecker,
InlineClassDeclarationChecker,
PropertiesWithBackingFieldsInsideInlineClass(),
InnerClassInsideInlineClass(),
ValueClassDeclarationChecker,
PropertiesWithBackingFieldsInsideValueClass(),
InnerClassInsideValueClass(),
AnnotationClassTargetAndRetentionChecker(),
ReservedMembersAndConstructsForInlineClass(),
ReservedMembersAndConstructsForValueClass(),
ResultClassInReturnTypeChecker(),
LocalVariableTypeParametersChecker(),
ExplicitApiDeclarationChecker(),
@@ -127,6 +127,11 @@ object ValueClassDeclarationChecker : DeclarationChecker {
baseParametersOk = false
continue
}
if (descriptor.isMultiFieldValueClass() && baseParameter.defaultValue != null) {
// todo fix when inline arguments are supported
trace.report(Errors.MULTI_FIELD_VALUE_CLASS_PRIMARY_CONSTRUCTOR_DEFAULT_PARAMETER.on(baseParameter.defaultValue!!))
}
}
}
if (!baseParametersOk) {
@@ -203,7 +208,7 @@ object ValueClassDeclarationChecker : DeclarationChecker {
}
}
class PropertiesWithBackingFieldsInsideInlineClass : DeclarationChecker {
class PropertiesWithBackingFieldsInsideValueClass : DeclarationChecker {
override fun check(declaration: KtDeclaration, descriptor: DeclarationDescriptor, context: DeclarationCheckerContext) {
if (declaration !is KtProperty) return
if (descriptor !is PropertyDescriptor) return
@@ -220,7 +225,7 @@ class PropertiesWithBackingFieldsInsideInlineClass : DeclarationChecker {
}
}
class InnerClassInsideInlineClass : DeclarationChecker {
class InnerClassInsideValueClass : DeclarationChecker {
override fun check(declaration: KtDeclaration, descriptor: DeclarationDescriptor, context: DeclarationCheckerContext) {
if (declaration !is KtClass) return
if (descriptor !is ClassDescriptor) return
@@ -232,7 +237,7 @@ class InnerClassInsideInlineClass : DeclarationChecker {
}
}
class ReservedMembersAndConstructsForInlineClass : DeclarationChecker {
class ReservedMembersAndConstructsForValueClass : DeclarationChecker {
companion object {
private val boxAndUnboxNames = setOf("box", "unbox")
+1 -1
View File
@@ -19,7 +19,7 @@ value class B(val x: UInt) {
}
@JvmInline
value class C(val x: Int, val y: B, val z: String = "3")
value class C(val x: Int, val y: B, val z: String)
@JvmInline
value class D(val x: C) {
@@ -2,8 +2,8 @@
@kotlin.Metadata
public final class DPoint {
// source: 'defaultParameters.kt'
private final field x: double
private final field y: double
private final field field-0: double
private final field field-1: double
private synthetic method <init>(p0: double, p1: double): void
public synthetic final static method box-impl(p0: double, p1: double): DPoint
public final static method constructor-impl(p0: double, p1: double): void
@@ -12,25 +12,23 @@ public final class DPoint {
public final static method equals-sUp7gFk(p0: double, p1: double, p2: double, p3: double): boolean
public synthetic static method f1-lIoT8es$default(p0: double, p1: double, p2: int, p3: int, p4: double, p5: double, p6: int, p7: java.lang.Object): java.util.List
public final static @org.jetbrains.annotations.NotNull method f1-lIoT8es(p0: double, p1: double, p2: int, p3: int, p4: double, p5: double): java.util.List
public final method getX(): double
public final method getY(): double
public method hashCode(): int
public static method hashCode-impl(p0: double, p1: double): int
public @org.jetbrains.annotations.NotNull method toString(): java.lang.String
public static method toString-impl(p0: double, p1: double): java.lang.String
public synthetic final method unbox-impl-x(): double
public synthetic final method unbox-impl-y(): double
public synthetic final method unbox-impl-0(): double
public synthetic final method unbox-impl-1(): double
}
@kotlin.jvm.JvmInline
@kotlin.Metadata
public final class DSegment {
// source: 'defaultParameters.kt'
private final field n: int
private final field p1-x: double
private final field p1-y: double
private final field p2-x: double
private final field p2-y: double
private final field field-0-0: double
private final field field-0-1: double
private final field field-1-0: double
private final field field-1-1: double
private final field field-2: int
private synthetic method <init>(p0: double, p1: double, p2: double, p3: double, p4: int): void
public synthetic final static method box-impl(p0: double, p1: double, p2: double, p3: double, p4: int): DSegment
public final static method constructor-impl(p0: double, p1: double, p2: double, p3: double, p4: int): void
@@ -39,20 +37,17 @@ public final class DSegment {
public final static method equals-sUp7gFk(p0: double, p1: double, p2: double, p3: double, p4: int, p5: double, p6: double, p7: double, p8: double, p9: int): boolean
public synthetic static method f2-lIoT8es$default(p0: double, p1: double, p2: double, p3: double, p4: int, p5: int, p6: int, p7: double, p8: double, p9: int, p10: java.lang.Object): java.util.List
public final static @org.jetbrains.annotations.NotNull method f2-lIoT8es(p0: double, p1: double, p2: double, p3: double, p4: int, p5: int, p6: int, p7: double, p8: double): java.util.List
public final method getN(): int
public final @org.jetbrains.annotations.NotNull method getP1(): DPoint
public final @org.jetbrains.annotations.NotNull method getP2(): DPoint
public method hashCode(): int
public static method hashCode-impl(p0: double, p1: double, p2: double, p3: double, p4: int): int
public @org.jetbrains.annotations.NotNull method toString(): java.lang.String
public static method toString-impl(p0: double, p1: double, p2: double, p3: double, p4: int): java.lang.String
public synthetic final method unbox-impl-n(): int
public synthetic final method unbox-impl-p1(): DPoint
public synthetic final method unbox-impl-p1-x(): double
public synthetic final method unbox-impl-p1-y(): double
public synthetic final method unbox-impl-p2(): DPoint
public synthetic final method unbox-impl-p2-x(): double
public synthetic final method unbox-impl-p2-y(): double
public synthetic final method unbox-impl-0(): DPoint
public synthetic final method unbox-impl-0-0(): double
public synthetic final method unbox-impl-0-1(): double
public synthetic final method unbox-impl-1(): DPoint
public synthetic final method unbox-impl-1-0(): double
public synthetic final method unbox-impl-1-1(): double
public synthetic final method unbox-impl-2(): int
}
@kotlin.Metadata
@@ -70,11 +65,11 @@ public final class DefaultParametersKt {
public final class Wrapper {
// source: 'defaultParameters.kt'
private final field n: int
private final field segment-n: int
private final field segment-p1-x: double
private final field segment-p1-y: double
private final field segment-p2-x: double
private final field segment-p2-y: double
private final field segment-0-0: double
private final field segment-0-1: double
private final field segment-1-0: double
private final field segment-1-1: double
private final field segment-2: int
public method <init>(): void
public method <init>(p0: double, p1: double, p2: double, p3: double, p4: int, p5: int): void
public synthetic method <init>(p0: double, p1: double, p2: double, p3: double, p4: int, p5: int, p6: int, p7: kotlin.jvm.internal.DefaultConstructorMarker): void
@@ -87,13 +82,13 @@ public final class Wrapper {
public final @org.jetbrains.annotations.NotNull method f3-lIoT8es(p0: int, p1: int, p2: double, p3: double): java.util.List
public final method getN(): int
public final @org.jetbrains.annotations.NotNull method getSegment(): DSegment
public synthetic final method getSegment-n(): int
public synthetic final method getSegment-p1(): DPoint
public synthetic final method getSegment-p1-x(): double
public synthetic final method getSegment-p1-y(): double
public synthetic final method getSegment-p2(): DPoint
public synthetic final method getSegment-p2-x(): double
public synthetic final method getSegment-p2-y(): double
public synthetic final method getSegment-0(): DPoint
public synthetic final method getSegment-0-0(): double
public synthetic final method getSegment-0-1(): double
public synthetic final method getSegment-1(): DPoint
public synthetic final method getSegment-1-0(): double
public synthetic final method getSegment-1-1(): double
public synthetic final method getSegment-2(): int
public method hashCode(): int
public @org.jetbrains.annotations.NotNull method toString(): java.lang.String
}
@@ -12,7 +12,7 @@ value class A<T : Any>(val x: List<T>)
value class B(val x: UInt)
@JvmInline
value class C(val x: Int, val y: B, val z: String = "3")
value class C(val x: Int, val y: B, val z: String)
@JvmInline
value class D(val x: C) {
@@ -0,0 +1,10 @@
// !LANGUAGE: +ValueClasses
// WITH_STDLIB
// SKIP_TXT
// WORKS_WHEN_VALUE_CLASS
// FIR_IDENTICAL
@JvmInline
value class DPoint(val x: Double, val y: Double = <!MULTI_FIELD_VALUE_CLASS_PRIMARY_CONSTRUCTOR_DEFAULT_PARAMETER!>Double.NaN<!>) {
fun f(otherDPoint: DPoint = DPoint(1.0, 2.0)) = Unit
}
@@ -33726,6 +33726,12 @@ public class DiagnosticTestGenerated extends AbstractDiagnosticTest {
runTest("compiler/testData/diagnostics/tests/valueClasses/constructorsJvmSignaturesClash.kt");
}
@Test
@TestMetadata("defaultParameters.kt")
public void testDefaultParameters() throws Exception {
runTest("compiler/testData/diagnostics/tests/valueClasses/defaultParameters.kt", TransformersFunctions.getReplaceOptionalJvmInlineAnnotationWithUniversal());
}
@Test
@TestMetadata("delegatedPropertyInValueClass.kt")
public void testDelegatedPropertyInValueClass() throws Exception {