Fix some Unit materialization bugs
This commit is contained in:
+2
-2
@@ -280,13 +280,13 @@ public final class PatternTranslator extends AbstractTranslator {
|
|||||||
EqualityType matchEquality = equalityType(subjectType);
|
EqualityType matchEquality = equalityType(subjectType);
|
||||||
EqualityType patternEquality = equalityType(patternType);
|
EqualityType patternEquality = equalityType(patternType);
|
||||||
|
|
||||||
JsExpression expressionToMatchAgainst = translateExpressionForExpressionPattern(patternExpression);
|
JsExpression expressionToMatchAgainst = TranslationUtils.coerce(context(), translateExpressionForExpressionPattern(patternExpression), subjectType);
|
||||||
|
|
||||||
if (matchEquality == EqualityType.PRIMITIVE && patternEquality == EqualityType.PRIMITIVE) {
|
if (matchEquality == EqualityType.PRIMITIVE && patternEquality == EqualityType.PRIMITIVE) {
|
||||||
return equality(expressionToMatch, expressionToMatchAgainst);
|
return equality(expressionToMatch, expressionToMatchAgainst);
|
||||||
}
|
}
|
||||||
else if (expressionToMatchAgainst instanceof JsNullLiteral) {
|
else if (expressionToMatchAgainst instanceof JsNullLiteral) {
|
||||||
return TranslationUtils.nullCheck(expressionToMatch, false);
|
return TranslationUtils.nullCheck(subjectExpression, expressionToMatch, context(), false);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return TopLevelFIF.KOTLIN_EQUALS.apply(expressionToMatch, Collections.singletonList(expressionToMatchAgainst), context());
|
return TopLevelFIF.KOTLIN_EQUALS.apply(expressionToMatch, Collections.singletonList(expressionToMatchAgainst), context());
|
||||||
|
|||||||
+2
-4
@@ -27,6 +27,7 @@ import org.jetbrains.kotlin.js.translate.context.TranslationContext
|
|||||||
import org.jetbrains.kotlin.js.translate.intrinsic.functions.factories.TopLevelFIF
|
import org.jetbrains.kotlin.js.translate.intrinsic.functions.factories.TopLevelFIF
|
||||||
import org.jetbrains.kotlin.js.translate.utils.JsAstUtils
|
import org.jetbrains.kotlin.js.translate.utils.JsAstUtils
|
||||||
import org.jetbrains.kotlin.js.translate.utils.PsiUtils.getOperationToken
|
import org.jetbrains.kotlin.js.translate.utils.PsiUtils.getOperationToken
|
||||||
|
import org.jetbrains.kotlin.js.translate.utils.PsiUtils.isNegatedOperation
|
||||||
import org.jetbrains.kotlin.js.translate.utils.TranslationUtils
|
import org.jetbrains.kotlin.js.translate.utils.TranslationUtils
|
||||||
import org.jetbrains.kotlin.lexer.KtTokens
|
import org.jetbrains.kotlin.lexer.KtTokens
|
||||||
import org.jetbrains.kotlin.psi.KtBinaryExpression
|
import org.jetbrains.kotlin.psi.KtBinaryExpression
|
||||||
@@ -36,7 +37,6 @@ import org.jetbrains.kotlin.types.KotlinType
|
|||||||
import org.jetbrains.kotlin.types.TypeUtils
|
import org.jetbrains.kotlin.types.TypeUtils
|
||||||
import org.jetbrains.kotlin.types.expressions.OperatorConventions
|
import org.jetbrains.kotlin.types.expressions.OperatorConventions
|
||||||
import org.jetbrains.kotlin.types.isDynamic
|
import org.jetbrains.kotlin.types.isDynamic
|
||||||
import org.jetbrains.kotlin.types.typeUtil.makeNullable
|
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
object EqualsBOIF : BinaryOperationIntrinsicFactory {
|
object EqualsBOIF : BinaryOperationIntrinsicFactory {
|
||||||
@@ -49,9 +49,7 @@ object EqualsBOIF : BinaryOperationIntrinsicFactory {
|
|||||||
val anyType = context.currentModule.builtIns.anyType
|
val anyType = context.currentModule.builtIns.anyType
|
||||||
if (right is JsNullLiteral || left is JsNullLiteral) {
|
if (right is JsNullLiteral || left is JsNullLiteral) {
|
||||||
val (subject, ktSubject) = if (right is JsNullLiteral) Pair(left, expression.left!!) else Pair(right, expression.right!!)
|
val (subject, ktSubject) = if (right is JsNullLiteral) Pair(left, expression.left!!) else Pair(right, expression.right!!)
|
||||||
val type = context.bindingContext().getType(ktSubject) ?: anyType
|
return TranslationUtils.nullCheck(ktSubject, subject, context, isNegatedOperation(expression))
|
||||||
val coercedSubject = TranslationUtils.coerce(context, subject, type.makeNullable())
|
|
||||||
return TranslationUtils.nullCheck(coercedSubject, isNegated)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
val (leftKotlinType, rightKotlinType) = binaryOperationTypes(expression, context)
|
val (leftKotlinType, rightKotlinType) = binaryOperationTypes(expression, context)
|
||||||
|
|||||||
+2
@@ -35,6 +35,7 @@ import org.jetbrains.kotlin.types.expressions.OperatorConventions;
|
|||||||
|
|
||||||
import static org.jetbrains.kotlin.js.translate.utils.PsiUtils.getOperationToken;
|
import static org.jetbrains.kotlin.js.translate.utils.PsiUtils.getOperationToken;
|
||||||
import static org.jetbrains.kotlin.js.translate.utils.PsiUtils.isAssignment;
|
import static org.jetbrains.kotlin.js.translate.utils.PsiUtils.isAssignment;
|
||||||
|
import static org.jetbrains.kotlin.js.translate.utils.TranslationUtils.coerce;
|
||||||
import static org.jetbrains.kotlin.js.translate.utils.TranslationUtils.isSimpleNameExpressionNotDelegatedLocalVar;
|
import static org.jetbrains.kotlin.js.translate.utils.TranslationUtils.isSimpleNameExpressionNotDelegatedLocalVar;
|
||||||
|
|
||||||
public final class IntrinsicAssignmentTranslator extends AssignmentTranslator {
|
public final class IntrinsicAssignmentTranslator extends AssignmentTranslator {
|
||||||
@@ -62,6 +63,7 @@ public final class IntrinsicAssignmentTranslator extends AssignmentTranslator {
|
|||||||
JsExpression result = TranslationUtils.translateRightExpression(context, expression, rightBlock);
|
JsExpression result = TranslationUtils.translateRightExpression(context, expression, rightBlock);
|
||||||
KotlinType leftType = context.bindingContext().getType(expression.getLeft());
|
KotlinType leftType = context.bindingContext().getType(expression.getLeft());
|
||||||
KotlinType rightType = context.bindingContext().getType(expression.getRight());
|
KotlinType rightType = context.bindingContext().getType(expression.getRight());
|
||||||
|
|
||||||
if (rightType != null && KotlinBuiltIns.isCharOrNullableChar(rightType)) {
|
if (rightType != null && KotlinBuiltIns.isCharOrNullableChar(rightType)) {
|
||||||
if (leftType != null && KotlinBuiltIns.isStringOrNullableString(leftType)) {
|
if (leftType != null && KotlinBuiltIns.isStringOrNullableString(leftType)) {
|
||||||
result = JsAstUtils.charToString(result);
|
result = JsAstUtils.charToString(result);
|
||||||
|
|||||||
+1
-1
@@ -54,7 +54,7 @@ public final class UnaryOperationTranslator {
|
|||||||
if (operationToken == KtTokens.EXCLEXCL) {
|
if (operationToken == KtTokens.EXCLEXCL) {
|
||||||
KtExpression baseExpression = getBaseExpression(expression);
|
KtExpression baseExpression = getBaseExpression(expression);
|
||||||
JsExpression translatedExpression = translateAsExpression(baseExpression, context);
|
JsExpression translatedExpression = translateAsExpression(baseExpression, context);
|
||||||
return sure(translatedExpression, context);
|
return sure(baseExpression, translatedExpression, context);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (operationToken == KtTokens.MINUS) {
|
if (operationToken == KtTokens.MINUS) {
|
||||||
|
|||||||
@@ -50,6 +50,7 @@ import org.jetbrains.kotlin.resolve.inline.InlineUtil;
|
|||||||
import org.jetbrains.kotlin.resolve.source.KotlinSourceElementKt;
|
import org.jetbrains.kotlin.resolve.source.KotlinSourceElementKt;
|
||||||
import org.jetbrains.kotlin.types.DynamicTypesKt;
|
import org.jetbrains.kotlin.types.DynamicTypesKt;
|
||||||
import org.jetbrains.kotlin.types.KotlinType;
|
import org.jetbrains.kotlin.types.KotlinType;
|
||||||
|
import org.jetbrains.kotlin.types.TypeUtils;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
@@ -157,6 +158,30 @@ public final class TranslationUtils {
|
|||||||
return new JsBinaryOperation(operator, expressionToCheck, new JsNullLiteral());
|
return new JsBinaryOperation(operator, expressionToCheck, new JsNullLiteral());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
private static JsExpression prepareForNullCheck(
|
||||||
|
@NotNull KtExpression ktSubject,
|
||||||
|
@NotNull JsExpression expression,
|
||||||
|
@NotNull TranslationContext context
|
||||||
|
) {
|
||||||
|
KotlinType type = context.bindingContext().getType(ktSubject);
|
||||||
|
if (type == null) {
|
||||||
|
type = context.getCurrentModule().getBuiltIns().getAnyType();
|
||||||
|
}
|
||||||
|
|
||||||
|
return coerce(context, expression, TypeUtils.makeNullable(type));
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
public static JsBinaryOperation nullCheck(
|
||||||
|
@NotNull KtExpression ktSubject,
|
||||||
|
@NotNull JsExpression expressionToCheck,
|
||||||
|
@NotNull TranslationContext context,
|
||||||
|
boolean isNegated
|
||||||
|
) {
|
||||||
|
return nullCheck(prepareForNullCheck(ktSubject, expressionToCheck, context), isNegated);
|
||||||
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
public static JsConditional notNullConditional(
|
public static JsConditional notNullConditional(
|
||||||
@NotNull JsExpression expression,
|
@NotNull JsExpression expression,
|
||||||
@@ -310,8 +335,9 @@ public final class TranslationUtils {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
public static JsExpression sure(@NotNull JsExpression expression, @NotNull TranslationContext context) {
|
public static JsExpression sure(@NotNull KtExpression ktExpression, @NotNull JsExpression expression, @NotNull TranslationContext context) {
|
||||||
return new JsInvocation(context.getReferenceToIntrinsic(Namer.NULL_CHECK_INTRINSIC_NAME), expression);
|
return new JsInvocation(context.getReferenceToIntrinsic(Namer.NULL_CHECK_INTRINSIC_NAME),
|
||||||
|
prepareForNullCheck(ktExpression, expression, context));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean isSimpleNameExpressionNotDelegatedLocalVar(@Nullable KtExpression expression, @NotNull TranslationContext context) {
|
public static boolean isSimpleNameExpressionNotDelegatedLocalVar(@Nullable KtExpression expression, @NotNull TranslationContext context) {
|
||||||
@@ -491,9 +517,7 @@ public final class TranslationUtils {
|
|||||||
}
|
}
|
||||||
else if (KotlinBuiltIns.isUnit(from)) {
|
else if (KotlinBuiltIns.isUnit(from)) {
|
||||||
if (!KotlinBuiltIns.isUnit(to) && !MetadataProperties.isUnit(value)) {
|
if (!KotlinBuiltIns.isUnit(to) && !MetadataProperties.isUnit(value)) {
|
||||||
ClassDescriptor unit = context.getCurrentModule().getBuiltIns().getUnit();
|
value = voidToUnit(context, value);
|
||||||
JsExpression unitRef = ReferenceTranslator.translateAsValueReference(unit, context);
|
|
||||||
value = JsAstUtils.newSequence(Arrays.asList(value, unitRef));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -501,6 +525,13 @@ public final class TranslationUtils {
|
|||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
public static JsExpression voidToUnit(@NotNull TranslationContext context, @NotNull JsExpression expression) {
|
||||||
|
ClassDescriptor unit = context.getCurrentModule().getBuiltIns().getUnit();
|
||||||
|
JsExpression unitRef = ReferenceTranslator.translateAsValueReference(unit, context);
|
||||||
|
return JsAstUtils.newSequence(Arrays.asList(expression, unitRef));
|
||||||
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
private static JsExpression unitToVoid(@NotNull JsExpression expression) {
|
private static JsExpression unitToVoid(@NotNull JsExpression expression) {
|
||||||
if (expression instanceof JsBinaryOperation) {
|
if (expression instanceof JsBinaryOperation) {
|
||||||
|
|||||||
+20
-12
@@ -1,18 +1,26 @@
|
|||||||
// EXPECTED_REACHABLE_NODES: 1132
|
// EXPECTED_REACHABLE_NODES: 1132
|
||||||
var log = ""
|
var log = ""
|
||||||
|
|
||||||
fun box(): String {
|
fun log(msg: String) {
|
||||||
foo() ?: bar()
|
log += "$msg;"
|
||||||
if (foo() == null) bar()
|
}
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
log("!!")!!
|
||||||
|
|
||||||
|
log("elvis-left") ?: log("elvis-right")
|
||||||
|
|
||||||
|
if (log("if") == null) log("then")
|
||||||
|
|
||||||
|
when (null) {
|
||||||
|
log("when-pattern") -> log("when-body-1")
|
||||||
|
}
|
||||||
|
|
||||||
|
when (log("when-subject")) {
|
||||||
|
null -> log("when-body-2")
|
||||||
|
}
|
||||||
|
|
||||||
|
if (log != "!!;elvis-left;if;when-pattern;when-subject;") return "fail: $log"
|
||||||
|
|
||||||
if (log != "foo;foo;") return "fail: $log"
|
|
||||||
return "OK"
|
return "OK"
|
||||||
}
|
}
|
||||||
|
|
||||||
fun foo() {
|
|
||||||
log += "foo;"
|
|
||||||
}
|
|
||||||
|
|
||||||
fun bar() {
|
|
||||||
log += "bar;"
|
|
||||||
}
|
|
||||||
|
|||||||
Reference in New Issue
Block a user