Support val initialization in non-inline function with EXACTLY_ONCE effect
by generating a box for the value. #KT-26126 Fixed
This commit is contained in:
@@ -97,8 +97,7 @@ import static org.jetbrains.kotlin.codegen.JvmCodegenUtil.*;
|
||||
import static org.jetbrains.kotlin.codegen.binding.CodegenBinding.*;
|
||||
import static org.jetbrains.kotlin.codegen.inline.InlineCodegenUtilsKt.*;
|
||||
import static org.jetbrains.kotlin.resolve.BindingContext.*;
|
||||
import static org.jetbrains.kotlin.resolve.BindingContextUtils.getDelegationConstructorCall;
|
||||
import static org.jetbrains.kotlin.resolve.BindingContextUtils.isVarCapturedInClosure;
|
||||
import static org.jetbrains.kotlin.resolve.BindingContextUtils.*;
|
||||
import static org.jetbrains.kotlin.resolve.DescriptorUtils.*;
|
||||
import static org.jetbrains.kotlin.resolve.jvm.AsmTypes.*;
|
||||
import static org.jetbrains.kotlin.types.expressions.ExpressionTypingUtils.isFunctionExpression;
|
||||
@@ -3030,7 +3029,7 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
|
||||
public int indexOfLocalNotDelegated(KtReferenceExpression lhs) {
|
||||
DeclarationDescriptor declarationDescriptor = bindingContext.get(REFERENCE_TARGET, lhs);
|
||||
if (isVarCapturedInClosure(bindingContext, declarationDescriptor)) {
|
||||
if (isBoxedLocalCapturedInClosure(bindingContext, declarationDescriptor)) {
|
||||
return -1;
|
||||
}
|
||||
if (declarationDescriptor instanceof LocalVariableDescriptor && ((LocalVariableDescriptor) declarationDescriptor).isDelegated()) {
|
||||
@@ -4192,6 +4191,9 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
private void initializeLocalVariableWithFakeDefaultValue(@NotNull KtProperty variableDeclaration) {
|
||||
LocalVariableDescriptor variableDescriptor = (LocalVariableDescriptor) getVariableDescriptorNotNull(variableDeclaration);
|
||||
|
||||
// For this kind of variables we generate boxes, i.e. we regard them as
|
||||
if (isCapturedInClosureWithExactlyOnceEffect(bindingContext, variableDescriptor)) return;
|
||||
|
||||
assert !variableDeclaration.isVar() && !variableDeclaration.hasDelegateExpressionOrInitializer() &&
|
||||
!variableDescriptor.isLateInit() : variableDeclaration.getText() + " in not variable declaration without initializer";
|
||||
|
||||
|
||||
@@ -73,7 +73,7 @@ import static org.jetbrains.kotlin.codegen.AsmUtil.isStaticMethod;
|
||||
import static org.jetbrains.kotlin.codegen.JvmCodegenUtil.*;
|
||||
import static org.jetbrains.kotlin.codegen.binding.CodegenBinding.*;
|
||||
import static org.jetbrains.kotlin.resolve.BindingContextUtils.getDelegationConstructorCall;
|
||||
import static org.jetbrains.kotlin.resolve.BindingContextUtils.isVarCapturedInClosure;
|
||||
import static org.jetbrains.kotlin.resolve.BindingContextUtils.isBoxedLocalCapturedInClosure;
|
||||
import static org.jetbrains.kotlin.resolve.DescriptorUtils.*;
|
||||
import static org.jetbrains.kotlin.resolve.jvm.AsmTypes.DEFAULT_CONSTRUCTOR_MARKER;
|
||||
import static org.jetbrains.kotlin.resolve.jvm.AsmTypes.OBJECT_TYPE;
|
||||
@@ -1869,7 +1869,7 @@ public class KotlinTypeMapper {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (descriptor instanceof VariableDescriptor && isVarCapturedInClosure(bindingContext, descriptor)) {
|
||||
if (descriptor instanceof VariableDescriptor && isBoxedLocalCapturedInClosure(bindingContext, descriptor)) {
|
||||
return StackValue.sharedTypeForType(mapType(((VariableDescriptor) descriptor).getType()));
|
||||
}
|
||||
|
||||
|
||||
@@ -1,17 +1,6 @@
|
||||
/*
|
||||
* Copyright 2010-2015 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.resolve;
|
||||
@@ -33,6 +22,7 @@ import org.jetbrains.kotlin.resolve.calls.tower.TowerLevelsKt;
|
||||
import org.jetbrains.kotlin.resolve.diagnostics.MutableDiagnosticsWithSuppression;
|
||||
import org.jetbrains.kotlin.types.KotlinType;
|
||||
import org.jetbrains.kotlin.types.TypeUtils;
|
||||
import org.jetbrains.kotlin.types.expressions.CaptureKind;
|
||||
import org.jetbrains.kotlin.types.expressions.KotlinTypeInfo;
|
||||
import org.jetbrains.kotlin.types.expressions.typeInfoFactory.TypeInfoFactoryKt;
|
||||
import org.jetbrains.kotlin.util.slicedMap.MutableSlicedMap;
|
||||
@@ -204,8 +194,15 @@ public class BindingContextUtils {
|
||||
return bindingContext.get(CAPTURED_IN_CLOSURE, variableDescriptor) != null;
|
||||
}
|
||||
|
||||
public static boolean isVarCapturedInClosure(BindingContext bindingContext, DeclarationDescriptor descriptor) {
|
||||
return isCapturedInClosure(bindingContext, descriptor) && ((VariableDescriptor) descriptor).isVar();
|
||||
public static boolean isCapturedInClosureWithExactlyOnceEffect(BindingContext bindingContext, DeclarationDescriptor descriptor) {
|
||||
if (!(descriptor instanceof VariableDescriptor) || descriptor instanceof PropertyDescriptor) return false;
|
||||
VariableDescriptor variableDescriptor = (VariableDescriptor) descriptor;
|
||||
return bindingContext.get(CAPTURED_IN_CLOSURE, variableDescriptor) == CaptureKind.EXACTLY_ONCE_EFFECT;
|
||||
}
|
||||
|
||||
public static boolean isBoxedLocalCapturedInClosure(BindingContext bindingContext, DeclarationDescriptor descriptor) {
|
||||
return (isCapturedInClosure(bindingContext, descriptor) && ((VariableDescriptor) descriptor).isVar()) ||
|
||||
isCapturedInClosureWithExactlyOnceEffect(bindingContext, descriptor);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
|
||||
+34
-22
@@ -1,28 +1,24 @@
|
||||
/*
|
||||
* Copyright 2010-2015 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.resolve.calls.checkers
|
||||
|
||||
import com.intellij.psi.PsiElement
|
||||
import org.jetbrains.kotlin.contracts.description.CallsEffectDeclaration
|
||||
import org.jetbrains.kotlin.contracts.description.ContractProviderKey
|
||||
import org.jetbrains.kotlin.contracts.description.InvocationKind
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.psi.KtFunction
|
||||
import org.jetbrains.kotlin.psi.KtPsiUtil
|
||||
import org.jetbrains.kotlin.resolve.BindingContext
|
||||
import org.jetbrains.kotlin.resolve.BindingContext.CAPTURED_IN_CLOSURE
|
||||
import org.jetbrains.kotlin.resolve.BindingTrace
|
||||
import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils
|
||||
import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall
|
||||
import org.jetbrains.kotlin.resolve.calls.callUtil.getValueArgumentForExpression
|
||||
import org.jetbrains.kotlin.resolve.calls.model.ArgumentMatch
|
||||
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
|
||||
import org.jetbrains.kotlin.resolve.calls.model.VariableAsFunctionResolvedCall
|
||||
import org.jetbrains.kotlin.resolve.inline.InlineUtil
|
||||
@@ -43,8 +39,7 @@ class CapturingInClosureChecker : CallChecker {
|
||||
val scopeContainer = scope.ownerDescriptor
|
||||
if (isCapturedVariable(variableParent, scopeContainer)) {
|
||||
if (trace.get(CAPTURED_IN_CLOSURE, variable) != CaptureKind.NOT_INLINE) {
|
||||
val inline = isCapturedInInline(trace.bindingContext, scopeContainer, variableParent)
|
||||
trace.record(CAPTURED_IN_CLOSURE, variable, if (inline) CaptureKind.INLINE_ONLY else CaptureKind.NOT_INLINE)
|
||||
trace.record(CAPTURED_IN_CLOSURE, variable, getCaptureKind(trace.bindingContext, scopeContainer, variableParent))
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -61,17 +56,34 @@ class CapturingInClosureChecker : CallChecker {
|
||||
return true
|
||||
}
|
||||
|
||||
private fun isCapturedInInline(
|
||||
private fun getCaptureKind(
|
||||
context: BindingContext, scopeContainer: DeclarationDescriptor, variableParent: DeclarationDescriptor
|
||||
): Boolean {
|
||||
): CaptureKind {
|
||||
val scopeDeclaration = DescriptorToSourceUtils.descriptorToDeclaration(scopeContainer)
|
||||
if (!InlineUtil.canBeInlineArgument(scopeDeclaration)) return false
|
||||
if (!InlineUtil.canBeInlineArgument(scopeDeclaration)) return CaptureKind.NOT_INLINE
|
||||
|
||||
if (InlineUtil.isInlinedArgument(scopeDeclaration as KtFunction, context, false)) {
|
||||
val exactlyOnceContract = isExactlyOnceContract(context, scopeDeclaration as KtFunction)
|
||||
if (InlineUtil.isInlinedArgument(scopeDeclaration, context, exactlyOnceContract)) {
|
||||
val scopeContainerParent = scopeContainer.containingDeclaration ?: error("parent is null for $scopeContainer")
|
||||
return !isCapturedVariable(variableParent, scopeContainerParent) ||
|
||||
isCapturedInInline(context, scopeContainerParent, variableParent)
|
||||
return if (
|
||||
!isCapturedVariable(variableParent, scopeContainerParent) ||
|
||||
getCaptureKind(context, scopeContainerParent, variableParent) == CaptureKind.INLINE_ONLY
|
||||
) CaptureKind.INLINE_ONLY else CaptureKind.NOT_INLINE
|
||||
}
|
||||
return false
|
||||
if (exactlyOnceContract) return CaptureKind.EXACTLY_ONCE_EFFECT
|
||||
return CaptureKind.NOT_INLINE
|
||||
}
|
||||
|
||||
private fun isExactlyOnceContract(bindingContext: BindingContext, argument: KtFunction): Boolean {
|
||||
val call = KtPsiUtil.getParentCallIfPresent(argument) ?: return false
|
||||
val resolvedCall = call.getResolvedCall(bindingContext) ?: return false
|
||||
val descriptor = resolvedCall.getResultingDescriptor()
|
||||
val valueArgument = resolvedCall.call.getValueArgumentForExpression(argument) ?: return false
|
||||
val mapping = resolvedCall.getArgumentMapping(valueArgument) as? ArgumentMatch ?: return false
|
||||
val parameter = mapping.valueParameter
|
||||
val contractDescription = descriptor.getUserData(ContractProviderKey)?.getContractDescription() ?: return false
|
||||
val effect = contractDescription.effects.filterIsInstance<CallsEffectDeclaration>()
|
||||
.find { it.variableReference.descriptor == parameter } ?: return false
|
||||
return effect.kind == InvocationKind.EXACTLY_ONCE
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,22 +1,12 @@
|
||||
/*
|
||||
* Copyright 2010-2015 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.types.expressions;
|
||||
|
||||
public enum CaptureKind {
|
||||
NOT_INLINE,
|
||||
INLINE_ONLY
|
||||
INLINE_ONLY,
|
||||
EXACTLY_ONCE_EFFECT
|
||||
}
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
// !LANGUAGE: +AllowContractsForCustomFunctions +UseCallsInPlaceEffect +ReadDeserializedContracts
|
||||
// !USE_EXPERIMENTAL: kotlin.contracts.ExperimentalContracts
|
||||
// IGNORE_BACKEND: JVM_IR, NATIVE, JS_IR
|
||||
|
||||
import kotlin.contracts.*
|
||||
|
||||
@Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE")
|
||||
public fun myrun(block: () -> Unit) {
|
||||
contract {
|
||||
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
|
||||
}
|
||||
block()
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
val x: Long
|
||||
myrun {
|
||||
x = 1L
|
||||
}
|
||||
return if (x != 1L) "FAIL" else "OK"
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
// !LANGUAGE: +AllowContractsForCustomFunctions +UseCallsInPlaceEffect +ReadDeserializedContracts
|
||||
// !USE_EXPERIMENTAL: kotlin.contracts.ExperimentalContracts
|
||||
// IGNORE_BACKEND: JVM_IR, NATIVE, JS_IR
|
||||
// FILE: 1.kt
|
||||
package test
|
||||
|
||||
import kotlin.contracts.*
|
||||
|
||||
@Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE")
|
||||
public inline fun myrun(crossinline block: () -> Unit): Unit {
|
||||
contract {
|
||||
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
|
||||
}
|
||||
val l = { block() }
|
||||
l()
|
||||
}
|
||||
|
||||
// FILE: 2.kt
|
||||
import test.*
|
||||
|
||||
fun box(): String {
|
||||
val x: Long
|
||||
myrun {
|
||||
x = 42L
|
||||
}
|
||||
return if (x != 42L) "FAIL" else "OK"
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
// !LANGUAGE: +AllowContractsForCustomFunctions +UseCallsInPlaceEffect +ReadDeserializedContracts
|
||||
// !USE_EXPERIMENTAL: kotlin.contracts.ExperimentalContracts
|
||||
// IGNORE_BACKEND: JVM_IR, NATIVE, JS_IR
|
||||
// NO_CHECK_LAMBDA_INLINING
|
||||
// FILE: 1.kt
|
||||
package test
|
||||
|
||||
import kotlin.contracts.*
|
||||
|
||||
@Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE")
|
||||
public inline fun myrun(noinline block: () -> Unit): Unit {
|
||||
contract {
|
||||
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
|
||||
}
|
||||
block()
|
||||
}
|
||||
|
||||
// FILE: 2.kt
|
||||
import test.*
|
||||
|
||||
fun box(): String {
|
||||
val x: Long
|
||||
myrun {
|
||||
x = 42L
|
||||
}
|
||||
return if (x != 42L) "FAIL" else "OK"
|
||||
}
|
||||
@@ -21,5 +21,5 @@ fun doIt(block: () -> Unit) {
|
||||
block()
|
||||
}
|
||||
|
||||
// 2 FCONST 0
|
||||
// 1 LOCALVARIABLE c Lkotlin/jvm/internal/Ref$CharRef; L1 L10 0
|
||||
// 0 ISTORE 0
|
||||
// 1 LOCALVARIABLE c Lkotlin/jvm/internal/Ref\$CharRef; L1 L3 0
|
||||
+18
@@ -4473,6 +4473,24 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("compiler/testData/codegen/box/contracts")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
public static class Contracts extends AbstractBlackBoxCodegenTest {
|
||||
private void runTest(String testDataFilePath) throws Exception {
|
||||
KotlinTestUtils.runTest(this::doTest, TargetBackend.JVM, testDataFilePath);
|
||||
}
|
||||
|
||||
public void testAllFilesPresentInContracts() throws Exception {
|
||||
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/contracts"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JVM, true);
|
||||
}
|
||||
|
||||
@TestMetadata("exactlyOnceNotInline.kt")
|
||||
public void testExactlyOnceNotInline() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/contracts/exactlyOnceNotInline.kt");
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("compiler/testData/codegen/box/controlStructures")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
|
||||
+10
@@ -1024,6 +1024,16 @@ public class BlackBoxInlineCodegenTestGenerated extends AbstractBlackBoxInlineCo
|
||||
runTest("compiler/testData/codegen/boxInline/contracts/definiteValInitialization.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("exactlyOnceCrossinline.kt")
|
||||
public void testExactlyOnceCrossinline() throws Exception {
|
||||
runTest("compiler/testData/codegen/boxInline/contracts/exactlyOnceCrossinline.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("exactlyOnceNoinline.kt")
|
||||
public void testExactlyOnceNoinline() throws Exception {
|
||||
runTest("compiler/testData/codegen/boxInline/contracts/exactlyOnceNoinline.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("nonLocalReturn.kt")
|
||||
public void testNonLocalReturn() throws Exception {
|
||||
runTest("compiler/testData/codegen/boxInline/contracts/nonLocalReturn.kt");
|
||||
|
||||
Generated
+10
@@ -1024,6 +1024,16 @@ public class CompileKotlinAgainstInlineKotlinTestGenerated extends AbstractCompi
|
||||
runTest("compiler/testData/codegen/boxInline/contracts/definiteValInitialization.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("exactlyOnceCrossinline.kt")
|
||||
public void testExactlyOnceCrossinline() throws Exception {
|
||||
runTest("compiler/testData/codegen/boxInline/contracts/exactlyOnceCrossinline.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("exactlyOnceNoinline.kt")
|
||||
public void testExactlyOnceNoinline() throws Exception {
|
||||
runTest("compiler/testData/codegen/boxInline/contracts/exactlyOnceNoinline.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("nonLocalReturn.kt")
|
||||
public void testNonLocalReturn() throws Exception {
|
||||
runTest("compiler/testData/codegen/boxInline/contracts/nonLocalReturn.kt");
|
||||
|
||||
+18
@@ -4473,6 +4473,24 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("compiler/testData/codegen/box/contracts")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
public static class Contracts extends AbstractLightAnalysisModeTest {
|
||||
private void runTest(String testDataFilePath) throws Exception {
|
||||
KotlinTestUtils.runTest(this::doTest, TargetBackend.JVM, testDataFilePath);
|
||||
}
|
||||
|
||||
public void testAllFilesPresentInContracts() throws Exception {
|
||||
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/contracts"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JVM, true);
|
||||
}
|
||||
|
||||
@TestMetadata("exactlyOnceNotInline.kt")
|
||||
public void testExactlyOnceNotInline() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/contracts/exactlyOnceNotInline.kt");
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("compiler/testData/codegen/box/controlStructures")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
|
||||
+18
@@ -4473,6 +4473,24 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("compiler/testData/codegen/box/contracts")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
public static class Contracts extends AbstractIrBlackBoxCodegenTest {
|
||||
private void runTest(String testDataFilePath) throws Exception {
|
||||
KotlinTestUtils.runTest(this::doTest, TargetBackend.JVM_IR, testDataFilePath);
|
||||
}
|
||||
|
||||
public void testAllFilesPresentInContracts() throws Exception {
|
||||
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/contracts"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JVM_IR, true);
|
||||
}
|
||||
|
||||
@TestMetadata("exactlyOnceNotInline.kt")
|
||||
public void testExactlyOnceNotInline() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/contracts/exactlyOnceNotInline.kt");
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("compiler/testData/codegen/box/controlStructures")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
|
||||
+10
@@ -1024,6 +1024,16 @@ public class IrBlackBoxInlineCodegenTestGenerated extends AbstractIrBlackBoxInli
|
||||
runTest("compiler/testData/codegen/boxInline/contracts/definiteValInitialization.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("exactlyOnceCrossinline.kt")
|
||||
public void testExactlyOnceCrossinline() throws Exception {
|
||||
runTest("compiler/testData/codegen/boxInline/contracts/exactlyOnceCrossinline.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("exactlyOnceNoinline.kt")
|
||||
public void testExactlyOnceNoinline() throws Exception {
|
||||
runTest("compiler/testData/codegen/boxInline/contracts/exactlyOnceNoinline.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("nonLocalReturn.kt")
|
||||
public void testNonLocalReturn() throws Exception {
|
||||
runTest("compiler/testData/codegen/boxInline/contracts/nonLocalReturn.kt");
|
||||
|
||||
+18
@@ -3663,6 +3663,24 @@ public class IrJsCodegenBoxTestGenerated extends AbstractIrJsCodegenBoxTest {
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("compiler/testData/codegen/box/contracts")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
public static class Contracts extends AbstractIrJsCodegenBoxTest {
|
||||
private void runTest(String testDataFilePath) throws Exception {
|
||||
KotlinTestUtils.runTest0(this::doTest, TargetBackend.JS_IR, testDataFilePath);
|
||||
}
|
||||
|
||||
public void testAllFilesPresentInContracts() throws Exception {
|
||||
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/contracts"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JS_IR, true);
|
||||
}
|
||||
|
||||
@TestMetadata("exactlyOnceNotInline.kt")
|
||||
public void testExactlyOnceNotInline() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/contracts/exactlyOnceNotInline.kt");
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("compiler/testData/codegen/box/controlStructures")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
|
||||
Generated
+10
@@ -64,6 +64,16 @@ public class IrJsInlineContractsTestsGenerated extends AbstractIrJsInlineContrac
|
||||
runTest("compiler/testData/codegen/boxInline/contracts/definiteValInitialization.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("exactlyOnceCrossinline.kt")
|
||||
public void testExactlyOnceCrossinline() throws Exception {
|
||||
runTest("compiler/testData/codegen/boxInline/contracts/exactlyOnceCrossinline.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("exactlyOnceNoinline.kt")
|
||||
public void testExactlyOnceNoinline() throws Exception {
|
||||
runTest("compiler/testData/codegen/boxInline/contracts/exactlyOnceNoinline.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("nonLocalReturn.kt")
|
||||
public void testNonLocalReturn() throws Exception {
|
||||
runTest("compiler/testData/codegen/boxInline/contracts/nonLocalReturn.kt");
|
||||
|
||||
+18
@@ -3673,6 +3673,24 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest {
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("compiler/testData/codegen/box/contracts")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
public static class Contracts extends AbstractJsCodegenBoxTest {
|
||||
private void runTest(String testDataFilePath) throws Exception {
|
||||
KotlinTestUtils.runTest0(this::doTest, TargetBackend.JS, testDataFilePath);
|
||||
}
|
||||
|
||||
public void testAllFilesPresentInContracts() throws Exception {
|
||||
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/contracts"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JS, true);
|
||||
}
|
||||
|
||||
@TestMetadata("exactlyOnceNotInline.kt")
|
||||
public void testExactlyOnceNotInline() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/contracts/exactlyOnceNotInline.kt");
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("compiler/testData/codegen/box/controlStructures")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
|
||||
Generated
+10
@@ -64,6 +64,16 @@ public class JsInlineContractsTestsGenerated extends AbstractJsInlineContractsTe
|
||||
runTest("compiler/testData/codegen/boxInline/contracts/definiteValInitialization.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("exactlyOnceCrossinline.kt")
|
||||
public void testExactlyOnceCrossinline() throws Exception {
|
||||
runTest("compiler/testData/codegen/boxInline/contracts/exactlyOnceCrossinline.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("exactlyOnceNoinline.kt")
|
||||
public void testExactlyOnceNoinline() throws Exception {
|
||||
runTest("compiler/testData/codegen/boxInline/contracts/exactlyOnceNoinline.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("nonLocalReturn.kt")
|
||||
public void testNonLocalReturn() throws Exception {
|
||||
runTest("compiler/testData/codegen/boxInline/contracts/nonLocalReturn.kt");
|
||||
|
||||
+4
-15
@@ -1,17 +1,6 @@
|
||||
/*
|
||||
* Copyright 2010-2015 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;
|
||||
@@ -40,7 +29,7 @@ import java.util.List;
|
||||
|
||||
import static org.jetbrains.kotlin.js.translate.context.Namer.getCapturedVarAccessor;
|
||||
import static org.jetbrains.kotlin.js.translate.utils.InlineUtils.setInlineCallMetadata;
|
||||
import static org.jetbrains.kotlin.resolve.BindingContextUtils.isVarCapturedInClosure;
|
||||
import static org.jetbrains.kotlin.resolve.BindingContextUtils.isBoxedLocalCapturedInClosure;
|
||||
|
||||
public class DestructuringDeclarationTranslator extends AbstractTranslator {
|
||||
|
||||
@@ -87,7 +76,7 @@ public class DestructuringDeclarationTranslator extends AbstractTranslator {
|
||||
entryInitializer = TranslationUtils.coerce(context(), entryInitializer, descriptor.getType());
|
||||
|
||||
JsName name = context().getNameForDescriptor(descriptor);
|
||||
if (isVarCapturedInClosure(context().bindingContext(), descriptor)) {
|
||||
if (isBoxedLocalCapturedInClosure(context().bindingContext(), descriptor)) {
|
||||
JsNameRef alias = getCapturedVarAccessor(name.makeRef());
|
||||
entryInitializer = JsAstUtils.wrapValue(alias, entryInitializer);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user