[JS BE] Support val in when subject
#KT-25014 Fixed
This commit is contained in:
-1
@@ -1,5 +1,4 @@
|
||||
// !LANGUAGE: +VariableDeclarationInWhenSubject
|
||||
// IGNORE_BACKEND: JS
|
||||
|
||||
fun box(): String {
|
||||
var y: String = "OK"
|
||||
|
||||
Vendored
+1
-1
@@ -1,6 +1,6 @@
|
||||
// !LANGUAGE: +VariableDeclarationInWhenSubject
|
||||
// WITH_RUNTIME
|
||||
// IGNORE_BACKEND: JS, JS_IR
|
||||
// IGNORE_BACKEND: JS_IR
|
||||
|
||||
fun dense(x: Int): Int {
|
||||
return when (val xx = x) {
|
||||
|
||||
-1
@@ -1,5 +1,4 @@
|
||||
// !LANGUAGE: +VariableDeclarationInWhenSubject
|
||||
// IGNORE_BACKEND: JS
|
||||
|
||||
val x = 1
|
||||
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
// !LANGUAGE: +VariableDeclarationInWhenSubject
|
||||
// IGNORE_BACKEND: JS
|
||||
|
||||
val dz = -0.0
|
||||
val fz = -0.0f
|
||||
@@ -29,5 +28,14 @@ fun box(): String {
|
||||
}
|
||||
}
|
||||
|
||||
testDoubleAsUpperBound(-0.0)
|
||||
|
||||
return "OK"
|
||||
}
|
||||
}
|
||||
|
||||
fun <T: Double> testDoubleAsUpperBound(v: T): Boolean {
|
||||
return when (val a = v*v) {
|
||||
0.0 -> true
|
||||
else -> throw AssertionError()
|
||||
}
|
||||
}
|
||||
|
||||
+15
-5
@@ -1,22 +1,32 @@
|
||||
// !LANGUAGE: +VariableDeclarationInWhenSubject +ProperIeee754Comparisons
|
||||
// IGNORE_BACKEND: JVM_IR
|
||||
// IGNORE_BACKEND: JS, JS_IR
|
||||
// IGNORE_BACKEND: JS_IR
|
||||
|
||||
val az: Any = -0.0
|
||||
val afz: Any = -0.0f
|
||||
|
||||
fun box(): String {
|
||||
when (val y = az) {
|
||||
val y = az
|
||||
when (y) {
|
||||
!is Double -> throw AssertionError()
|
||||
0.0 -> {}
|
||||
else -> throw AssertionError()
|
||||
}
|
||||
|
||||
when (val y = afz) {
|
||||
val yy = afz
|
||||
when (yy) {
|
||||
!is Float -> throw AssertionError()
|
||||
0.0 -> {}
|
||||
else -> throw AssertionError()
|
||||
}
|
||||
|
||||
testDoubleAsUpperBound(-0.0)
|
||||
|
||||
return "OK"
|
||||
}
|
||||
}
|
||||
|
||||
fun <T: Double> testDoubleAsUpperBound(v: T): Boolean {
|
||||
return when (val a = v*v) {
|
||||
0.0 -> true
|
||||
else -> throw AssertionError()
|
||||
}
|
||||
}
|
||||
|
||||
-1
@@ -1,5 +1,4 @@
|
||||
// !LANGUAGE: +VariableDeclarationInWhenSubject
|
||||
// IGNORE_BACKEND: JS
|
||||
|
||||
val x: Any = 1
|
||||
|
||||
|
||||
Vendored
+1
-1
@@ -1,6 +1,6 @@
|
||||
// !LANGUAGE: +VariableDeclarationInWhenSubject
|
||||
// WITH_RUNTIME
|
||||
// IGNORE_BACKEND: JS, JS_IR
|
||||
// IGNORE_BACKEND: JS_IR
|
||||
|
||||
fun sparse(x: Int): Int {
|
||||
return when (val xx = (x % 4) * 100) {
|
||||
|
||||
-1
@@ -1,5 +1,4 @@
|
||||
// !LANGUAGE: +VariableDeclarationInWhenSubject
|
||||
// IGNORE_BACKEND: JS
|
||||
|
||||
var effectCount = 0
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// !LANGUAGE: +VariableDeclarationInWhenSubject
|
||||
// WITH_RUNTIME
|
||||
// IGNORE_BACKEND: JS, JS_IR
|
||||
// IGNORE_BACKEND: JS_IR
|
||||
|
||||
import kotlin.test.assertEquals
|
||||
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
// !LANGUAGE: +VariableDeclarationInWhenSubject
|
||||
// WITH_RUNTIME
|
||||
// IGNORE_BACKEND: JS, JS_IR
|
||||
// IGNORE_BACKEND: JS_IR
|
||||
|
||||
import kotlin.test.assertEquals
|
||||
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
// !LANGUAGE: +VariableDeclarationInWhenSubject
|
||||
// WITH_RUNTIME
|
||||
// IGNORE_BACKEND: JS
|
||||
|
||||
import kotlin.test.assertEquals
|
||||
|
||||
|
||||
+11
-24
@@ -1,17 +1,6 @@
|
||||
/*
|
||||
* Copyright 2010-2017 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||
* that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.js.translate.expression;
|
||||
@@ -36,10 +25,7 @@ import org.jetbrains.kotlin.js.translate.intrinsic.functions.factories.TopLevelF
|
||||
import org.jetbrains.kotlin.js.translate.reference.ReferenceTranslator;
|
||||
import org.jetbrains.kotlin.js.translate.utils.*;
|
||||
import org.jetbrains.kotlin.name.Name;
|
||||
import org.jetbrains.kotlin.psi.KtBinaryExpressionWithTypeRHS;
|
||||
import org.jetbrains.kotlin.psi.KtExpression;
|
||||
import org.jetbrains.kotlin.psi.KtIsExpression;
|
||||
import org.jetbrains.kotlin.psi.KtTypeReference;
|
||||
import org.jetbrains.kotlin.psi.*;
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils;
|
||||
import org.jetbrains.kotlin.resolve.checkers.PrimitiveNumericComparisonInfo;
|
||||
import org.jetbrains.kotlin.types.KotlinType;
|
||||
@@ -270,31 +256,32 @@ public final class PatternTranslator extends AbstractTranslator {
|
||||
|
||||
@NotNull
|
||||
public JsExpression translateExpressionPattern(
|
||||
@NotNull KtExpression subjectExpression,
|
||||
@NotNull KotlinType subjectType,
|
||||
@NotNull JsExpression expressionToMatch,
|
||||
@NotNull KtExpression patternExpression
|
||||
) {
|
||||
PrimitiveNumericComparisonInfo ieeeInfo = UtilsKt.getPrimitiveNumericComparisonInfo(context(), patternExpression);
|
||||
|
||||
KotlinType subjectType, patternType;
|
||||
KotlinType actualSubjectType;
|
||||
KotlinType patternType;
|
||||
if (ieeeInfo != null) {
|
||||
subjectType = ieeeInfo.getLeftType();
|
||||
actualSubjectType = ieeeInfo.getLeftType();
|
||||
patternType = ieeeInfo.getRightType();
|
||||
} else {
|
||||
subjectType = UtilsKt.getPrecisePrimitiveTypeNotNull(context(), subjectExpression);
|
||||
actualSubjectType = UtilsKt.refineType(subjectType);
|
||||
patternType = UtilsKt.getPrecisePrimitiveTypeNotNull(context(), patternExpression);
|
||||
}
|
||||
|
||||
EqualityType matchEquality = equalityType(subjectType);
|
||||
EqualityType matchEquality = equalityType(actualSubjectType);
|
||||
EqualityType patternEquality = equalityType(patternType);
|
||||
|
||||
JsExpression expressionToMatchAgainst = TranslationUtils.coerce(context(), translateExpressionForExpressionPattern(patternExpression), subjectType);
|
||||
JsExpression expressionToMatchAgainst = TranslationUtils.coerce(context(), translateExpressionForExpressionPattern(patternExpression), actualSubjectType);
|
||||
|
||||
if (matchEquality == EqualityType.PRIMITIVE && patternEquality == EqualityType.PRIMITIVE) {
|
||||
return equality(expressionToMatch, expressionToMatchAgainst);
|
||||
}
|
||||
else if (expressionToMatchAgainst instanceof JsNullLiteral) {
|
||||
return TranslationUtils.nullCheck(subjectExpression, expressionToMatch, context(), false);
|
||||
return TranslationUtils.nullCheck(actualSubjectType, expressionToMatch, context(), false);
|
||||
}
|
||||
else {
|
||||
return TopLevelFIF.KOTLIN_EQUALS.apply(expressionToMatch, Collections.singletonList(expressionToMatchAgainst), context());
|
||||
|
||||
+28
-18
@@ -1,17 +1,6 @@
|
||||
/*
|
||||
* Copyright 2010-2017 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||
* that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.js.translate.expression
|
||||
@@ -19,6 +8,7 @@ package org.jetbrains.kotlin.js.translate.expression
|
||||
import org.jetbrains.kotlin.backend.common.CodegenUtil
|
||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||
import org.jetbrains.kotlin.config.languageVersionSettings
|
||||
import org.jetbrains.kotlin.descriptors.CallableDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.ClassKind
|
||||
import org.jetbrains.kotlin.js.backend.ast.*
|
||||
@@ -27,6 +17,7 @@ import org.jetbrains.kotlin.js.translate.context.TranslationContext
|
||||
import org.jetbrains.kotlin.js.translate.general.AbstractTranslator
|
||||
import org.jetbrains.kotlin.js.translate.general.Translation
|
||||
import org.jetbrains.kotlin.js.translate.operation.InOperationTranslator
|
||||
import org.jetbrains.kotlin.js.translate.utils.BindingUtils
|
||||
import org.jetbrains.kotlin.js.translate.utils.JsAstUtils
|
||||
import org.jetbrains.kotlin.js.translate.utils.JsAstUtils.not
|
||||
import org.jetbrains.kotlin.js.translate.utils.mutator.CoercionMutator
|
||||
@@ -49,6 +40,7 @@ private typealias EntryWithConstants = Pair<List<JsExpression>, KtWhenEntry>
|
||||
|
||||
class WhenTranslator
|
||||
private constructor(private val whenExpression: KtWhenExpression, context: TranslationContext) : AbstractTranslator(context) {
|
||||
private val subjectType: KotlinType?
|
||||
private val expressionToMatch: JsExpression?
|
||||
private val type: KotlinType?
|
||||
private val uniqueConstants = mutableSetOf<Any>()
|
||||
@@ -63,8 +55,27 @@ private constructor(private val whenExpression: KtWhenExpression, context: Trans
|
||||
}
|
||||
|
||||
init {
|
||||
val subject = whenExpression.subjectExpression
|
||||
expressionToMatch = if (subject != null) context.defineTemporary(Translation.translateAsExpression(subject, context)) else null
|
||||
val subjectVariable = whenExpression.subjectVariable
|
||||
val subjectExpression = whenExpression.subjectExpression
|
||||
|
||||
when {
|
||||
subjectVariable != null -> {
|
||||
val variable = Translation.translateAsStatement(subjectVariable, context) as JsVars
|
||||
context.addStatementToCurrentBlock(variable)
|
||||
|
||||
val descriptor = BindingUtils.getDescriptorForElement(context.bindingContext(), subjectVariable) as? CallableDescriptor
|
||||
subjectType = descriptor?.returnType
|
||||
expressionToMatch = variable.vars.first().name.makeRef()
|
||||
}
|
||||
subjectExpression != null -> {
|
||||
subjectType = bindingContext().getType(subjectExpression)
|
||||
expressionToMatch = context.defineTemporary(Translation.translateAsExpression(subjectExpression, context))
|
||||
}
|
||||
else -> {
|
||||
subjectType = null
|
||||
expressionToMatch = null
|
||||
}
|
||||
}
|
||||
|
||||
type = bindingContext().getType(whenExpression)
|
||||
}
|
||||
@@ -123,8 +134,8 @@ private constructor(private val whenExpression: KtWhenExpression, context: Trans
|
||||
}
|
||||
|
||||
private fun translateAsSwitch(fromIndex: Int): Pair<JsSwitch, Int>? {
|
||||
val subjectType = subjectType ?: return null
|
||||
val ktSubject = whenExpression.subjectExpression ?: return null
|
||||
val subjectType = bindingContext().getType(ktSubject) ?: return null
|
||||
|
||||
val dataFlow = dataFlowValueFactory.createDataFlowValue(
|
||||
ktSubject, subjectType, bindingContext(), context().declarationDescriptor ?: context().currentModule)
|
||||
@@ -322,12 +333,11 @@ private constructor(private val whenExpression: KtWhenExpression, context: Trans
|
||||
private fun translateExpressionCondition(condition: KtWhenConditionWithExpression, context: TranslationContext): JsExpression {
|
||||
val patternExpression = condition.expression ?: error("Expression pattern should have an expression.")
|
||||
|
||||
val expressionToMatch = expressionToMatch
|
||||
val patternTranslator = Translation.patternTranslator(context)
|
||||
return if (expressionToMatch == null) {
|
||||
patternTranslator.translateExpressionForExpressionPattern(patternExpression)
|
||||
} else {
|
||||
patternTranslator.translateExpressionPattern(whenExpression.subjectExpression!!, expressionToMatch, patternExpression)
|
||||
patternTranslator.translateExpressionPattern(subjectType!!, expressionToMatch, patternExpression)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -173,6 +173,16 @@ public final class TranslationUtils {
|
||||
return nullCheck(prepareForNullCheck(ktSubject, expressionToCheck, context), isNegated);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static JsBinaryOperation nullCheck(
|
||||
@NotNull KotlinType expressionType,
|
||||
@NotNull JsExpression expressionToCheck,
|
||||
@NotNull TranslationContext context,
|
||||
boolean isNegated
|
||||
) {
|
||||
return nullCheck(coerce(context, expressionToCheck, TypeUtils.makeNullable(expressionType)), isNegated);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static JsConditional notNullConditional(
|
||||
@NotNull JsExpression expression,
|
||||
|
||||
@@ -242,6 +242,9 @@ fun TranslationContext.createCoroutineResult(resolvedCall: ResolvedCall<*>): JsE
|
||||
}
|
||||
}
|
||||
|
||||
fun KotlinType.refineType() =
|
||||
TypeUtils.getAllSupertypes(this).find(KotlinBuiltIns::isPrimitiveTypeOrNullablePrimitiveType) ?: this
|
||||
|
||||
/**
|
||||
* Tries to get precise statically known primitive type. Takes generic supertypes into account. Doesn't handle smart-casts.
|
||||
* This is needed to be compatible with JVM NaN behaviour:
|
||||
@@ -256,7 +259,7 @@ fun TranslationContext.getPrecisePrimitiveType(expression: KtExpression): Kotlin
|
||||
val bindingContext = bindingContext()
|
||||
val ktType = bindingContext.getType(expression) ?: return null
|
||||
|
||||
return TypeUtils.getAllSupertypes(ktType).find(KotlinBuiltIns::isPrimitiveTypeOrNullablePrimitiveType) ?: ktType
|
||||
return ktType.refineType()
|
||||
}
|
||||
|
||||
fun TranslationContext.getPrecisePrimitiveTypeNotNull(expression: KtExpression): KotlinType {
|
||||
|
||||
Reference in New Issue
Block a user