JS: fix val with backing field initialization in secondary constructors
This change reverts the AssignmentTranslator logic to a previous state of "if we assign to a val, tranlate to backing field". Previously a check whether or not we are inside of a constructor was added. The check didn't detect secondary constructors, hence initializing of val's with backing field started to work incorrectly. The check itself was added in an attempt to prevent augmented assignment operators to reference the backing field. The check seems to have been wrong, because an augmented assignment could happen inside a construcotr. A more correct fix was added later. It seems that it is safe now to revert the logic back and rely on the frontend to only allow assignment to a val property during initilization.
This commit is contained in:
@@ -0,0 +1,10 @@
|
||||
class A {
|
||||
val value: String
|
||||
get() = field + "K"
|
||||
|
||||
constructor(o: String) {
|
||||
value = o
|
||||
}
|
||||
}
|
||||
|
||||
fun box() = A("O").value
|
||||
+5
@@ -21347,6 +21347,11 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
|
||||
public void testWithoutPrimary() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/secondaryConstructors/withoutPrimary.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("withoutPrimarySimple.kt")
|
||||
public void testWithoutPrimarySimple() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/secondaryConstructors/withoutPrimarySimple.kt");
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("compiler/testData/codegen/box/signatureAnnotations")
|
||||
|
||||
+5
@@ -21347,6 +21347,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
|
||||
public void testWithoutPrimary() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/secondaryConstructors/withoutPrimary.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("withoutPrimarySimple.kt")
|
||||
public void testWithoutPrimarySimple() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/secondaryConstructors/withoutPrimarySimple.kt");
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("compiler/testData/codegen/box/signatureAnnotations")
|
||||
|
||||
+5
@@ -21352,6 +21352,11 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
|
||||
public void testWithoutPrimary() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/secondaryConstructors/withoutPrimary.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("withoutPrimarySimple.kt")
|
||||
public void testWithoutPrimarySimple() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/secondaryConstructors/withoutPrimarySimple.kt");
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("compiler/testData/codegen/box/signatureAnnotations")
|
||||
|
||||
+5
@@ -19282,6 +19282,11 @@ public class IrJsCodegenBoxTestGenerated extends AbstractIrJsCodegenBoxTest {
|
||||
public void testWithReturnUnit() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/secondaryConstructors/withReturnUnit.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("withoutPrimarySimple.kt")
|
||||
public void testWithoutPrimarySimple() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/secondaryConstructors/withoutPrimarySimple.kt");
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("compiler/testData/codegen/box/signatureAnnotations")
|
||||
|
||||
+5
@@ -20327,6 +20327,11 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest {
|
||||
public void testWithReturnUnit() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/secondaryConstructors/withReturnUnit.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("withoutPrimarySimple.kt")
|
||||
public void testWithoutPrimarySimple() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/secondaryConstructors/withoutPrimarySimple.kt");
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("compiler/testData/codegen/box/signatureAnnotations")
|
||||
|
||||
+9
-35
@@ -18,10 +18,7 @@ package org.jetbrains.kotlin.js.translate.operation;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.kotlin.descriptors.CallableDescriptor;
|
||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor;
|
||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor;
|
||||
import org.jetbrains.kotlin.descriptors.PropertyDescriptor;
|
||||
import org.jetbrains.kotlin.descriptors.*;
|
||||
import org.jetbrains.kotlin.js.backend.ast.JsExpression;
|
||||
import org.jetbrains.kotlin.js.translate.context.TranslationContext;
|
||||
import org.jetbrains.kotlin.js.translate.general.AbstractTranslator;
|
||||
@@ -70,7 +67,7 @@ public abstract class AssignmentTranslator extends AbstractTranslator {
|
||||
}
|
||||
|
||||
protected final AccessTranslator createAccessTranslator(@NotNull KtExpression left, boolean forceOrderOfEvaluation) {
|
||||
if (isReferenceToBackingFieldFromConstructor(left, context())) {
|
||||
if (isValProperty(left, context())) {
|
||||
KtSimpleNameExpression simpleName = getSimpleName(left);
|
||||
assert simpleName != null;
|
||||
return BackingFieldAccessTranslator.newInstance(simpleName, context());
|
||||
@@ -80,40 +77,17 @@ public abstract class AssignmentTranslator extends AbstractTranslator {
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean isReferenceToBackingFieldFromConstructor(
|
||||
private static boolean isValProperty(
|
||||
@NotNull KtExpression expression,
|
||||
@NotNull TranslationContext context
|
||||
) {
|
||||
if (expression instanceof KtSimpleNameExpression) {
|
||||
KtSimpleNameExpression nameExpression = (KtSimpleNameExpression) expression;
|
||||
DeclarationDescriptor descriptor = getDescriptorForReferenceExpression(context.bindingContext(), nameExpression);
|
||||
return isReferenceToBackingFieldFromConstructor(descriptor, context);
|
||||
}
|
||||
else if (expression instanceof KtDotQualifiedExpression) {
|
||||
KtDotQualifiedExpression qualifiedExpression = (KtDotQualifiedExpression) expression;
|
||||
if (qualifiedExpression.getReceiverExpression() instanceof KtThisExpression &&
|
||||
qualifiedExpression.getSelectorExpression() instanceof KtSimpleNameExpression
|
||||
) {
|
||||
KtSimpleNameExpression nameExpression = (KtSimpleNameExpression) qualifiedExpression.getSelectorExpression();
|
||||
DeclarationDescriptor descriptor = getDescriptorForReferenceExpression(context.bindingContext(), nameExpression);
|
||||
return isReferenceToBackingFieldFromConstructor(descriptor, context);
|
||||
}
|
||||
KtSimpleNameExpression simpleNameExpression = getSimpleName(expression);
|
||||
|
||||
if (simpleNameExpression != null) {
|
||||
DeclarationDescriptor descriptor = getDescriptorForReferenceExpression(context.bindingContext(), simpleNameExpression);
|
||||
return descriptor instanceof PropertyDescriptor && !((PropertyDescriptor) descriptor).isVar();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private static boolean isReferenceToBackingFieldFromConstructor(
|
||||
@Nullable DeclarationDescriptor descriptor,
|
||||
@NotNull TranslationContext context
|
||||
) {
|
||||
if (!(descriptor instanceof PropertyDescriptor)) return false;
|
||||
|
||||
PropertyDescriptor propertyDescriptor = (PropertyDescriptor) descriptor;
|
||||
if (!(context.getDeclarationDescriptor() instanceof ClassDescriptor)) return false;
|
||||
|
||||
ClassDescriptor classDescriptor = (ClassDescriptor) context.getDeclarationDescriptor();
|
||||
if (classDescriptor != propertyDescriptor.getContainingDeclaration()) return false;
|
||||
|
||||
return !propertyDescriptor.isVar();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user