Move coroutines to kotlin.coroutines package: compiler

Generate continuation type as kotlin.coroutines.Continuaion. This code will
fail at runtime since there is no stdlib backing this change yet.
However, in order to generate compatible stdlib we need a compiler, which
generates continuation type as kotlin.coroutines.Continuation.
Thus, firstly we support the change in the compiler, make it bootstrap
compiler and only then change stdlib and tests accordingly.
 #KT-23362
This commit is contained in:
Ilmir Usmanov
2018-03-21 19:54:14 +03:00
parent f8c0c54a66
commit 2cfe387bab
67 changed files with 692 additions and 694 deletions
@@ -1,32 +1,18 @@
/* /*
* Copyright 2010-2016 JetBrains s.r.o. * 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.
* 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.
*/ */
package org.jetbrains.kotlin.backend.common package org.jetbrains.kotlin.backend.common
import org.jetbrains.kotlin.config.coroutinesIntrinsicsPackageFqName
import org.jetbrains.kotlin.descriptors.CallableDescriptor import org.jetbrains.kotlin.descriptors.CallableDescriptor
import org.jetbrains.kotlin.descriptors.FunctionDescriptor import org.jetbrains.kotlin.descriptors.FunctionDescriptor
import org.jetbrains.kotlin.descriptors.PropertyGetterDescriptor
import org.jetbrains.kotlin.incremental.components.NoLookupLocation import org.jetbrains.kotlin.incremental.components.NoLookupLocation
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.resolve.DescriptorEquivalenceForOverrides import org.jetbrains.kotlin.resolve.DescriptorEquivalenceForOverrides
import org.jetbrains.kotlin.resolve.DescriptorUtils.COROUTINES_INTRINSICS_PACKAGE_FQ_NAME
import org.jetbrains.kotlin.resolve.calls.checkers.COROUTINE_CONTEXT_1_2_20_FQ_NAME
import org.jetbrains.kotlin.resolve.calls.checkers.COROUTINE_CONTEXT_FQ_NAME
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe
import org.jetbrains.kotlin.resolve.descriptorUtil.module import org.jetbrains.kotlin.resolve.descriptorUtil.module
import org.jetbrains.kotlin.config.LanguageVersionSettings
val SUSPEND_COROUTINE_OR_RETURN_NAME = Name.identifier("suspendCoroutineOrReturn") val SUSPEND_COROUTINE_OR_RETURN_NAME = Name.identifier("suspendCoroutineOrReturn")
val INTERCEPTED_NAME = Name.identifier("intercepted") val INTERCEPTED_NAME = Name.identifier("intercepted")
@@ -34,33 +20,33 @@ val COROUTINE_SUSPENDED_NAME = Name.identifier("COROUTINE_SUSPENDED")
val SUSPEND_COROUTINE_UNINTERCEPTED_OR_RETURN_NAME = Name.identifier("suspendCoroutineUninterceptedOrReturn") val SUSPEND_COROUTINE_UNINTERCEPTED_OR_RETURN_NAME = Name.identifier("suspendCoroutineUninterceptedOrReturn")
fun FunctionDescriptor.isBuiltInIntercepted(): Boolean { fun FunctionDescriptor.isBuiltInIntercepted(languageVersionSettings: LanguageVersionSettings): Boolean {
if (name != INTERCEPTED_NAME) return false if (name != INTERCEPTED_NAME) return false
val original = val original =
module.getPackage(COROUTINES_INTRINSICS_PACKAGE_FQ_NAME).memberScope module.getPackage(languageVersionSettings.coroutinesIntrinsicsPackageFqName()).memberScope
.getContributedFunctions(INTERCEPTED_NAME, NoLookupLocation.FROM_BACKEND) .getContributedFunctions(INTERCEPTED_NAME, NoLookupLocation.FROM_BACKEND)
.singleOrNull() as CallableDescriptor .singleOrNull() as CallableDescriptor
return DescriptorEquivalenceForOverrides.areEquivalent(original, this) return DescriptorEquivalenceForOverrides.areEquivalent(original, this)
} }
fun FunctionDescriptor.isBuiltInSuspendCoroutineOrReturn(): Boolean { fun FunctionDescriptor.isBuiltInSuspendCoroutineOrReturn(languageVersionSettings: LanguageVersionSettings): Boolean {
if (name != SUSPEND_COROUTINE_OR_RETURN_NAME) return false if (name != SUSPEND_COROUTINE_OR_RETURN_NAME) return false
val originalDeclaration = getBuiltInSuspendCoroutineOrReturn() ?: return false val originalDeclaration = getBuiltInSuspendCoroutineOrReturn(languageVersionSettings) ?: return false
return DescriptorEquivalenceForOverrides.areEquivalent( return DescriptorEquivalenceForOverrides.areEquivalent(
originalDeclaration, this originalDeclaration, this
) )
} }
fun FunctionDescriptor.getBuiltInSuspendCoroutineOrReturn() = fun FunctionDescriptor.getBuiltInSuspendCoroutineOrReturn(languageVersionSettings: LanguageVersionSettings) =
module.getPackage(COROUTINES_INTRINSICS_PACKAGE_FQ_NAME).memberScope module.getPackage(languageVersionSettings.coroutinesIntrinsicsPackageFqName()).memberScope
.getContributedFunctions(SUSPEND_COROUTINE_OR_RETURN_NAME, NoLookupLocation.FROM_BACKEND) .getContributedFunctions(SUSPEND_COROUTINE_OR_RETURN_NAME, NoLookupLocation.FROM_BACKEND)
.singleOrNull() .singleOrNull()
fun FunctionDescriptor.isBuiltInSuspendCoroutineUninterceptedOrReturn(): Boolean { fun FunctionDescriptor.isBuiltInSuspendCoroutineUninterceptedOrReturn(languageVersionSettings: LanguageVersionSettings): Boolean {
if (name != SUSPEND_COROUTINE_UNINTERCEPTED_OR_RETURN_NAME) return false if (name != SUSPEND_COROUTINE_UNINTERCEPTED_OR_RETURN_NAME) return false
val original = module.getPackage(COROUTINES_INTRINSICS_PACKAGE_FQ_NAME).memberScope val original = module.getPackage(languageVersionSettings.coroutinesIntrinsicsPackageFqName()).memberScope
.getContributedFunctions(SUSPEND_COROUTINE_UNINTERCEPTED_OR_RETURN_NAME, NoLookupLocation.FROM_BACKEND) .getContributedFunctions(SUSPEND_COROUTINE_UNINTERCEPTED_OR_RETURN_NAME, NoLookupLocation.FROM_BACKEND)
.singleOrNull() as CallableDescriptor .singleOrNull() as CallableDescriptor
return DescriptorEquivalenceForOverrides.areEquivalent(original, this) return DescriptorEquivalenceForOverrides.areEquivalent(original, this)
@@ -1,5 +1,5 @@
/* /*
* Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 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. * that can be found in the license/LICENSE.txt file.
*/ */
@@ -422,7 +422,7 @@ public class ClosureCodegen extends MemberCodegen<KtElement> {
String superClassConstructorDescriptor; String superClassConstructorDescriptor;
if (superClassAsmType.equals(LAMBDA) || superClassAsmType.equals(FUNCTION_REFERENCE) || if (superClassAsmType.equals(LAMBDA) || superClassAsmType.equals(FUNCTION_REFERENCE) ||
superClassAsmType.equals(CoroutineCodegenUtilKt.COROUTINE_IMPL_ASM_TYPE)) { superClassAsmType.equals(CoroutineCodegenUtilKt.coroutineImplAsmType(state.getLanguageVersionSettings()))) {
int arity = calculateArity(); int arity = calculateArity();
iv.iconst(arity); iv.iconst(arity);
if (shouldHaveBoundReferenceReceiver) { if (shouldHaveBoundReferenceReceiver) {
@@ -1,5 +1,5 @@
/* /*
* Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 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. * that can be found in the license/LICENSE.txt file.
*/ */
@@ -2237,9 +2237,7 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
@NotNull @NotNull
public StackValue invokeFunction(@NotNull Call call, @NotNull ResolvedCall<?> resolvedCall, @NotNull StackValue receiver) { public StackValue invokeFunction(@NotNull Call call, @NotNull ResolvedCall<?> resolvedCall, @NotNull StackValue receiver) {
ResolvedCallWithRealDescriptor callWithRealDescriptor = ResolvedCallWithRealDescriptor callWithRealDescriptor =
CoroutineCodegenUtilKt.replaceSuspensionFunctionWithRealDescriptor( CoroutineCodegenUtilKt.replaceSuspensionFunctionWithRealDescriptor(resolvedCall, state);
resolvedCall, state.getProject(), state.getBindingContext()
);
if (callWithRealDescriptor != null) { if (callWithRealDescriptor != null) {
prepareCoroutineArgumentForSuspendCall(resolvedCall, callWithRealDescriptor.getFakeContinuationExpression()); prepareCoroutineArgumentForSuspendCall(resolvedCall, callWithRealDescriptor.getFakeContinuationExpression());
return invokeFunction(callWithRealDescriptor.getResolvedCall(), receiver); return invokeFunction(callWithRealDescriptor.getResolvedCall(), receiver);
@@ -2352,7 +2350,8 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
@NotNull CallGenerator callGenerator, @NotNull CallGenerator callGenerator,
@NotNull ArgumentGenerator argumentGenerator @NotNull ArgumentGenerator argumentGenerator
) { ) {
boolean isSuspendNoInlineCall = CoroutineCodegenUtilKt.isSuspendNoInlineCall(resolvedCall, this); boolean isSuspendNoInlineCall =
CoroutineCodegenUtilKt.isSuspendNoInlineCall(resolvedCall, this, state.getLanguageVersionSettings());
boolean isConstructor = resolvedCall.getResultingDescriptor() instanceof ConstructorDescriptor; boolean isConstructor = resolvedCall.getResultingDescriptor() instanceof ConstructorDescriptor;
if (!(callableMethod instanceof IntrinsicWithSpecialReceiver)) { if (!(callableMethod instanceof IntrinsicWithSpecialReceiver)) {
putReceiverAndInlineMarkerIfNeeded(callableMethod, resolvedCall, receiver, isSuspendNoInlineCall, isConstructor); putReceiverAndInlineMarkerIfNeeded(callableMethod, resolvedCall, receiver, isSuspendNoInlineCall, isConstructor);
@@ -2503,7 +2502,7 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
FunctionDescriptor original = FunctionDescriptor original =
CoroutineCodegenUtilKt.getOriginalSuspendFunctionView( CoroutineCodegenUtilKt.getOriginalSuspendFunctionView(
unwrapInitialSignatureDescriptor(DescriptorUtils.unwrapFakeOverride((FunctionDescriptor) descriptor.getOriginal())), unwrapInitialSignatureDescriptor(DescriptorUtils.unwrapFakeOverride((FunctionDescriptor) descriptor.getOriginal())),
bindingContext bindingContext, state
); );
if (isDefaultCompilation) { if (isDefaultCompilation) {
return new InlineCodegenForDefaultBody(original, this, state, new PsiSourceCompilerForInline(this, callElement)); return new InlineCodegenForDefaultBody(original, this, state, new PsiSourceCompilerForInline(this, callElement));
@@ -3583,9 +3582,7 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
ResolvedCall<?> resolvedCall = CallUtilKt.getResolvedCallWithAssert(expression, bindingContext); ResolvedCall<?> resolvedCall = CallUtilKt.getResolvedCallWithAssert(expression, bindingContext);
ResolvedCallWithRealDescriptor callWithRealDescriptor = ResolvedCallWithRealDescriptor callWithRealDescriptor =
CoroutineCodegenUtilKt.replaceSuspensionFunctionWithRealDescriptor( CoroutineCodegenUtilKt.replaceSuspensionFunctionWithRealDescriptor(resolvedCall, state);
resolvedCall, state.getProject(), state.getBindingContext()
);
if (callWithRealDescriptor != null) { if (callWithRealDescriptor != null) {
prepareCoroutineArgumentForSuspendCall(resolvedCall, callWithRealDescriptor.getFakeContinuationExpression()); prepareCoroutineArgumentForSuspendCall(resolvedCall, callWithRealDescriptor.getFakeContinuationExpression());
resolvedCall = callWithRealDescriptor.getResolvedCall(); resolvedCall = callWithRealDescriptor.getResolvedCall();
@@ -1,5 +1,5 @@
/* /*
* Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 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. * that can be found in the license/LICENSE.txt file.
*/ */
@@ -23,6 +23,7 @@ import org.jetbrains.kotlin.codegen.coroutines.SuspendFunctionGenerationStrategy
import org.jetbrains.kotlin.codegen.state.GenerationState; import org.jetbrains.kotlin.codegen.state.GenerationState;
import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper; import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper;
import org.jetbrains.kotlin.config.JvmTarget; import org.jetbrains.kotlin.config.JvmTarget;
import org.jetbrains.kotlin.config.LanguageFeature;
import org.jetbrains.kotlin.descriptors.*; import org.jetbrains.kotlin.descriptors.*;
import org.jetbrains.kotlin.descriptors.annotations.Annotated; import org.jetbrains.kotlin.descriptors.annotations.Annotated;
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor; import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor;
@@ -161,7 +162,8 @@ public class FunctionCodegen {
@NotNull FunctionGenerationStrategy strategy @NotNull FunctionGenerationStrategy strategy
) { ) {
if (CoroutineCodegenUtilKt.isSuspendFunctionNotSuspensionView(descriptor)) { if (CoroutineCodegenUtilKt.isSuspendFunctionNotSuspensionView(descriptor)) {
generateMethod(origin, CoroutineCodegenUtilKt.getOrCreateJvmSuspendFunctionView(descriptor, bindingContext), strategy); generateMethod(origin, CoroutineCodegenUtilKt.getOrCreateJvmSuspendFunctionView(descriptor, state.getLanguageVersionSettings()
.supportsFeature(LanguageFeature.ReleaseCoroutines), bindingContext), strategy);
return; return;
} }
@@ -625,7 +627,11 @@ public class FunctionCodegen {
Type thisType = getThisTypeForFunction(functionDescriptor, context, typeMapper); Type thisType = getThisTypeForFunction(functionDescriptor, context, typeMapper);
if (functionDescriptor instanceof AnonymousFunctionDescriptor && functionDescriptor.isSuspend()) { if (functionDescriptor instanceof AnonymousFunctionDescriptor && functionDescriptor.isSuspend()) {
functionDescriptor = CoroutineCodegenUtilKt.getOrCreateJvmSuspendFunctionView(functionDescriptor, typeMapper.getBindingContext()); functionDescriptor = CoroutineCodegenUtilKt.getOrCreateJvmSuspendFunctionView(
functionDescriptor,
parentCodegen.state.getLanguageVersionSettings().supportsFeature(LanguageFeature.ReleaseCoroutines),
typeMapper.getBindingContext()
);
} }
generateLocalVariableTable( generateLocalVariableTable(
mv, signature, functionDescriptor, thisType, methodBegin, methodEnd, context.getContextKind(), typeMapper, mv, signature, functionDescriptor, thisType, methodBegin, methodEnd, context.getContextKind(), typeMapper,
@@ -1,24 +1,15 @@
/* /*
* Copyright 2010-2016 JetBrains s.r.o. * 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.
* 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.
*/ */
package org.jetbrains.kotlin.codegen package org.jetbrains.kotlin.codegen
import org.jetbrains.kotlin.builtins.createFunctionType import org.jetbrains.kotlin.builtins.createFunctionType
import org.jetbrains.kotlin.codegen.coroutines.COROUTINES_JVM_INTERNAL_PACKAGE_FQ_NAME import org.jetbrains.kotlin.codegen.coroutines.coroutinesJvmInternalPackageFqName
import org.jetbrains.kotlin.codegen.coroutines.getOrCreateJvmSuspendFunctionView import org.jetbrains.kotlin.codegen.coroutines.getOrCreateJvmSuspendFunctionView
import org.jetbrains.kotlin.config.LanguageVersionSettings
import org.jetbrains.kotlin.config.LanguageFeature
import org.jetbrains.kotlin.coroutines.isSuspendLambda import org.jetbrains.kotlin.coroutines.isSuspendLambda
import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.annotations.Annotations import org.jetbrains.kotlin.descriptors.annotations.Annotations
@@ -31,10 +22,10 @@ import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns
import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.kotlin.types.KotlinType
class JvmRuntimeTypes(module: ModuleDescriptor) { class JvmRuntimeTypes(module: ModuleDescriptor, private val languageVersionSettings: LanguageVersionSettings) {
private val kotlinJvmInternalPackage = MutablePackageFragmentDescriptor(module, FqName("kotlin.jvm.internal")) private val kotlinJvmInternalPackage = MutablePackageFragmentDescriptor(module, FqName("kotlin.jvm.internal"))
private val kotlinCoroutinesJvmInternalPackage = private val kotlinCoroutinesJvmInternalPackage =
MutablePackageFragmentDescriptor(module, COROUTINES_JVM_INTERNAL_PACKAGE_FQ_NAME) MutablePackageFragmentDescriptor(module, languageVersionSettings.coroutinesJvmInternalPackageFqName())
private fun klass(name: String) = lazy { createClass(kotlinJvmInternalPackage, name) } private fun klass(name: String) = lazy { createClass(kotlinJvmInternalPackage, name) }
@@ -68,10 +59,10 @@ class JvmRuntimeTypes(module: ModuleDescriptor) {
fun getSupertypesForClosure(descriptor: FunctionDescriptor): Collection<KotlinType> { fun getSupertypesForClosure(descriptor: FunctionDescriptor): Collection<KotlinType> {
val actualFunctionDescriptor = val actualFunctionDescriptor =
if (descriptor.isSuspend) if (descriptor.isSuspend)
getOrCreateJvmSuspendFunctionView(descriptor) getOrCreateJvmSuspendFunctionView(descriptor, languageVersionSettings.supportsFeature(LanguageFeature.ReleaseCoroutines))
else else
descriptor descriptor
val functionType = createFunctionType( val functionType = createFunctionType(
descriptor.builtIns, descriptor.builtIns,
@@ -1,5 +1,5 @@
/* /*
* Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 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. * that can be found in the license/LICENSE.txt file.
*/ */
@@ -14,13 +14,13 @@ import kotlin.collections.CollectionsKt;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import org.jetbrains.kotlin.builtins.ReflectionTypes; import org.jetbrains.kotlin.builtins.ReflectionTypes;
import org.jetbrains.kotlin.builtins.functions.FunctionInvokeDescriptor;
import org.jetbrains.kotlin.cfg.WhenChecker; import org.jetbrains.kotlin.cfg.WhenChecker;
import org.jetbrains.kotlin.codegen.*; import org.jetbrains.kotlin.codegen.*;
import org.jetbrains.kotlin.codegen.coroutines.CoroutineCodegenUtilKt; import org.jetbrains.kotlin.codegen.coroutines.CoroutineCodegenUtilKt;
import org.jetbrains.kotlin.codegen.state.GenerationState; import org.jetbrains.kotlin.codegen.state.GenerationState;
import org.jetbrains.kotlin.codegen.when.SwitchCodegenProvider; import org.jetbrains.kotlin.codegen.when.SwitchCodegenProvider;
import org.jetbrains.kotlin.codegen.when.WhenByEnumsMapping; import org.jetbrains.kotlin.codegen.when.WhenByEnumsMapping;
import org.jetbrains.kotlin.config.LanguageFeature;
import org.jetbrains.kotlin.config.LanguageVersionSettings; import org.jetbrains.kotlin.config.LanguageVersionSettings;
import org.jetbrains.kotlin.coroutines.CoroutineUtilKt; import org.jetbrains.kotlin.coroutines.CoroutineUtilKt;
import org.jetbrains.kotlin.descriptors.*; import org.jetbrains.kotlin.descriptors.*;
@@ -308,7 +308,8 @@ class CodegenAnnotatingVisitor extends KtVisitorVoid {
if (CoroutineUtilKt.isSuspendLambda(functionDescriptor)) { if (CoroutineUtilKt.isSuspendLambda(functionDescriptor)) {
SimpleFunctionDescriptor jvmSuspendFunctionView = SimpleFunctionDescriptor jvmSuspendFunctionView =
CoroutineCodegenUtilKt.getOrCreateJvmSuspendFunctionView( CoroutineCodegenUtilKt.getOrCreateJvmSuspendFunctionView(
(SimpleFunctionDescriptor) functionDescriptor (SimpleFunctionDescriptor) functionDescriptor,
languageVersionSettings.supportsFeature(LanguageFeature.ReleaseCoroutines)
); );
bindingTrace.record( bindingTrace.record(
@@ -510,7 +511,8 @@ class CodegenAnnotatingVisitor extends KtVisitorVoid {
!functionDescriptor.getVisibility().equals(Visibilities.LOCAL)) { !functionDescriptor.getVisibility().equals(Visibilities.LOCAL)) {
SimpleFunctionDescriptor jvmSuspendFunctionView = SimpleFunctionDescriptor jvmSuspendFunctionView =
CoroutineCodegenUtilKt.getOrCreateJvmSuspendFunctionView( CoroutineCodegenUtilKt.getOrCreateJvmSuspendFunctionView(
(SimpleFunctionDescriptor) functionDescriptor (SimpleFunctionDescriptor) functionDescriptor,
languageVersionSettings.supportsFeature(LanguageFeature.ReleaseCoroutines)
); );
// This is a very subtle place (hack). // This is a very subtle place (hack).
@@ -573,6 +575,7 @@ class CodegenAnnotatingVisitor extends KtVisitorVoid {
SimpleFunctionDescriptor jvmSuspendFunctionView = SimpleFunctionDescriptor jvmSuspendFunctionView =
CoroutineCodegenUtilKt.getOrCreateJvmSuspendFunctionView( CoroutineCodegenUtilKt.getOrCreateJvmSuspendFunctionView(
(SimpleFunctionDescriptor) functionDescriptor, (SimpleFunctionDescriptor) functionDescriptor,
languageVersionSettings.supportsFeature(LanguageFeature.ReleaseCoroutines),
/*bindingContext*/ null, /*bindingContext*/ null,
/*dropSuspend*/ true /*dropSuspend*/ true
); );
@@ -1,5 +1,5 @@
/* /*
* Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 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. * that can be found in the license/LICENSE.txt file.
*/ */
@@ -13,7 +13,7 @@ import org.jetbrains.kotlin.codegen.binding.CodegenBinding.CAPTURES_CROSSINLINE_
import org.jetbrains.kotlin.codegen.context.ClosureContext import org.jetbrains.kotlin.codegen.context.ClosureContext
import org.jetbrains.kotlin.codegen.context.MethodContext import org.jetbrains.kotlin.codegen.context.MethodContext
import org.jetbrains.kotlin.codegen.serialization.JvmSerializerExtension import org.jetbrains.kotlin.codegen.serialization.JvmSerializerExtension
import org.jetbrains.kotlin.coroutines.isSuspendLambda import org.jetbrains.kotlin.config.LanguageFeature
import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.annotations.Annotations import org.jetbrains.kotlin.descriptors.annotations.Annotations
import org.jetbrains.kotlin.descriptors.impl.SimpleFunctionDescriptorImpl import org.jetbrains.kotlin.descriptors.impl.SimpleFunctionDescriptorImpl
@@ -53,6 +53,7 @@ abstract class AbstractCoroutineCodegen(
outerExpressionCodegen.parentCodegen, classBuilder outerExpressionCodegen.parentCodegen, classBuilder
) { ) {
protected val classDescriptor = closureContext.contextDescriptor protected val classDescriptor = closureContext.contextDescriptor
protected val languageVersionSettings = outerExpressionCodegen.state.languageVersionSettings
protected val doResumeDescriptor = protected val doResumeDescriptor =
SimpleFunctionDescriptorImpl.create( SimpleFunctionDescriptorImpl.create(
@@ -85,7 +86,7 @@ abstract class AbstractCoroutineCodegen(
override fun generateConstructor(): Method { override fun generateConstructor(): Method {
val args = calculateConstructorParameters(typeMapper, closure, asmType) val args = calculateConstructorParameters(typeMapper, closure, asmType)
val argTypes = args.map { it.fieldType }.plus(CONTINUATION_ASM_TYPE).toTypedArray() val argTypes = args.map { it.fieldType }.plus(languageVersionSettings.continuationAsmType()).toTypedArray()
val constructor = Method("<init>", Type.VOID_TYPE, argTypes) val constructor = Method("<init>", Type.VOID_TYPE, argTypes)
val mv = v.newMethod( val mv = v.newMethod(
@@ -104,9 +105,9 @@ abstract class AbstractCoroutineCodegen(
iv.load(argTypes.map { it.size }.sum(), AsmTypes.OBJECT_TYPE) iv.load(argTypes.map { it.size }.sum(), AsmTypes.OBJECT_TYPE)
val superClassConstructorDescriptor = Type.getMethodDescriptor( val superClassConstructorDescriptor = Type.getMethodDescriptor(
Type.VOID_TYPE, Type.VOID_TYPE,
Type.INT_TYPE, Type.INT_TYPE,
CONTINUATION_ASM_TYPE languageVersionSettings.continuationAsmType()
) )
iv.invokespecial(superClassAsmType.internalName, "<init>", superClassConstructorDescriptor, false) iv.invokespecial(superClassAsmType.internalName, "<init>", superClassConstructorDescriptor, false)
@@ -142,7 +143,10 @@ class CoroutineCodegenForLambda private constructor(
funDescriptor.createCustomCopy { funDescriptor.createCustomCopy {
setName(Name.identifier(SUSPEND_FUNCTION_CREATE_METHOD_NAME)) setName(Name.identifier(SUSPEND_FUNCTION_CREATE_METHOD_NAME))
setReturnType( setReturnType(
funDescriptor.module.getContinuationOfTypeOrAny(builtIns.unitType) funDescriptor.module.getContinuationOfTypeOrAny(
builtIns.unitType,
state.languageVersionSettings.supportsFeature(LanguageFeature.ReleaseCoroutines)
)
) )
// 'create' method should not inherit initial descriptor for suspend function from original descriptor // 'create' method should not inherit initial descriptor for suspend function from original descriptor
putUserData(INITIAL_DESCRIPTOR_FOR_SUSPEND_FUNCTION, null) putUserData(INITIAL_DESCRIPTOR_FOR_SUSPEND_FUNCTION, null)
@@ -205,8 +209,8 @@ class CoroutineCodegenForLambda private constructor(
v.thisName, v.thisName,
createCoroutineDescriptor.name.identifier, createCoroutineDescriptor.name.identifier,
Type.getMethodDescriptor( Type.getMethodDescriptor(
CONTINUATION_ASM_TYPE, languageVersionSettings.continuationAsmType(),
*parameterTypes.toTypedArray() *parameterTypes.toTypedArray()
), ),
false false
) )
@@ -307,7 +311,8 @@ class CoroutineCodegenForLambda private constructor(
lineNumber = CodegenUtil.getLineNumberForElement(element, false) ?: 0, lineNumber = CodegenUtil.getLineNumberForElement(element, false) ?: 0,
shouldPreserveClassInitialization = constructorCallNormalizationMode.shouldPreserveClassInitialization, shouldPreserveClassInitialization = constructorCallNormalizationMode.shouldPreserveClassInitialization,
containingClassInternalName = v.thisName, containingClassInternalName = v.thisName,
isForNamedFunction = false isForNamedFunction = false,
languageVersionSettings = languageVersionSettings
) )
} }
@@ -333,8 +338,12 @@ class CoroutineCodegenForLambda private constructor(
expressionCodegen, expressionCodegen,
declaration, declaration,
expressionCodegen.context.intoCoroutineClosure( expressionCodegen.context.intoCoroutineClosure(
getOrCreateJvmSuspendFunctionView(originalSuspendLambdaDescriptor, expressionCodegen.state.bindingContext), getOrCreateJvmSuspendFunctionView(
originalSuspendLambdaDescriptor, expressionCodegen, expressionCodegen.state.typeMapper originalSuspendLambdaDescriptor,
expressionCodegen.state.languageVersionSettings.supportsFeature(LanguageFeature.ReleaseCoroutines),
expressionCodegen.state.bindingContext
),
originalSuspendLambdaDescriptor, expressionCodegen, expressionCodegen.state.typeMapper
), ),
classBuilder, classBuilder,
originalSuspendLambdaDescriptor, originalSuspendLambdaDescriptor,
@@ -352,6 +361,14 @@ class CoroutineCodegenForNamedFunction private constructor(
classBuilder: ClassBuilder, classBuilder: ClassBuilder,
originalSuspendFunctionDescriptor: FunctionDescriptor originalSuspendFunctionDescriptor: FunctionDescriptor
) : AbstractCoroutineCodegen(outerExpressionCodegen, element, closureContext, classBuilder) { ) : AbstractCoroutineCodegen(outerExpressionCodegen, element, closureContext, classBuilder) {
private val labelFieldStackValue = StackValue.field(
FieldInfo.createForHiddenField(
outerExpressionCodegen.state.languageVersionSettings.coroutineImplAsmType(),
Type.INT_TYPE,
COROUTINE_LABEL_FIELD_NAME
),
StackValue.LOCAL_0
)
private val suspendFunctionJvmView = private val suspendFunctionJvmView =
bindingContext[CodegenBinding.SUSPEND_FUNCTION_TO_JVM_VIEW, originalSuspendFunctionDescriptor]!! bindingContext[CodegenBinding.SUSPEND_FUNCTION_TO_JVM_VIEW, originalSuspendFunctionDescriptor]!!
@@ -393,13 +410,13 @@ class CoroutineCodegenForNamedFunction private constructor(
StackValue.LOCAL_0 StackValue.LOCAL_0
).store(StackValue.local(2, AsmTypes.JAVA_THROWABLE_TYPE), codegen.v) ).store(StackValue.local(2, AsmTypes.JAVA_THROWABLE_TYPE), codegen.v)
LABEL_FIELD_STACK_VALUE.store( labelFieldStackValue.store(
StackValue.operation(Type.INT_TYPE) { StackValue.operation(Type.INT_TYPE) {
LABEL_FIELD_STACK_VALUE.put(Type.INT_TYPE, it) labelFieldStackValue.put(Type.INT_TYPE, it)
it.iconst(1 shl 31) it.iconst(1 shl 31)
it.or(Type.INT_TYPE) it.or(Type.INT_TYPE)
}, },
codegen.v codegen.v
) )
val captureThisType = closure.captureThis?.let(typeMapper::mapType) val captureThisType = closure.captureThis?.let(typeMapper::mapType)
@@ -450,7 +467,7 @@ class CoroutineCodegenForNamedFunction private constructor(
) )
mv.visitCode() mv.visitCode()
LABEL_FIELD_STACK_VALUE.put(Type.INT_TYPE, InstructionAdapter(mv)) labelFieldStackValue.put(Type.INT_TYPE, InstructionAdapter(mv))
mv.visitInsn(Opcodes.IRETURN) mv.visitInsn(Opcodes.IRETURN)
mv.visitEnd() mv.visitEnd()
} }
@@ -466,7 +483,7 @@ class CoroutineCodegenForNamedFunction private constructor(
) )
mv.visitCode() mv.visitCode()
LABEL_FIELD_STACK_VALUE.store(StackValue.local(1, Type.INT_TYPE), InstructionAdapter(mv)) labelFieldStackValue.store(StackValue.local(1, Type.INT_TYPE), InstructionAdapter(mv))
mv.visitInsn(Opcodes.RETURN) mv.visitInsn(Opcodes.RETURN)
mv.visitEnd() mv.visitEnd()
} }
@@ -478,14 +495,7 @@ class CoroutineCodegenForNamedFunction private constructor(
AsmUtil.writeAnnotationData(av, serializer, functionProto) AsmUtil.writeAnnotationData(av, serializer, functionProto)
} }
} }
companion object { companion object {
private val LABEL_FIELD_STACK_VALUE =
StackValue.field(
FieldInfo.createForHiddenField(COROUTINE_IMPL_ASM_TYPE, Type.INT_TYPE, COROUTINE_LABEL_FIELD_NAME),
StackValue.LOCAL_0
)
fun create( fun create(
cv: ClassBuilder, cv: ClassBuilder,
expressionCodegen: ExpressionCodegen, expressionCodegen: ExpressionCodegen,
@@ -1,17 +1,6 @@
/* /*
* Copyright 2010-2016 JetBrains s.r.o. * 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.
* 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.
*/ */
package org.jetbrains.kotlin.codegen.coroutines package org.jetbrains.kotlin.codegen.coroutines
@@ -27,6 +16,7 @@ import org.jetbrains.kotlin.codegen.optimization.common.*
import org.jetbrains.kotlin.codegen.optimization.fixStack.FixStackMethodTransformer import org.jetbrains.kotlin.codegen.optimization.fixStack.FixStackMethodTransformer
import org.jetbrains.kotlin.codegen.optimization.fixStack.top import org.jetbrains.kotlin.codegen.optimization.fixStack.top
import org.jetbrains.kotlin.codegen.optimization.transformer.MethodTransformer import org.jetbrains.kotlin.codegen.optimization.transformer.MethodTransformer
import org.jetbrains.kotlin.config.LanguageVersionSettings
import org.jetbrains.kotlin.resolve.jvm.AsmTypes import org.jetbrains.kotlin.resolve.jvm.AsmTypes
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin
import org.jetbrains.kotlin.utils.sure import org.jetbrains.kotlin.utils.sure
@@ -52,6 +42,7 @@ class CoroutineTransformerMethodVisitor(
private val isForNamedFunction: Boolean, private val isForNamedFunction: Boolean,
private val shouldPreserveClassInitialization: Boolean, private val shouldPreserveClassInitialization: Boolean,
private val lineNumber: Int, private val lineNumber: Int,
private val languageVersionSettings: LanguageVersionSettings,
// It's only matters for named functions, may differ from '!isStatic(access)' in case of DefaultImpls // It's only matters for named functions, may differ from '!isStatic(access)' in case of DefaultImpls
private val needDispatchReceiver: Boolean = false, private val needDispatchReceiver: Boolean = false,
// May differ from containingClassInternalName in case of DefaultImpls // May differ from containingClassInternalName in case of DefaultImpls
@@ -73,7 +64,7 @@ class CoroutineTransformerMethodVisitor(
) )
FixStackMethodTransformer().transform(containingClassInternalName, methodNode) FixStackMethodTransformer().transform(containingClassInternalName, methodNode)
RedundantLocalsEliminationMethodTransformer().transform(containingClassInternalName, methodNode) RedundantLocalsEliminationMethodTransformer(languageVersionSettings).transform(containingClassInternalName, methodNode)
updateMaxStack(methodNode) updateMaxStack(methodNode)
val suspensionPoints = collectSuspensionPoints(methodNode) val suspensionPoints = collectSuspensionPoints(methodNode)
@@ -128,7 +119,7 @@ class CoroutineTransformerMethodVisitor(
insertBefore( insertBefore(
actualCoroutineStart, actualCoroutineStart,
insnListOf( insnListOf(
*withInstructionAdapter { loadCoroutineSuspendedMarker() }.toArray(), *withInstructionAdapter { loadCoroutineSuspendedMarker(languageVersionSettings) }.toArray(),
tableSwitchLabel, tableSwitchLabel,
// Allow debugger to stop on enter into suspend function // Allow debugger to stop on enter into suspend function
LineNumberNode(lineNumber, tableSwitchLabel), LineNumberNode(lineNumber, tableSwitchLabel),
@@ -181,7 +172,7 @@ class CoroutineTransformerMethodVisitor(
else else
FieldInsnNode( FieldInsnNode(
Opcodes.GETFIELD, Opcodes.GETFIELD,
COROUTINE_IMPL_ASM_TYPE.internalName, languageVersionSettings.coroutineImplAsmType().internalName,
COROUTINE_LABEL_FIELD_NAME, Type.INT_TYPE.descriptor COROUTINE_LABEL_FIELD_NAME, Type.INT_TYPE.descriptor
) )
@@ -197,7 +188,7 @@ class CoroutineTransformerMethodVisitor(
else else
FieldInsnNode( FieldInsnNode(
Opcodes.PUTFIELD, Opcodes.PUTFIELD,
COROUTINE_IMPL_ASM_TYPE.internalName, languageVersionSettings.coroutineImplAsmType().internalName,
COROUTINE_LABEL_FIELD_NAME, Type.INT_TYPE.descriptor COROUTINE_LABEL_FIELD_NAME, Type.INT_TYPE.descriptor
) )
@@ -291,7 +282,8 @@ class CoroutineTransformerMethodVisitor(
needDispatchReceiver, needDispatchReceiver,
internalNameForDispatchReceiver, internalNameForDispatchReceiver,
containingClassInternalName, containingClassInternalName,
classBuilderForCoroutineState classBuilderForCoroutineState,
languageVersionSettings
) )
visitVarInsn(Opcodes.ASTORE, continuationIndex) visitVarInsn(Opcodes.ASTORE, continuationIndex)
@@ -605,7 +597,8 @@ internal fun InstructionAdapter.generateContinuationConstructorCall(
needDispatchReceiver: Boolean, needDispatchReceiver: Boolean,
internalNameForDispatchReceiver: String?, internalNameForDispatchReceiver: String?,
containingClassInternalName: String, containingClassInternalName: String,
classBuilderForCoroutineState: ClassBuilder classBuilderForCoroutineState: ClassBuilder,
languageVersionSettings: LanguageVersionSettings
) { ) {
anew(objectTypeForState) anew(objectTypeForState)
dup() dup()
@@ -614,7 +607,8 @@ internal fun InstructionAdapter.generateContinuationConstructorCall(
getParameterTypesIndicesForCoroutineConstructor( getParameterTypesIndicesForCoroutineConstructor(
methodNode.desc, methodNode.desc,
methodNode.access, methodNode.access,
needDispatchReceiver, internalNameForDispatchReceiver ?: containingClassInternalName needDispatchReceiver, internalNameForDispatchReceiver ?: containingClassInternalName,
languageVersionSettings
) )
for ((type, index) in parameterTypesAndIndices) { for ((type, index) in parameterTypesAndIndices) {
load(index, type) load(index, type)
@@ -703,7 +697,8 @@ private fun getParameterTypesIndicesForCoroutineConstructor(
desc: String, desc: String,
containingFunctionAccess: Int, containingFunctionAccess: Int,
needDispatchReceiver: Boolean, needDispatchReceiver: Boolean,
thisName: String thisName: String,
languageVersionSettings: LanguageVersionSettings
): Collection<Pair<Type, Int>> { ): Collection<Pair<Type, Int>> {
return mutableListOf<Pair<Type, Int>>().apply { return mutableListOf<Pair<Type, Int>>().apply {
if (needDispatchReceiver) { if (needDispatchReceiver) {
@@ -711,7 +706,7 @@ private fun getParameterTypesIndicesForCoroutineConstructor(
} }
val continuationIndex = val continuationIndex =
getAllParameterTypes(desc, !isStatic(containingFunctionAccess), thisName).dropLast(1).map(Type::getSize).sum() getAllParameterTypes(desc, !isStatic(containingFunctionAccess), thisName).dropLast(1).map(Type::getSize).sum()
add(CONTINUATION_ASM_TYPE to continuationIndex) add(languageVersionSettings.continuationAsmType() to continuationIndex)
} }
} }
@@ -1,5 +1,5 @@
/* /*
* Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 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. * that can be found in the license/LICENSE.txt file.
*/ */
@@ -11,6 +11,7 @@ import org.jetbrains.kotlin.codegen.optimization.common.asSequence
import org.jetbrains.kotlin.codegen.optimization.common.isMeaningful import org.jetbrains.kotlin.codegen.optimization.common.isMeaningful
import org.jetbrains.kotlin.codegen.optimization.common.removeAll import org.jetbrains.kotlin.codegen.optimization.common.removeAll
import org.jetbrains.kotlin.codegen.optimization.transformer.MethodTransformer import org.jetbrains.kotlin.codegen.optimization.transformer.MethodTransformer
import org.jetbrains.kotlin.config.LanguageVersionSettings
import org.jetbrains.org.objectweb.asm.Opcodes import org.jetbrains.org.objectweb.asm.Opcodes
import org.jetbrains.org.objectweb.asm.tree.* import org.jetbrains.org.objectweb.asm.tree.*
@@ -18,7 +19,7 @@ import org.jetbrains.org.objectweb.asm.tree.*
// Remove all of them since these locals are // Remove all of them since these locals are
// 1) going to be spilled into continuation object // 1) going to be spilled into continuation object
// 2) breaking tail-call elimination // 2) breaking tail-call elimination
class RedundantLocalsEliminationMethodTransformer : MethodTransformer() { class RedundantLocalsEliminationMethodTransformer(private val languageVersionSettings: LanguageVersionSettings) : MethodTransformer() {
lateinit var internalClassName: String lateinit var internalClassName: String
override fun transform(internalClassName: String, methodNode: MethodNode) { override fun transform(internalClassName: String, methodNode: MethodNode) {
this.internalClassName = internalClassName this.internalClassName = internalClassName
@@ -26,7 +27,7 @@ class RedundantLocalsEliminationMethodTransformer : MethodTransformer() {
var changed = false var changed = false
changed = simpleRemove(methodNode) || changed changed = simpleRemove(methodNode) || changed
changed = removeWithReplacement(methodNode) || changed changed = removeWithReplacement(methodNode) || changed
changed = removeAloadCheckcastContinuationAstore(methodNode) || changed changed = removeAloadCheckcastContinuationAstore(methodNode, languageVersionSettings) || changed
} while (changed) } while (changed)
} }
@@ -139,12 +140,12 @@ class RedundantLocalsEliminationMethodTransformer : MethodTransformer() {
// ... // ...
// ALOAD K // ALOAD K
// CHECKCAST Continuation // CHECKCAST Continuation
private fun removeAloadCheckcastContinuationAstore(methodNode: MethodNode): Boolean { private fun removeAloadCheckcastContinuationAstore(methodNode: MethodNode, languageVersionSettings: LanguageVersionSettings): Boolean {
// Here we ignore the duplicates of continuation in local variable table, // Here we ignore the duplicates of continuation in local variable table,
// Since it increases performance greatly. // Since it increases performance greatly.
val insns = findSafeAstorePredecessors(methodNode, ignoreLocalVariableTable = true) { val insns = findSafeAstorePredecessors(methodNode, ignoreLocalVariableTable = true) {
it.opcode == Opcodes.CHECKCAST && it.opcode == Opcodes.CHECKCAST &&
(it as TypeInsnNode).desc == CONTINUATION_ASM_TYPE.internalName && (it as TypeInsnNode).desc == languageVersionSettings.continuationAsmType().internalName &&
it.previous?.opcode == Opcodes.ALOAD it.previous?.opcode == Opcodes.ALOAD
} }
@@ -1,17 +1,6 @@
/* /*
* Copyright 2010-2016 JetBrains s.r.o. * 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.
* 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.
*/ */
package org.jetbrains.kotlin.codegen.coroutines package org.jetbrains.kotlin.codegen.coroutines
@@ -25,6 +14,8 @@ import org.jetbrains.kotlin.codegen.binding.CodegenBinding
import org.jetbrains.kotlin.codegen.inline.addFakeContinuationConstructorCallMarker import org.jetbrains.kotlin.codegen.inline.addFakeContinuationConstructorCallMarker
import org.jetbrains.kotlin.codegen.state.GenerationState import org.jetbrains.kotlin.codegen.state.GenerationState
import org.jetbrains.kotlin.config.JVMConstructorCallNormalizationMode import org.jetbrains.kotlin.config.JVMConstructorCallNormalizationMode
import org.jetbrains.kotlin.config.LanguageVersionSettings
import org.jetbrains.kotlin.config.languageVersionSettings
import org.jetbrains.kotlin.descriptors.ClassDescriptor import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.descriptors.FunctionDescriptor import org.jetbrains.kotlin.descriptors.FunctionDescriptor
import org.jetbrains.kotlin.psi.KtFunction import org.jetbrains.kotlin.psi.KtFunction
@@ -46,6 +37,7 @@ class SuspendFunctionGenerationStrategy(
) : FunctionGenerationStrategy.CodegenBased(state) { ) : FunctionGenerationStrategy.CodegenBased(state) {
private lateinit var codegen: ExpressionCodegen private lateinit var codegen: ExpressionCodegen
private val languageVersionSettings: LanguageVersionSettings = state.configuration.languageVersionSettings
private val classBuilderForCoroutineState by lazy { private val classBuilderForCoroutineState by lazy {
state.factory.newVisitor( state.factory.newVisitor(
@@ -67,7 +59,8 @@ class SuspendFunctionGenerationStrategy(
mv, access, name, desc, null, null, this::classBuilderForCoroutineState, mv, access, name, desc, null, null, this::classBuilderForCoroutineState,
containingClassInternalName, containingClassInternalName,
originalSuspendDescriptor.dispatchReceiverParameter != null, originalSuspendDescriptor.dispatchReceiverParameter != null,
containingClassInternalNameOrNull() containingClassInternalNameOrNull(),
languageVersionSettings
) )
} }
return CoroutineTransformerMethodVisitor( return CoroutineTransformerMethodVisitor(
@@ -76,7 +69,8 @@ class SuspendFunctionGenerationStrategy(
lineNumber = CodegenUtil.getLineNumberForElement(declaration, false) ?: 0, lineNumber = CodegenUtil.getLineNumberForElement(declaration, false) ?: 0,
shouldPreserveClassInitialization = constructorCallNormalizationMode.shouldPreserveClassInitialization, shouldPreserveClassInitialization = constructorCallNormalizationMode.shouldPreserveClassInitialization,
needDispatchReceiver = originalSuspendDescriptor.dispatchReceiverParameter != null, needDispatchReceiver = originalSuspendDescriptor.dispatchReceiverParameter != null,
internalNameForDispatchReceiver = containingClassInternalNameOrNull() internalNameForDispatchReceiver = containingClassInternalNameOrNull(),
languageVersionSettings = languageVersionSettings
) )
} }
@@ -103,7 +97,8 @@ class SuspendFunctionGenerationStrategy(
obtainClassBuilderForCoroutineState: () -> ClassBuilder, obtainClassBuilderForCoroutineState: () -> ClassBuilder,
private val containingClassInternalName: String, private val containingClassInternalName: String,
private val needDispatchReceiver: Boolean, private val needDispatchReceiver: Boolean,
private val internalNameForDispatchReceiver: String? private val internalNameForDispatchReceiver: String?,
private val languageVersionSettings: LanguageVersionSettings
) : TransformationMethodVisitor(delegate, access, name, desc, signature, exceptions) { ) : TransformationMethodVisitor(delegate, access, name, desc, signature, exceptions) {
private val classBuilderForCoroutineState: ClassBuilder by lazy(obtainClassBuilderForCoroutineState) private val classBuilderForCoroutineState: ClassBuilder by lazy(obtainClassBuilderForCoroutineState)
override fun performTransformations(methodNode: MethodNode) { override fun performTransformations(methodNode: MethodNode) {
@@ -116,7 +111,8 @@ class SuspendFunctionGenerationStrategy(
needDispatchReceiver, needDispatchReceiver,
internalNameForDispatchReceiver, internalNameForDispatchReceiver,
containingClassInternalName, containingClassInternalName,
classBuilderForCoroutineState classBuilderForCoroutineState,
languageVersionSettings
) )
addFakeContinuationConstructorCallMarker(this, false) addFakeContinuationConstructorCallMarker(this, false)
}) })
@@ -1,32 +1,26 @@
/* /*
* Copyright 2010-2017 JetBrains s.r.o. * 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.
* 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.
*/ */
package org.jetbrains.kotlin.codegen.coroutines package org.jetbrains.kotlin.codegen.coroutines
import com.intellij.openapi.project.Project import com.intellij.openapi.project.Project
import org.jetbrains.kotlin.backend.common.* import org.jetbrains.kotlin.backend.common.COROUTINE_SUSPENDED_NAME
import org.jetbrains.kotlin.backend.common.isBuiltInIntercepted
import org.jetbrains.kotlin.backend.common.isBuiltInSuspendCoroutineOrReturn
import org.jetbrains.kotlin.backend.common.isBuiltInSuspendCoroutineUninterceptedOrReturn
import org.jetbrains.kotlin.builtins.isBuiltinFunctionalType import org.jetbrains.kotlin.builtins.isBuiltinFunctionalType
import org.jetbrains.kotlin.codegen.ExpressionCodegen import org.jetbrains.kotlin.codegen.ExpressionCodegen
import org.jetbrains.kotlin.codegen.StackValue import org.jetbrains.kotlin.codegen.StackValue
import org.jetbrains.kotlin.codegen.binding.CodegenBinding import org.jetbrains.kotlin.codegen.binding.CodegenBinding
import org.jetbrains.kotlin.codegen.inline.addFakeContinuationMarker import org.jetbrains.kotlin.codegen.inline.addFakeContinuationMarker
import org.jetbrains.kotlin.codegen.state.GenerationState
import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper
import org.jetbrains.kotlin.codegen.topLevelClassAsmType import org.jetbrains.kotlin.codegen.topLevelClassAsmType
import org.jetbrains.kotlin.codegen.topLevelClassInternalName import org.jetbrains.kotlin.codegen.topLevelClassInternalName
import org.jetbrains.kotlin.coroutines.isSuspendLambda import org.jetbrains.kotlin.coroutines.isSuspendLambda
import org.jetbrains.kotlin.config.*
import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.annotations.Annotations import org.jetbrains.kotlin.descriptors.annotations.Annotations
import org.jetbrains.kotlin.descriptors.impl.AnonymousFunctionDescriptor import org.jetbrains.kotlin.descriptors.impl.AnonymousFunctionDescriptor
@@ -62,25 +56,28 @@ const val DO_RESUME_METHOD_NAME = "doResume"
const val DATA_FIELD_NAME = "data" const val DATA_FIELD_NAME = "data"
const val EXCEPTION_FIELD_NAME = "exception" const val EXCEPTION_FIELD_NAME = "exception"
@JvmField fun LanguageVersionSettings.coroutinesJvmInternalPackageFqName() =
val COROUTINES_JVM_INTERNAL_PACKAGE_FQ_NAME = coroutinesPackageFqName().child(Name.identifier("jvm")).child(Name.identifier("internal"))
DescriptorUtils.COROUTINES_PACKAGE_FQ_NAME.child(Name.identifier("jvm")).child(Name.identifier("internal"))
@JvmField fun LanguageVersionSettings.continuationAsmType() =
val CONTINUATION_ASM_TYPE = DescriptorUtils.CONTINUATION_INTERFACE_FQ_NAME.topLevelClassAsmType() continuationInterfaceFqName().topLevelClassAsmType()
@JvmField fun continuationAsmTypes() = listOf(
val COROUTINE_CONTEXT_ASM_TYPE = LanguageVersionSettingsImpl(LanguageVersion.KOTLIN_1_3, ApiVersion.KOTLIN_1_3).continuationAsmType(),
DescriptorUtils.COROUTINES_PACKAGE_FQ_NAME.child(Name.identifier("CoroutineContext")).topLevelClassAsmType() LanguageVersionSettingsImpl(LanguageVersion.KOTLIN_1_2, ApiVersion.KOTLIN_1_2).continuationAsmType()
)
@JvmField fun LanguageVersionSettings.coroutineContextAsmType() =
val COROUTINE_IMPL_ASM_TYPE = COROUTINES_JVM_INTERNAL_PACKAGE_FQ_NAME.child(Name.identifier("CoroutineImpl")).topLevelClassAsmType() coroutinesPackageFqName().child(Name.identifier("CoroutineContext")).topLevelClassAsmType()
private val COROUTINES_INTRINSICS_FILE_FACADE_INTERNAL_NAME = fun LanguageVersionSettings.coroutineImplAsmType() =
DescriptorUtils.COROUTINES_INTRINSICS_PACKAGE_FQ_NAME.child(Name.identifier("IntrinsicsKt")).topLevelClassAsmType() coroutinesJvmInternalPackageFqName().child(Name.identifier("CoroutineImpl")).topLevelClassAsmType()
private val INTERNAL_COROUTINE_INTRINSICS_OWNER_INTERNAL_NAME = private fun LanguageVersionSettings.coroutinesIntrinsicsFileFacadeInternalName() =
COROUTINES_JVM_INTERNAL_PACKAGE_FQ_NAME.child(Name.identifier("CoroutineIntrinsics")).topLevelClassInternalName() coroutinesIntrinsicsPackageFqName().child(Name.identifier("IntrinsicsKt")).topLevelClassAsmType()
private fun LanguageVersionSettings.internalCoroutineIntrinsicsOwnerInternalName() =
coroutinesJvmInternalPackageFqName().child(Name.identifier("CoroutineIntrinsics")).topLevelClassInternalName()
private val NORMALIZE_CONTINUATION_METHOD_NAME = "normalizeContinuation" private val NORMALIZE_CONTINUATION_METHOD_NAME = "normalizeContinuation"
private val GET_CONTEXT_METHOD_NAME = "getContext" private val GET_CONTEXT_METHOD_NAME = "getContext"
@@ -101,11 +98,12 @@ val INITIAL_SUSPEND_DESCRIPTOR_FOR_DO_RESUME = object : FunctionDescriptor.UserD
// and fake `this` expression that used as argument for second parameter // and fake `this` expression that used as argument for second parameter
fun ResolvedCall<*>.replaceSuspensionFunctionWithRealDescriptor( fun ResolvedCall<*>.replaceSuspensionFunctionWithRealDescriptor(
project: Project, project: Project,
bindingContext: BindingContext bindingContext: BindingContext,
isReleaseCoroutines: Boolean
): ResolvedCallWithRealDescriptor? { ): ResolvedCallWithRealDescriptor? {
if (this is VariableAsFunctionResolvedCall) { if (this is VariableAsFunctionResolvedCall) {
val replacedFunctionCall = val replacedFunctionCall =
functionCall.replaceSuspensionFunctionWithRealDescriptor(project, bindingContext) functionCall.replaceSuspensionFunctionWithRealDescriptor(project, bindingContext, isReleaseCoroutines)
?: return null ?: return null
@Suppress("UNCHECKED_CAST") @Suppress("UNCHECKED_CAST")
@@ -122,9 +120,9 @@ fun ResolvedCall<*>.replaceSuspensionFunctionWithRealDescriptor(
val newCandidateDescriptor = val newCandidateDescriptor =
when (function) { when (function) {
is FunctionImportedFromObject -> is FunctionImportedFromObject ->
getOrCreateJvmSuspendFunctionView(function.callableFromObject, bindingContext).asImportedFromObject() getOrCreateJvmSuspendFunctionView(function.callableFromObject, isReleaseCoroutines, bindingContext).asImportedFromObject()
is SimpleFunctionDescriptor -> is SimpleFunctionDescriptor ->
getOrCreateJvmSuspendFunctionView(function, bindingContext) getOrCreateJvmSuspendFunctionView(function, isReleaseCoroutines, bindingContext)
else -> else ->
throw AssertionError("Unexpected suspend function descriptor: $function") throw AssertionError("Unexpected suspend function descriptor: $function")
} }
@@ -160,6 +158,13 @@ fun ResolvedCall<*>.replaceSuspensionFunctionWithRealDescriptor(
return ResolvedCallWithRealDescriptor(newCall, thisExpression) return ResolvedCallWithRealDescriptor(newCall, thisExpression)
} }
fun ResolvedCall<*>.replaceSuspensionFunctionWithRealDescriptor(state: GenerationState): ResolvedCallWithRealDescriptor? =
replaceSuspensionFunctionWithRealDescriptor(
state.project,
state.bindingContext,
state.languageVersionSettings.supportsFeature(LanguageFeature.ReleaseCoroutines)
)
private fun ResolvedCall<VariableDescriptor>.asMutableResolvedCall(bindingContext: BindingContext): MutableResolvedCall<VariableDescriptor> { private fun ResolvedCall<VariableDescriptor>.asMutableResolvedCall(bindingContext: BindingContext): MutableResolvedCall<VariableDescriptor> {
return when (this) { return when (this) {
is ResolvedCallImpl<*> -> this as MutableResolvedCall<VariableDescriptor> is ResolvedCallImpl<*> -> this as MutableResolvedCall<VariableDescriptor>
@@ -178,14 +183,16 @@ private fun NewResolvedCallImpl<VariableDescriptor>.asDummyOldResolvedCall(bindi
) )
} }
fun ResolvedCall<*>.isSuspendNoInlineCall(codegen: ExpressionCodegen): Boolean { fun ResolvedCall<*>.isSuspendNoInlineCall(codegen: ExpressionCodegen, languageVersionSettings: LanguageVersionSettings): Boolean {
val isInlineLambda = this.safeAs<VariableAsFunctionResolvedCall>() val isInlineLambda = this.safeAs<VariableAsFunctionResolvedCall>()
?.variableCall?.resultingDescriptor?.safeAs<ValueParameterDescriptor>() ?.variableCall?.resultingDescriptor?.safeAs<ValueParameterDescriptor>()
?.let { it.isCrossinline || (!it.isNoinline && codegen.context.functionDescriptor.isInline) } == true ?.let { it.isCrossinline || (!it.isNoinline && codegen.context.functionDescriptor.isInline) } == true
val functionDescriptor = resultingDescriptor as? FunctionDescriptor ?: return false val functionDescriptor = resultingDescriptor as? FunctionDescriptor ?: return false
if (!functionDescriptor.unwrapInitialDescriptorForSuspendFunction().isSuspend) return false if (!functionDescriptor.unwrapInitialDescriptorForSuspendFunction().isSuspend) return false
if (functionDescriptor.isBuiltInSuspendCoroutineOrReturnInJvm() || functionDescriptor.isBuiltInSuspendCoroutineUninterceptedOrReturnInJvm()) return true if (functionDescriptor.isBuiltInSuspendCoroutineOrReturnInJvm(languageVersionSettings) ||
functionDescriptor.isBuiltInSuspendCoroutineUninterceptedOrReturnInJvm(languageVersionSettings)
) return true
return !(functionDescriptor.isInline || isInlineLambda) return !(functionDescriptor.isInline || isInlineLambda)
} }
@@ -200,6 +207,7 @@ fun CallableDescriptor.isSuspendFunctionNotSuspensionView(): Boolean {
@JvmOverloads @JvmOverloads
fun <D : FunctionDescriptor> getOrCreateJvmSuspendFunctionView( fun <D : FunctionDescriptor> getOrCreateJvmSuspendFunctionView(
function: D, function: D,
isReleaseCoroutines: Boolean,
bindingContext: BindingContext? = null, bindingContext: BindingContext? = null,
dropSuspend: Boolean = false dropSuspend: Boolean = false
): D { ): D {
@@ -211,14 +219,19 @@ fun <D : FunctionDescriptor> getOrCreateJvmSuspendFunctionView(
bindingContext?.get(CodegenBinding.SUSPEND_FUNCTION_TO_JVM_VIEW, function)?.let { return it as D } bindingContext?.get(CodegenBinding.SUSPEND_FUNCTION_TO_JVM_VIEW, function)?.let { return it as D }
val continuationParameter = ValueParameterDescriptorImpl( val continuationParameter = ValueParameterDescriptorImpl(
function, null, function.valueParameters.size, Annotations.EMPTY, Name.identifier("continuation"), containingDeclaration = function,
original = null,
index = function.valueParameters.size,
annotations = Annotations.EMPTY,
name = Name.identifier("continuation"),
// Add j.l.Object to invoke(), because that is the type of parameters we have in FunctionN+1 // Add j.l.Object to invoke(), because that is the type of parameters we have in FunctionN+1
if (function.containingDeclaration.safeAs<ClassDescriptor>()?.defaultType?.isBuiltinFunctionalType == true) outType = if (function.containingDeclaration.safeAs<ClassDescriptor>()?.defaultType?.isBuiltinFunctionalType == true)
function.builtIns.nullableAnyType function.builtIns.nullableAnyType
else else
function.getContinuationParameterTypeOfSuspendFunction(), function.getContinuationParameterTypeOfSuspendFunction(isReleaseCoroutines),
/* declaresDefaultValue = */ false, /* isCrossinline = */ false, declaresDefaultValue = false, isCrossinline = false,
/* isNoinline = */ false, /* varargElementType = */ null, SourceElement.NO_SOURCE isNoinline = false, varargElementType = null,
source = SourceElement.NO_SOURCE
) )
return function.createCustomCopy { return function.createCustomCopy {
@@ -255,25 +268,29 @@ fun <D : FunctionDescriptor> D.createCustomCopy(
return result as D return result as D
} }
private fun FunctionDescriptor.getContinuationParameterTypeOfSuspendFunction() = private fun FunctionDescriptor.getContinuationParameterTypeOfSuspendFunction(isReleaseCoroutines: Boolean) =
module.getContinuationOfTypeOrAny(returnType!!) module.getContinuationOfTypeOrAny(returnType!!, isReleaseCoroutines)
fun ModuleDescriptor.getContinuationOfTypeOrAny(kotlinType: KotlinType) = fun ModuleDescriptor.getContinuationOfTypeOrAny(kotlinType: KotlinType, isReleaseCoroutines: Boolean) =
module.findContinuationClassDescriptorOrNull(NoLookupLocation.FROM_BACKEND)?.defaultType?.let { module.findContinuationClassDescriptorOrNull(
NoLookupLocation.FROM_BACKEND,
isReleaseCoroutines
)?.defaultType?.let {
KotlinTypeFactory.simpleType( KotlinTypeFactory.simpleType(
it, it,
arguments = listOf(kotlinType.asTypeProjection()) arguments = listOf(kotlinType.asTypeProjection())
) )
} ?: module.builtIns.nullableAnyType } ?: module.builtIns.nullableAnyType
fun FunctionDescriptor.isBuiltInSuspendCoroutineOrReturnInJvm() = fun FunctionDescriptor.isBuiltInSuspendCoroutineOrReturnInJvm(languageVersionSettings: LanguageVersionSettings) =
getUserData(INITIAL_DESCRIPTOR_FOR_SUSPEND_FUNCTION)?.isBuiltInSuspendCoroutineOrReturn() == true getUserData(INITIAL_DESCRIPTOR_FOR_SUSPEND_FUNCTION)?.isBuiltInSuspendCoroutineOrReturn(languageVersionSettings) == true
fun createMethodNodeForSuspendCoroutineOrReturn( fun createMethodNodeForSuspendCoroutineOrReturn(
functionDescriptor: FunctionDescriptor, functionDescriptor: FunctionDescriptor,
typeMapper: KotlinTypeMapper typeMapper: KotlinTypeMapper,
languageVersionSettings: LanguageVersionSettings
): MethodNode { ): MethodNode {
assert(functionDescriptor.isBuiltInSuspendCoroutineOrReturnInJvm()) { assert(functionDescriptor.isBuiltInSuspendCoroutineOrReturnInJvm(languageVersionSettings)) {
"functionDescriptor must be kotlin.coroutines.intrinsics.suspendOrReturn" "functionDescriptor must be kotlin.coroutines.intrinsics.suspendOrReturn"
} }
@@ -288,13 +305,7 @@ fun createMethodNodeForSuspendCoroutineOrReturn(
node.visitVarInsn(Opcodes.ALOAD, 0) node.visitVarInsn(Opcodes.ALOAD, 0)
node.visitVarInsn(Opcodes.ALOAD, 1) node.visitVarInsn(Opcodes.ALOAD, 1)
node.visitMethodInsn( node.invokeNormalizeContinuation(languageVersionSettings)
Opcodes.INVOKESTATIC,
INTERNAL_COROUTINE_INTRINSICS_OWNER_INTERNAL_NAME,
NORMALIZE_CONTINUATION_METHOD_NAME,
Type.getMethodDescriptor(CONTINUATION_ASM_TYPE, CONTINUATION_ASM_TYPE),
false
)
node.visitMethodInsn( node.visitMethodInsn(
Opcodes.INVOKEINTERFACE, Opcodes.INVOKEINTERFACE,
@@ -309,14 +320,25 @@ fun createMethodNodeForSuspendCoroutineOrReturn(
return node return node
} }
fun FunctionDescriptor.isBuiltInSuspendCoroutineUninterceptedOrReturnInJvm() = private fun MethodNode.invokeNormalizeContinuation(languageVersionSettings: LanguageVersionSettings) {
getUserData(INITIAL_DESCRIPTOR_FOR_SUSPEND_FUNCTION)?.isBuiltInSuspendCoroutineUninterceptedOrReturn() == true visitMethodInsn(
Opcodes.INVOKESTATIC,
languageVersionSettings.internalCoroutineIntrinsicsOwnerInternalName(),
NORMALIZE_CONTINUATION_METHOD_NAME,
Type.getMethodDescriptor(languageVersionSettings.continuationAsmType(), languageVersionSettings.continuationAsmType()),
false
)
}
fun FunctionDescriptor.isBuiltInSuspendCoroutineUninterceptedOrReturnInJvm(languageVersionSettings: LanguageVersionSettings) =
getUserData(INITIAL_DESCRIPTOR_FOR_SUSPEND_FUNCTION)?.isBuiltInSuspendCoroutineUninterceptedOrReturn(languageVersionSettings) == true
fun createMethodNodeForIntercepted( fun createMethodNodeForIntercepted(
functionDescriptor: FunctionDescriptor, functionDescriptor: FunctionDescriptor,
typeMapper: KotlinTypeMapper typeMapper: KotlinTypeMapper,
languageVersionSettings: LanguageVersionSettings
): MethodNode { ): MethodNode {
assert(functionDescriptor.isBuiltInIntercepted()) { assert(functionDescriptor.isBuiltInIntercepted(languageVersionSettings)) {
"functionDescriptor must be kotlin.coroutines.intrinsics.intercepted" "functionDescriptor must be kotlin.coroutines.intrinsics.intercepted"
} }
@@ -330,21 +352,19 @@ fun createMethodNodeForIntercepted(
node.visitVarInsn(Opcodes.ALOAD, 0) node.visitVarInsn(Opcodes.ALOAD, 0)
node.visitMethodInsn( node.invokeNormalizeContinuation(languageVersionSettings)
Opcodes.INVOKESTATIC,
INTERNAL_COROUTINE_INTRINSICS_OWNER_INTERNAL_NAME,
NORMALIZE_CONTINUATION_METHOD_NAME,
Type.getMethodDescriptor(CONTINUATION_ASM_TYPE, CONTINUATION_ASM_TYPE),
false
)
node.visitInsn(Opcodes.ARETURN) node.visitInsn(Opcodes.ARETURN)
node.visitMaxs(1, 1) node.visitMaxs(1, 1)
return node return node
} }
fun createMethodNodeForCoroutineContext(functionDescriptor: FunctionDescriptor): MethodNode { fun createMethodNodeForCoroutineContext(
assert(functionDescriptor.isBuiltInCoroutineContext()) { functionDescriptor: FunctionDescriptor,
languageVersionSettings: LanguageVersionSettings
): MethodNode {
assert(functionDescriptor.isBuiltInCoroutineContext(languageVersionSettings)) {
"functionDescriptor must be kotlin.coroutines.intrinsics.coroutineContext property getter" "functionDescriptor must be kotlin.coroutines.intrinsics.coroutineContext property getter"
} }
@@ -353,7 +373,7 @@ fun createMethodNodeForCoroutineContext(functionDescriptor: FunctionDescriptor):
Opcodes.ASM5, Opcodes.ASM5,
Opcodes.ACC_STATIC, Opcodes.ACC_STATIC,
"fake", "fake",
Type.getMethodDescriptor(COROUTINE_CONTEXT_ASM_TYPE), Type.getMethodDescriptor(languageVersionSettings.coroutineContextAsmType()),
null, null null, null
) )
@@ -361,24 +381,19 @@ fun createMethodNodeForCoroutineContext(functionDescriptor: FunctionDescriptor):
addFakeContinuationMarker(v) addFakeContinuationMarker(v)
v.invokeinterface( v.invokeGetContext(languageVersionSettings)
CONTINUATION_ASM_TYPE.internalName,
GET_CONTEXT_METHOD_NAME,
Type.getMethodDescriptor(COROUTINE_CONTEXT_ASM_TYPE)
)
v.areturn(COROUTINE_CONTEXT_ASM_TYPE)
node.visitMaxs(1, 1) node.visitMaxs(1, 1)
return node return node
} }
fun createMethodNodeForSuspendCoroutineUninterceptedOrReturn( fun createMethodNodeForSuspendCoroutineUninterceptedOrReturn(
functionDescriptor: FunctionDescriptor, functionDescriptor: FunctionDescriptor,
typeMapper: KotlinTypeMapper typeMapper: KotlinTypeMapper,
languageVersionSettings: LanguageVersionSettings
): MethodNode { ): MethodNode {
assert(functionDescriptor.isBuiltInSuspendCoroutineUninterceptedOrReturnInJvm()) { assert(functionDescriptor.isBuiltInSuspendCoroutineUninterceptedOrReturnInJvm(languageVersionSettings)) {
"functionDescriptor must be kotlin.coroutines.intrinsics.suspendCoroutineUninterceptedOrReturn" "functionDescriptor must be kotlin.coroutines.intrinsics.suspendCoroutineUninterceptedOrReturn"
} }
@@ -406,20 +421,33 @@ fun createMethodNodeForSuspendCoroutineUninterceptedOrReturn(
return node return node
} }
private fun InstructionAdapter.invokeGetContext(languageVersionSettings: LanguageVersionSettings) {
invokeinterface(
languageVersionSettings.continuationAsmType().internalName,
GET_CONTEXT_METHOD_NAME,
Type.getMethodDescriptor(languageVersionSettings.coroutineContextAsmType())
)
areturn(languageVersionSettings.coroutineContextAsmType())
}
@Suppress("UNCHECKED_CAST") @Suppress("UNCHECKED_CAST")
fun <D : CallableDescriptor?> D.unwrapInitialDescriptorForSuspendFunction(): D = fun <D : CallableDescriptor?> D.unwrapInitialDescriptorForSuspendFunction(): D =
this.safeAs<SimpleFunctionDescriptor>()?.getUserData(INITIAL_DESCRIPTOR_FOR_SUSPEND_FUNCTION) as D ?: this this.safeAs<SimpleFunctionDescriptor>()?.getUserData(INITIAL_DESCRIPTOR_FOR_SUSPEND_FUNCTION) as D ?: this
fun FunctionDescriptor.getOriginalSuspendFunctionView(bindingContext: BindingContext): FunctionDescriptor = fun FunctionDescriptor.getOriginalSuspendFunctionView(bindingContext: BindingContext, isReleaseCoroutines: Boolean): FunctionDescriptor =
if (isSuspend) if (isSuspend)
getOrCreateJvmSuspendFunctionView(unwrapInitialDescriptorForSuspendFunction().original, bindingContext) getOrCreateJvmSuspendFunctionView(unwrapInitialDescriptorForSuspendFunction().original, isReleaseCoroutines, bindingContext)
else else
this this
fun InstructionAdapter.loadCoroutineSuspendedMarker() { fun FunctionDescriptor.getOriginalSuspendFunctionView(bindingContext: BindingContext, state: GenerationState) =
getOriginalSuspendFunctionView(bindingContext, state.languageVersionSettings.supportsFeature(LanguageFeature.ReleaseCoroutines))
fun InstructionAdapter.loadCoroutineSuspendedMarker(languageVersionSettings: LanguageVersionSettings) {
invokestatic( invokestatic(
COROUTINES_INTRINSICS_FILE_FACADE_INTERNAL_NAME.internalName, languageVersionSettings.coroutinesIntrinsicsFileFacadeInternalName().internalName,
"get$COROUTINE_SUSPENDED_NAME", "get$COROUTINE_SUSPENDED_NAME",
Type.getMethodDescriptor(AsmTypes.OBJECT_TYPE), Type.getMethodDescriptor(AsmTypes.OBJECT_TYPE),
false false
@@ -1,17 +1,6 @@
/* /*
* Copyright 2010-2016 JetBrains s.r.o. * 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.
* 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.
*/ */
package org.jetbrains.kotlin.codegen.inline package org.jetbrains.kotlin.codegen.inline
@@ -20,10 +9,10 @@ import com.intellij.util.ArrayUtil
import org.jetbrains.kotlin.codegen.AsmUtil import org.jetbrains.kotlin.codegen.AsmUtil
import org.jetbrains.kotlin.codegen.ClassBuilder import org.jetbrains.kotlin.codegen.ClassBuilder
import org.jetbrains.kotlin.codegen.StackValue import org.jetbrains.kotlin.codegen.StackValue
import org.jetbrains.kotlin.codegen.coroutines.COROUTINE_IMPL_ASM_TYPE
import org.jetbrains.kotlin.codegen.coroutines.CoroutineTransformerMethodVisitor import org.jetbrains.kotlin.codegen.coroutines.CoroutineTransformerMethodVisitor
import org.jetbrains.kotlin.codegen.optimization.common.asSequence import org.jetbrains.kotlin.codegen.optimization.common.asSequence
import org.jetbrains.kotlin.codegen.serialization.JvmCodegenStringTable import org.jetbrains.kotlin.codegen.serialization.JvmCodegenStringTable
import org.jetbrains.kotlin.codegen.coroutines.coroutineImplAsmType
import org.jetbrains.kotlin.codegen.writeKotlinMetadata import org.jetbrains.kotlin.codegen.writeKotlinMetadata
import org.jetbrains.kotlin.load.java.JvmAnnotationNames import org.jetbrains.kotlin.load.java.JvmAnnotationNames
import org.jetbrains.kotlin.load.kotlin.FileBasedKotlinClass import org.jetbrains.kotlin.load.kotlin.FileBasedKotlinClass
@@ -55,6 +44,7 @@ class AnonymousObjectTransformer(
private var sourceInfo: String? = null private var sourceInfo: String? = null
private var debugInfo: String? = null private var debugInfo: String? = null
private lateinit var sourceMapper: SourceMapper private lateinit var sourceMapper: SourceMapper
private val languageVersionSettings = inliningContext.state.languageVersionSettings
override fun doTransform(parentRemapper: FieldRemapper): InlineResult { override fun doTransform(parentRemapper: FieldRemapper): InlineResult {
val innerClassNodes = ArrayList<InnerClassNode>() val innerClassNodes = ArrayList<InnerClassNode>()
@@ -65,7 +55,7 @@ class AnonymousObjectTransformer(
createClassReader().accept(object : ClassVisitor(API, classBuilder.visitor) { createClassReader().accept(object : ClassVisitor(API, classBuilder.visitor) {
override fun visit(version: Int, access: Int, name: String, signature: String?, superName: String, interfaces: Array<String>) { override fun visit(version: Int, access: Int, name: String, signature: String?, superName: String, interfaces: Array<String>) {
classBuilder.defineClass(null, version, access, name, signature, superName, interfaces) classBuilder.defineClass(null, version, access, name, signature, superName, interfaces)
if (COROUTINE_IMPL_ASM_TYPE.internalName == superName) { if (languageVersionSettings.coroutineImplAsmType().internalName == superName) {
inliningContext.isContinuation = true inliningContext.isContinuation = true
} }
} }
@@ -454,6 +444,7 @@ class AnonymousObjectTransformer(
), original.access, original.name, original.desc, null, null, ), original.access, original.name, original.desc, null, null,
obtainClassBuilderForCoroutineState = { builder }, obtainClassBuilderForCoroutineState = { builder },
lineNumber = 0, // <- TODO lineNumber = 0, // <- TODO
languageVersionSettings = languageVersionSettings,
shouldPreserveClassInitialization = state.constructorCallNormalizationMode.shouldPreserveClassInitialization, shouldPreserveClassInitialization = state.constructorCallNormalizationMode.shouldPreserveClassInitialization,
containingClassInternalName = builder.thisName, containingClassInternalName = builder.thisName,
isForNamedFunction = false isForNamedFunction = false
@@ -480,6 +471,7 @@ class AnonymousObjectTransformer(
), original.access, original.name, original.desc, null, null, ), original.access, original.name, original.desc, null, null,
obtainClassBuilderForCoroutineState = { (inliningContext as RegeneratedClassContext).continuationBuilders[continuationClassName]!! }, obtainClassBuilderForCoroutineState = { (inliningContext as RegeneratedClassContext).continuationBuilders[continuationClassName]!! },
lineNumber = 0, // <- TODO lineNumber = 0, // <- TODO
languageVersionSettings = languageVersionSettings,
shouldPreserveClassInitialization = state.constructorCallNormalizationMode.shouldPreserveClassInitialization, shouldPreserveClassInitialization = state.constructorCallNormalizationMode.shouldPreserveClassInitialization,
containingClassInternalName = builder.thisName, containingClassInternalName = builder.thisName,
isForNamedFunction = true, isForNamedFunction = true,
@@ -1,5 +1,5 @@
/* /*
* Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 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. * that can be found in the license/LICENSE.txt file.
*/ */
@@ -460,6 +460,7 @@ abstract class InlineCodegen<out T: BaseExpressionCodegen>(
state: GenerationState, state: GenerationState,
sourceCompilerForInline: SourceCompilerForInline sourceCompilerForInline: SourceCompilerForInline
): SMAPAndMethodNode { ): SMAPAndMethodNode {
val languageVersionSettings = state.languageVersionSettings
when { when {
isSpecialEnumMethod(functionDescriptor) -> { isSpecialEnumMethod(functionDescriptor) -> {
val node = createSpecialEnumMethodBody( val node = createSpecialEnumMethodBody(
@@ -469,25 +470,29 @@ abstract class InlineCodegen<out T: BaseExpressionCodegen>(
) )
return SMAPAndMethodNode(node, SMAPParser.parseOrCreateDefault(null, null, "fake", -1, -1)) return SMAPAndMethodNode(node, SMAPParser.parseOrCreateDefault(null, null, "fake", -1, -1))
} }
functionDescriptor.isBuiltInSuspendCoroutineOrReturnInJvm() -> functionDescriptor.isBuiltInSuspendCoroutineOrReturnInJvm(languageVersionSettings) ->
return SMAPAndMethodNode( return SMAPAndMethodNode(
createMethodNodeForSuspendCoroutineOrReturn(functionDescriptor, state.typeMapper), createMethodNodeForSuspendCoroutineOrReturn(functionDescriptor, state.typeMapper, languageVersionSettings),
SMAPParser.parseOrCreateDefault(null, null, "fake", -1, -1) SMAPParser.parseOrCreateDefault(null, null, "fake", -1, -1)
) )
functionDescriptor.isBuiltInIntercepted() -> functionDescriptor.isBuiltInIntercepted(languageVersionSettings) ->
return SMAPAndMethodNode( return SMAPAndMethodNode(
createMethodNodeForIntercepted(functionDescriptor, state.typeMapper), createMethodNodeForIntercepted(functionDescriptor, state.typeMapper, languageVersionSettings),
SMAPParser.parseOrCreateDefault(null, null, "fake", -1, -1) SMAPParser.parseOrCreateDefault(null, null, "fake", -1, -1)
) )
functionDescriptor.isBuiltInCoroutineContext() -> functionDescriptor.isBuiltInCoroutineContext(languageVersionSettings) ->
return SMAPAndMethodNode( return SMAPAndMethodNode(
createMethodNodeForCoroutineContext(functionDescriptor), createMethodNodeForCoroutineContext(functionDescriptor, languageVersionSettings),
SMAPParser.parseOrCreateDefault(null, null, "fake", -1, -1) SMAPParser.parseOrCreateDefault(null, null, "fake", -1, -1)
) )
functionDescriptor.isBuiltInSuspendCoroutineUninterceptedOrReturnInJvm() -> functionDescriptor.isBuiltInSuspendCoroutineUninterceptedOrReturnInJvm(languageVersionSettings) ->
return SMAPAndMethodNode( return SMAPAndMethodNode(
createMethodNodeForSuspendCoroutineUninterceptedOrReturn(functionDescriptor, state.typeMapper), createMethodNodeForSuspendCoroutineUninterceptedOrReturn(
SMAPParser.parseOrCreateDefault(null, null, "fake", -1, -1) functionDescriptor,
state.typeMapper,
languageVersionSettings
),
SMAPParser.parseOrCreateDefault(null, null, "fake", -1, -1)
) )
} }
@@ -10,7 +10,7 @@ import org.jetbrains.kotlin.builtins.isFunctionType
import org.jetbrains.kotlin.codegen.AsmUtil import org.jetbrains.kotlin.codegen.AsmUtil
import org.jetbrains.kotlin.codegen.ClosureCodegen import org.jetbrains.kotlin.codegen.ClosureCodegen
import org.jetbrains.kotlin.codegen.StackValue import org.jetbrains.kotlin.codegen.StackValue
import org.jetbrains.kotlin.codegen.coroutines.CONTINUATION_ASM_TYPE import org.jetbrains.kotlin.codegen.coroutines.continuationAsmType
import org.jetbrains.kotlin.codegen.inline.FieldRemapper.Companion.foldName import org.jetbrains.kotlin.codegen.inline.FieldRemapper.Companion.foldName
import org.jetbrains.kotlin.codegen.intrinsics.IntrinsicMethods import org.jetbrains.kotlin.codegen.intrinsics.IntrinsicMethods
import org.jetbrains.kotlin.codegen.optimization.ApiVersionCallsPreprocessingMethodTransformer import org.jetbrains.kotlin.codegen.optimization.ApiVersionCallsPreprocessingMethodTransformer
@@ -50,6 +50,7 @@ class MethodInliner(
private val shouldPreprocessApiVersionCalls: Boolean = false private val shouldPreprocessApiVersionCalls: Boolean = false
) { ) {
private val typeMapper = inliningContext.state.typeMapper private val typeMapper = inliningContext.state.typeMapper
private val languageVersionSettings = inliningContext.state.languageVersionSettings
private val invokeCalls = ArrayList<InvokeCall>() private val invokeCalls = ArrayList<InvokeCall>()
//keeps order //keeps order
private val transformations = ArrayList<TransformationInfo>() private val transformations = ArrayList<TransformationInfo>()
@@ -292,7 +293,7 @@ class MethodInliner(
} }
val isContinuationCreate = isContinuation && oldInfo != null && resultNode.name == "create" && val isContinuationCreate = isContinuation && oldInfo != null && resultNode.name == "create" &&
resultNode.desc.endsWith(")" + CONTINUATION_ASM_TYPE.descriptor) resultNode.desc.endsWith(")" + languageVersionSettings.continuationAsmType().descriptor)
for (capturedParamDesc in info.allRecapturedParameters) { for (capturedParamDesc in info.allRecapturedParameters) {
if (capturedParamDesc.fieldName == THIS && isContinuationCreate) { if (capturedParamDesc.fieldName == THIS && isContinuationCreate) {
@@ -660,7 +661,7 @@ class MethodInliner(
// We can't have suspending constructors. // We can't have suspending constructors.
assert(invoke.opcode != Opcodes.INVOKESPECIAL) assert(invoke.opcode != Opcodes.INVOKESPECIAL)
if (Type.getReturnType(invoke.desc) != OBJECT_TYPE) return false if (Type.getReturnType(invoke.desc) != OBJECT_TYPE) return false
return Type.getArgumentTypes(invoke.desc).let { it.isNotEmpty() && it.last() == CONTINUATION_ASM_TYPE } return Type.getArgumentTypes(invoke.desc).let { it.isNotEmpty() && it.last() == languageVersionSettings.continuationAsmType() }
} }
private fun preprocessNodeBeforeInline(node: MethodNode, labelOwner: LabelOwner) { private fun preprocessNodeBeforeInline(node: MethodNode, labelOwner: LabelOwner) {
@@ -1,17 +1,6 @@
/* /*
* Copyright 2010-2016 JetBrains s.r.o. * 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.
* 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.
*/ */
package org.jetbrains.kotlin.codegen.serialization; package org.jetbrains.kotlin.codegen.serialization;
@@ -24,6 +13,7 @@ import org.jetbrains.kotlin.codegen.FakeDescriptorsForReferencesKt;
import org.jetbrains.kotlin.codegen.binding.CodegenBinding; import org.jetbrains.kotlin.codegen.binding.CodegenBinding;
import org.jetbrains.kotlin.codegen.state.GenerationState; import org.jetbrains.kotlin.codegen.state.GenerationState;
import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper; import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper;
import org.jetbrains.kotlin.config.LanguageFeature;
import org.jetbrains.kotlin.descriptors.*; import org.jetbrains.kotlin.descriptors.*;
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor; import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor;
import org.jetbrains.kotlin.descriptors.impl.LocalVariableDescriptor; import org.jetbrains.kotlin.descriptors.impl.LocalVariableDescriptor;
@@ -61,6 +51,7 @@ public class JvmSerializerExtension extends SerializerExtension {
private final boolean useTypeTable; private final boolean useTypeTable;
private final String moduleName; private final String moduleName;
private final ClassBuilderMode classBuilderMode; private final ClassBuilderMode classBuilderMode;
private final boolean isReleaseCoroutines;
public JvmSerializerExtension(@NotNull JvmSerializationBindings bindings, @NotNull GenerationState state) { public JvmSerializerExtension(@NotNull JvmSerializationBindings bindings, @NotNull GenerationState state) {
this.bindings = bindings; this.bindings = bindings;
@@ -71,6 +62,7 @@ public class JvmSerializerExtension extends SerializerExtension {
this.useTypeTable = state.getUseTypeTableInSerializer(); this.useTypeTable = state.getUseTypeTableInSerializer();
this.moduleName = state.getModuleName(); this.moduleName = state.getModuleName();
this.classBuilderMode = state.getClassBuilderMode(); this.classBuilderMode = state.getClassBuilderMode();
this.isReleaseCoroutines = state.getLanguageVersionSettings().supportsFeature(LanguageFeature.ReleaseCoroutines);
} }
@NotNull @NotNull
@@ -313,4 +305,9 @@ public class JvmSerializerExtension extends SerializerExtension {
return builder.build(); return builder.build();
} }
} }
@Override
public boolean releaseCoroutines() {
return isReleaseCoroutines;
}
} }
@@ -1,17 +1,6 @@
/* /*
* Copyright 2010-2015 JetBrains s.r.o. * 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.
* 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.
*/ */
package org.jetbrains.kotlin.codegen.signature package org.jetbrains.kotlin.codegen.signature
@@ -28,7 +17,8 @@ class KotlinToJvmSignatureMapperImpl : KotlinToJvmSignatureMapper {
// We use empty BindingContext, because it is only used by KotlinTypeMapper for purposes irrelevant to the needs of this class // We use empty BindingContext, because it is only used by KotlinTypeMapper for purposes irrelevant to the needs of this class
private val typeMapper = KotlinTypeMapper( private val typeMapper = KotlinTypeMapper(
BindingContext.EMPTY, ClassBuilderMode.LIGHT_CLASSES, BindingContext.EMPTY, ClassBuilderMode.LIGHT_CLASSES,
IncompatibleClassTracker.DoNothing, JvmAbi.DEFAULT_MODULE_NAME, false) IncompatibleClassTracker.DoNothing, JvmAbi.DEFAULT_MODULE_NAME, false, KotlinTypeMapper.RELEASE_COROUTINES_DEFAULT
)
override fun mapToJvmMethodSignature(function: FunctionDescriptor) = typeMapper.mapAsmMethod(function) override fun mapToJvmMethodSignature(function: FunctionDescriptor) = typeMapper.mapAsmMethod(function)
} }
@@ -1,17 +1,6 @@
/* /*
* Copyright 2010-2016 JetBrains s.r.o. * 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.
* 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.
*/ */
package org.jetbrains.kotlin.codegen.state package org.jetbrains.kotlin.codegen.state
@@ -53,16 +42,17 @@ private val PREDEFINED_SIGNATURES = listOf(
} }
class BuilderFactoryForDuplicateSignatureDiagnostics( class BuilderFactoryForDuplicateSignatureDiagnostics(
builderFactory: ClassBuilderFactory, builderFactory: ClassBuilderFactory,
bindingContext: BindingContext, bindingContext: BindingContext,
private val diagnostics: DiagnosticSink, private val diagnostics: DiagnosticSink,
moduleName: String, moduleName: String,
shouldGenerate: (JvmDeclarationOrigin) -> Boolean isReleaseCoroutines: Boolean,
shouldGenerate: (JvmDeclarationOrigin) -> Boolean
) : SignatureCollectingClassBuilderFactory(builderFactory, shouldGenerate) { ) : SignatureCollectingClassBuilderFactory(builderFactory, shouldGenerate) {
// Avoid errors when some classes are not loaded for some reason // Avoid errors when some classes are not loaded for some reason
private val typeMapper = KotlinTypeMapper( private val typeMapper = KotlinTypeMapper(
bindingContext, ClassBuilderMode.LIGHT_CLASSES, IncompatibleClassTracker.DoNothing, moduleName, false bindingContext, ClassBuilderMode.LIGHT_CLASSES, IncompatibleClassTracker.DoNothing, moduleName, false, isReleaseCoroutines
) )
private val reportDiagnosticsTasks = ArrayList<() -> Unit>() private val reportDiagnosticsTasks = ArrayList<() -> Unit>()
@@ -1,17 +1,6 @@
/* /*
* Copyright 2010-2015 JetBrains s.r.o. * 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.
* 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.
*/ */
package org.jetbrains.kotlin.codegen.state package org.jetbrains.kotlin.codegen.state
@@ -186,8 +175,12 @@ class GenerationState private constructor(
) )
val bindingContext: BindingContext = bindingTrace.bindingContext val bindingContext: BindingContext = bindingTrace.bindingContext
val typeMapper: KotlinTypeMapper = KotlinTypeMapper( val typeMapper: KotlinTypeMapper = KotlinTypeMapper(
this.bindingContext, classBuilderMode, IncompatibleClassTrackerImpl(extraJvmDiagnosticsTrace), this.bindingContext,
this.moduleName, isJvm8Target classBuilderMode,
IncompatibleClassTrackerImpl(extraJvmDiagnosticsTrace),
this.moduleName,
isJvm8Target,
configuration.languageVersionSettings.supportsFeature(LanguageFeature.ReleaseCoroutines)
) )
val intrinsics: IntrinsicMethods = run { val intrinsics: IntrinsicMethods = run {
val shouldUseConsistentEquals = languageVersionSettings.supportsFeature(LanguageFeature.ThrowNpeOnExplicitEqualsForBoxedNull) && val shouldUseConsistentEquals = languageVersionSettings.supportsFeature(LanguageFeature.ThrowNpeOnExplicitEqualsForBoxedNull) &&
@@ -197,7 +190,7 @@ class GenerationState private constructor(
val samWrapperClasses: SamWrapperClasses = SamWrapperClasses(this) val samWrapperClasses: SamWrapperClasses = SamWrapperClasses(this)
val globalInlineContext: GlobalInlineContext = GlobalInlineContext(diagnostics) val globalInlineContext: GlobalInlineContext = GlobalInlineContext(diagnostics)
val mappingsClassesForWhenByEnum: MappingsClassesForWhenByEnum = MappingsClassesForWhenByEnum(this) val mappingsClassesForWhenByEnum: MappingsClassesForWhenByEnum = MappingsClassesForWhenByEnum(this)
val jvmRuntimeTypes: JvmRuntimeTypes = JvmRuntimeTypes(module) val jvmRuntimeTypes: JvmRuntimeTypes = JvmRuntimeTypes(module, configuration.languageVersionSettings)
val factory: ClassFileFactory val factory: ClassFileFactory
private lateinit var duplicateSignatureFactory: BuilderFactoryForDuplicateSignatureDiagnostics private lateinit var duplicateSignatureFactory: BuilderFactoryForDuplicateSignatureDiagnostics
@@ -242,6 +235,7 @@ class GenerationState private constructor(
{ {
BuilderFactoryForDuplicateSignatureDiagnostics( BuilderFactoryForDuplicateSignatureDiagnostics(
it, this.bindingContext, diagnostics, this.moduleName, it, this.bindingContext, diagnostics, this.moduleName,
isReleaseCoroutines = languageVersionSettings.supportsFeature(LanguageFeature.ReleaseCoroutines),
shouldGenerate = { !shouldOnlyCollectSignatures(it) } shouldGenerate = { !shouldOnlyCollectSignatures(it) }
).apply { duplicateSignatureFactory = this } ).apply { duplicateSignatureFactory = this }
}, },
@@ -1,5 +1,5 @@
/* /*
* Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 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. * that can be found in the license/LICENSE.txt file.
*/ */
@@ -85,6 +85,7 @@ public class KotlinTypeMapper {
private final IncompatibleClassTracker incompatibleClassTracker; private final IncompatibleClassTracker incompatibleClassTracker;
private final String moduleName; private final String moduleName;
private final boolean isJvm8Target; private final boolean isJvm8Target;
private final boolean isReleaseCoroutines;
private final TypeMappingConfiguration<Type> typeMappingConfiguration = new TypeMappingConfiguration<Type>() { private final TypeMappingConfiguration<Type> typeMappingConfiguration = new TypeMappingConfiguration<Type>() {
@NotNull @NotNull
@@ -112,6 +113,11 @@ public class KotlinTypeMapper {
throw new IllegalStateException(generateErrorMessageForErrorType(kotlinType, descriptor)); throw new IllegalStateException(generateErrorMessageForErrorType(kotlinType, descriptor));
} }
} }
@Override
public boolean releaseCoroutines() {
return isReleaseCoroutines;
}
}; };
private static final TypeMappingConfiguration<Type> staticTypeMappingConfiguration = new TypeMappingConfiguration<Type>() { private static final TypeMappingConfiguration<Type> staticTypeMappingConfiguration = new TypeMappingConfiguration<Type>() {
@@ -137,6 +143,11 @@ public class KotlinTypeMapper {
public void processErrorType(@NotNull KotlinType kotlinType, @NotNull ClassDescriptor descriptor) { public void processErrorType(@NotNull KotlinType kotlinType, @NotNull ClassDescriptor descriptor) {
throw new IllegalStateException(generateErrorMessageForErrorType(kotlinType, descriptor)); throw new IllegalStateException(generateErrorMessageForErrorType(kotlinType, descriptor));
} }
@Override
public boolean releaseCoroutines() {
return false;
}
}; };
public KotlinTypeMapper( public KotlinTypeMapper(
@@ -144,15 +155,19 @@ public class KotlinTypeMapper {
@NotNull ClassBuilderMode classBuilderMode, @NotNull ClassBuilderMode classBuilderMode,
@NotNull IncompatibleClassTracker incompatibleClassTracker, @NotNull IncompatibleClassTracker incompatibleClassTracker,
@NotNull String moduleName, @NotNull String moduleName,
boolean isJvm8Target boolean isJvm8Target,
boolean isReleaseCoroutines
) { ) {
this.bindingContext = bindingContext; this.bindingContext = bindingContext;
this.classBuilderMode = classBuilderMode; this.classBuilderMode = classBuilderMode;
this.incompatibleClassTracker = incompatibleClassTracker; this.incompatibleClassTracker = incompatibleClassTracker;
this.moduleName = moduleName; this.moduleName = moduleName;
this.isJvm8Target = isJvm8Target; this.isJvm8Target = isJvm8Target;
this.isReleaseCoroutines = isReleaseCoroutines;
} }
public static final boolean RELEASE_COROUTINES_DEFAULT = false;
@NotNull @NotNull
public BindingContext getBindingContext() { public BindingContext getBindingContext() {
return bindingContext; return bindingContext;
@@ -363,7 +378,9 @@ public class KotlinTypeMapper {
} }
if (CoroutineCodegenUtilKt.isSuspendFunctionNotSuspensionView(descriptor)) { if (CoroutineCodegenUtilKt.isSuspendFunctionNotSuspensionView(descriptor)) {
return mapReturnType(CoroutineCodegenUtilKt.getOrCreateJvmSuspendFunctionView((SimpleFunctionDescriptor) descriptor), sw); return mapReturnType(
CoroutineCodegenUtilKt.getOrCreateJvmSuspendFunctionView((SimpleFunctionDescriptor) descriptor, isReleaseCoroutines),
sw);
} }
if (TypeSignatureMappingKt.hasVoidReturnType(descriptor)) { if (TypeSignatureMappingKt.hasVoidReturnType(descriptor)) {
@@ -1129,7 +1146,8 @@ public class KotlinTypeMapper {
} }
if (CoroutineCodegenUtilKt.isSuspendFunctionNotSuspensionView(f)) { if (CoroutineCodegenUtilKt.isSuspendFunctionNotSuspensionView(f)) {
return mapSignature(CoroutineCodegenUtilKt.getOrCreateJvmSuspendFunctionView(f), kind, skipGenericSignature); return mapSignature(CoroutineCodegenUtilKt.getOrCreateJvmSuspendFunctionView(f, isReleaseCoroutines), kind,
skipGenericSignature);
} }
return mapSignatureWithCustomParameters(f, kind, f.getValueParameters(), skipGenericSignature, hasSpecialBridge); return mapSignatureWithCustomParameters(f, kind, f.getValueParameters(), skipGenericSignature, hasSpecialBridge);
@@ -1,17 +1,6 @@
/* /*
* Copyright 2010-2016 JetBrains s.r.o. * 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.
* 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.
*/ */
package org.jetbrains.kotlin.resolve package org.jetbrains.kotlin.resolve
@@ -32,4 +21,6 @@ class CompilerDeserializationConfiguration(languageVersionSettings: LanguageVers
override val isJvmPackageNameSupported = languageVersionSettings.supportsFeature(LanguageFeature.JvmPackageName) override val isJvmPackageNameSupported = languageVersionSettings.supportsFeature(LanguageFeature.JvmPackageName)
override val readDeserializedContracts: Boolean = languageVersionSettings.supportsFeature(LanguageFeature.ReadDeserializedContracts) override val readDeserializedContracts: Boolean = languageVersionSettings.supportsFeature(LanguageFeature.ReadDeserializedContracts)
override val releaseCoroutines: Boolean = languageVersionSettings.supportsFeature(LanguageFeature.ReleaseCoroutines)
} }
@@ -1,17 +1,6 @@
/* /*
* Copyright 2010-2016 JetBrains s.r.o. * 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.
* 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.
*/ */
package org.jetbrains.kotlin.resolve.calls.checkers package org.jetbrains.kotlin.resolve.calls.checkers
@@ -19,6 +8,8 @@ package org.jetbrains.kotlin.resolve.calls.checkers
import com.intellij.psi.PsiElement import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.config.LanguageFeature import org.jetbrains.kotlin.config.LanguageFeature
import org.jetbrains.kotlin.config.LanguageVersionSettings import org.jetbrains.kotlin.config.LanguageVersionSettings
import org.jetbrains.kotlin.config.restrictsSuspensionFqName
import org.jetbrains.kotlin.config.isBuiltInCoroutineContext
import org.jetbrains.kotlin.coroutines.hasSuspendFunctionType import org.jetbrains.kotlin.coroutines.hasSuspendFunctionType
import org.jetbrains.kotlin.descriptors.CallableDescriptor import org.jetbrains.kotlin.descriptors.CallableDescriptor
import org.jetbrains.kotlin.descriptors.FunctionDescriptor import org.jetbrains.kotlin.descriptors.FunctionDescriptor
@@ -26,7 +17,6 @@ import org.jetbrains.kotlin.descriptors.PropertyDescriptor
import org.jetbrains.kotlin.descriptors.PropertyGetterDescriptor import org.jetbrains.kotlin.descriptors.PropertyGetterDescriptor
import org.jetbrains.kotlin.diagnostics.DiagnosticSink import org.jetbrains.kotlin.diagnostics.DiagnosticSink
import org.jetbrains.kotlin.diagnostics.Errors import org.jetbrains.kotlin.diagnostics.Errors
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.psi.KtExpression import org.jetbrains.kotlin.psi.KtExpression
import org.jetbrains.kotlin.psi.KtThisExpression import org.jetbrains.kotlin.psi.KtThisExpression
@@ -34,7 +24,6 @@ import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.DescriptorUtils import org.jetbrains.kotlin.resolve.DescriptorUtils
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe
import org.jetbrains.kotlin.resolve.descriptorUtil.hasRestrictsSuspensionAnnotation
import org.jetbrains.kotlin.resolve.inline.InlineUtil import org.jetbrains.kotlin.resolve.inline.InlineUtil
import org.jetbrains.kotlin.resolve.scopes.HierarchicalScope import org.jetbrains.kotlin.resolve.scopes.HierarchicalScope
import org.jetbrains.kotlin.resolve.scopes.LexicalScope import org.jetbrains.kotlin.resolve.scopes.LexicalScope
@@ -46,16 +35,14 @@ import org.jetbrains.kotlin.types.typeUtil.supertypes
import org.jetbrains.kotlin.utils.addToStdlib.cast import org.jetbrains.kotlin.utils.addToStdlib.cast
import org.jetbrains.kotlin.utils.addToStdlib.safeAs import org.jetbrains.kotlin.utils.addToStdlib.safeAs
val COROUTINE_CONTEXT_1_2_20_FQ_NAME = DescriptorUtils.COROUTINES_INTRINSICS_PACKAGE_FQ_NAME.child(Name.identifier("coroutineContext")) val COROUTINE_CONTEXT_1_2_20_FQ_NAME =
val COROUTINE_CONTEXT_FQ_NAME = DescriptorUtils.COROUTINES_PACKAGE_FQ_NAME.child(Name.identifier("coroutineContext")) DescriptorUtils.COROUTINES_INTRINSICS_PACKAGE_FQ_NAME_EXPERIMENTAL.child(Name.identifier("coroutineContext"))
fun FqName.isBuiltInCorouineContext() = fun FunctionDescriptor.isBuiltInCoroutineContext(languageVersionSettings: LanguageVersionSettings) =
this == COROUTINE_CONTEXT_1_2_20_FQ_NAME || this == COROUTINE_CONTEXT_FQ_NAME (this as? PropertyGetterDescriptor)?.correspondingProperty?.fqNameSafe?.isBuiltInCoroutineContext(languageVersionSettings) == true
fun FunctionDescriptor.isBuiltInCoroutineContext() = fun PropertyDescriptor.isBuiltInCoroutineContext(languageVersionSettings: LanguageVersionSettings) =
(this as? PropertyGetterDescriptor)?.correspondingProperty?.fqNameSafe?.isBuiltInCorouineContext() == true this.fqNameSafe.isBuiltInCoroutineContext(languageVersionSettings)
fun PropertyDescriptor.isBuiltInCoroutineContext() = this.fqNameSafe.isBuiltInCorouineContext()
object CoroutineSuspendCallChecker : CallChecker { object CoroutineSuspendCallChecker : CallChecker {
private val ALLOWED_SCOPE_KINDS = setOf(LexicalScopeKind.FUNCTION_INNER_SCOPE, LexicalScopeKind.FUNCTION_HEADER_FOR_DESTRUCTURING) private val ALLOWED_SCOPE_KINDS = setOf(LexicalScopeKind.FUNCTION_INNER_SCOPE, LexicalScopeKind.FUNCTION_HEADER_FOR_DESTRUCTURING)
@@ -64,10 +51,8 @@ object CoroutineSuspendCallChecker : CallChecker {
val descriptor = resolvedCall.candidateDescriptor val descriptor = resolvedCall.candidateDescriptor
when (descriptor) { when (descriptor) {
is FunctionDescriptor -> if (!descriptor.isSuspend) return is FunctionDescriptor -> if (!descriptor.isSuspend) return
is PropertyDescriptor -> when (descriptor.fqNameSafe) { is PropertyDescriptor ->
COROUTINE_CONTEXT_1_2_20_FQ_NAME, COROUTINE_CONTEXT_FQ_NAME -> {} if (descriptor.fqNameSafe != COROUTINE_CONTEXT_1_2_20_FQ_NAME && !descriptor.isBuiltInCoroutineContext(context.languageVersionSettings)) return
else -> return
}
else -> return else -> return
} }
@@ -153,7 +138,7 @@ private fun checkRestrictsSuspension(
val enclosingSuspendReceiverValue = enclosingCallableDescriptor.extensionReceiverParameter?.value ?: return val enclosingSuspendReceiverValue = enclosingCallableDescriptor.extensionReceiverParameter?.value ?: return
fun ReceiverValue.isRestrictsSuspensionReceiver() = (type.supertypes() + type).any { fun ReceiverValue.isRestrictsSuspensionReceiver() = (type.supertypes() + type).any {
it.constructor.declarationDescriptor?.hasRestrictsSuspensionAnnotation() == true it.constructor.declarationDescriptor?.annotations?.hasAnnotation(context.languageVersionSettings.restrictsSuspensionFqName()) == true
} }
infix fun ReceiverValue.sameInstance(other: ReceiverValue?): Boolean { infix fun ReceiverValue.sameInstance(other: ReceiverValue?): Boolean {
@@ -1,5 +1,5 @@
/* /*
* Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 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. * that can be found in the license/LICENSE.txt file.
*/ */
@@ -502,7 +502,7 @@ class DescriptorSerializer private constructor(
} }
if (type.isSuspendFunctionType) { if (type.isSuspendFunctionType) {
val functionType = type(transformSuspendFunctionToRuntimeFunctionType(type)) val functionType = type(transformSuspendFunctionToRuntimeFunctionType(type, extension.releaseCoroutines()))
functionType.flags = Flags.getTypeFlags(true) functionType.flags = Flags.getTypeFlags(true)
return functionType return functionType
} }
@@ -1,17 +1,6 @@
/* /*
* Copyright 2010-2016 JetBrains s.r.o. * 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.
* 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.
*/ */
package org.jetbrains.kotlin.serialization package org.jetbrains.kotlin.serialization
@@ -71,4 +60,6 @@ abstract class SerializerExtension {
open fun serializeErrorType(type: KotlinType, builder: ProtoBuf.Type.Builder) { open fun serializeErrorType(type: KotlinType, builder: ProtoBuf.Type.Builder) {
throw IllegalStateException("Cannot serialize error type: $type") throw IllegalStateException("Cannot serialize error type: $type")
} }
open fun releaseCoroutines(): Boolean = false
} }
@@ -0,0 +1,10 @@
// !API_VERSION: 1.3
suspend fun named() {}
suspend fun withStateMachine() {
named()
named()
}
val l: suspend() -> Unit = {}
@@ -0,0 +1,30 @@
@kotlin.Metadata
final class ReleaseCoroutinesKt$l$1 {
inner class ReleaseCoroutinesKt$l$1
method <init>(p0: kotlin.coroutines.Continuation): void
public final @org.jetbrains.annotations.Nullable method create(@org.jetbrains.annotations.Nullable p0: java.lang.Object): java.lang.Object
public final @org.jetbrains.annotations.Nullable method doResume(@org.jetbrains.annotations.Nullable p0: java.lang.Object, @org.jetbrains.annotations.Nullable p1: java.lang.Throwable): java.lang.Object
public final @org.jetbrains.annotations.Nullable method invoke(@org.jetbrains.annotations.Nullable p0: java.lang.Object): java.lang.Object
}
@kotlin.Metadata
final class ReleaseCoroutinesKt$withStateMachine$1 {
synthetic field data: java.lang.Object
synthetic field exception: java.lang.Throwable
inner class ReleaseCoroutinesKt$withStateMachine$1
method <init>(p0: kotlin.coroutines.Continuation): void
public final @org.jetbrains.annotations.Nullable method doResume(@org.jetbrains.annotations.Nullable p0: java.lang.Object, @org.jetbrains.annotations.Nullable p1: java.lang.Throwable): java.lang.Object
synthetic final method getLabel(): int
synthetic final method setLabel(p0: int): void
}
@kotlin.Metadata
public final class ReleaseCoroutinesKt {
private final static @org.jetbrains.annotations.NotNull field l: kotlin.jvm.functions.Function1
inner class ReleaseCoroutinesKt$l$1
inner class ReleaseCoroutinesKt$withStateMachine$1
static method <clinit>(): void
public final static @org.jetbrains.annotations.NotNull method getL(): kotlin.jvm.functions.Function1
public final static @org.jetbrains.annotations.Nullable method named(@org.jetbrains.annotations.Nullable p0: java.lang.Object): java.lang.Object
public final static @org.jetbrains.annotations.Nullable method withStateMachine(@org.jetbrains.annotations.Nullable p0: java.lang.Object): java.lang.Object
}
@@ -151,6 +151,12 @@ public class BytecodeListingTestGenerated extends AbstractBytecodeListingTest {
doTest(fileName); doTest(fileName);
} }
@TestMetadata("releaseCoroutines.kt")
public void testReleaseCoroutines() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/bytecodeListing/releaseCoroutines.kt");
doTest(fileName);
}
@TestMetadata("samAdapterAndInlinedOne.kt") @TestMetadata("samAdapterAndInlinedOne.kt")
public void testSamAdapterAndInlinedOne() throws Exception { public void testSamAdapterAndInlinedOne() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/bytecodeListing/samAdapterAndInlinedOne.kt"); String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/bytecodeListing/samAdapterAndInlinedOne.kt");
@@ -0,0 +1,37 @@
/*
* 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.config
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.resolve.DescriptorUtils
fun LanguageVersionSettings.coroutinesPackageFqName(): FqName {
return coroutinesPackageFqName(supportsFeature(LanguageFeature.ReleaseCoroutines))
}
private fun coroutinesPackageFqName(isReleaseCoroutines: Boolean): FqName {
return if (isReleaseCoroutines)
DescriptorUtils.COROUTINES_PACKAGE_FQ_NAME_RELEASE
else
DescriptorUtils.COROUTINES_PACKAGE_FQ_NAME_EXPERIMENTAL
}
fun LanguageVersionSettings.coroutinesIntrinsicsPackageFqName() =
coroutinesPackageFqName().child(Name.identifier("intrinsics"))
fun LanguageVersionSettings.continuationInterfaceFqName() =
coroutinesPackageFqName().child(Name.identifier("Continuation"))
fun LanguageVersionSettings.restrictsSuspensionFqName() =
coroutinesPackageFqName().child(Name.identifier("RestrictsSuspension"))
fun FqName.isBuiltInCoroutineContext(languageVersionSettings: LanguageVersionSettings) =
if (languageVersionSettings.supportsFeature(LanguageFeature.ReleaseCoroutines))
this == DescriptorUtils.COROUTINES_PACKAGE_FQ_NAME_RELEASE.child(Name.identifier("coroutineContext"))
else
this == DescriptorUtils.COROUTINES_PACKAGE_FQ_NAME_EXPERIMENTAL.child(Name.identifier("coroutineContext")) ||
this == DescriptorUtils.COROUTINES_INTRINSICS_PACKAGE_FQ_NAME_EXPERIMENTAL.child(Name.identifier("coroutineContext"))
@@ -1,5 +1,5 @@
/* /*
* Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 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. * that can be found in the license/LICENSE.txt file.
*/ */
@@ -68,6 +68,7 @@ enum class LanguageFeature(
InlineClasses(KOTLIN_1_3), InlineClasses(KOTLIN_1_3),
ProhibitVisibilityOfNestedClassifiersFromSupertypesOfCompanion(KOTLIN_1_3), ProhibitVisibilityOfNestedClassifiersFromSupertypesOfCompanion(KOTLIN_1_3),
ProhibitNonConstValuesAsVarargsInAnnotations(KOTLIN_1_3), ProhibitNonConstValuesAsVarargsInAnnotations(KOTLIN_1_3),
ReleaseCoroutines(KOTLIN_1_3),
ReadDeserializedContracts(KOTLIN_1_3), ReadDeserializedContracts(KOTLIN_1_3),
UseReturnsEffect(KOTLIN_1_3), UseReturnsEffect(KOTLIN_1_3),
UseCallsInPlaceEffect(KOTLIN_1_3), UseCallsInPlaceEffect(KOTLIN_1_3),
@@ -1,17 +1,6 @@
/* /*
* Copyright 2010-2016 JetBrains s.r.o. * 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.
* 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.
*/ */
package org.jetbrains.kotlin.load.kotlin package org.jetbrains.kotlin.load.kotlin
@@ -166,4 +155,6 @@ internal object TypeMappingConfigurationImpl : TypeMappingConfiguration<JvmType>
override fun processErrorType(kotlinType: KotlinType, descriptor: ClassDescriptor) { override fun processErrorType(kotlinType: KotlinType, descriptor: ClassDescriptor) {
// DO nothing // DO nothing
} }
override fun releaseCoroutines() = false
} }
@@ -1,14 +1,11 @@
/* /*
* Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 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. * that can be found in the license/LICENSE.txt file.
*/ */
package org.jetbrains.kotlin.load.kotlin package org.jetbrains.kotlin.load.kotlin
import org.jetbrains.kotlin.builtins.FAKE_CONTINUATION_CLASS_DESCRIPTOR import org.jetbrains.kotlin.builtins.*
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.builtins.isSuspendFunctionType
import org.jetbrains.kotlin.builtins.transformSuspendFunctionToRuntimeFunctionType
import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.load.java.typeEnhancement.hasEnhancedNullability import org.jetbrains.kotlin.load.java.typeEnhancement.hasEnhancedNullability
import org.jetbrains.kotlin.name.ClassId import org.jetbrains.kotlin.name.ClassId
@@ -43,13 +40,11 @@ interface TypeMappingConfiguration<out T : Any> {
fun getPredefinedTypeForClass(classDescriptor: ClassDescriptor): T? fun getPredefinedTypeForClass(classDescriptor: ClassDescriptor): T?
fun getPredefinedInternalNameForClass(classDescriptor: ClassDescriptor): String? fun getPredefinedInternalNameForClass(classDescriptor: ClassDescriptor): String?
fun processErrorType(kotlinType: KotlinType, descriptor: ClassDescriptor) fun processErrorType(kotlinType: KotlinType, descriptor: ClassDescriptor)
fun releaseCoroutines(): Boolean
} }
const val NON_EXISTENT_CLASS_NAME = "error/NonExistentClass" const val NON_EXISTENT_CLASS_NAME = "error/NonExistentClass"
private val CONTINUATION_INTERNAL_NAME =
JvmClassName.byClassId(ClassId.topLevel(DescriptorUtils.CONTINUATION_INTERFACE_FQ_NAME)).internalName
fun <T : Any> mapType( fun <T : Any> mapType(
kotlinType: KotlinType, kotlinType: KotlinType,
factory: JvmTypeFactory<T>, factory: JvmTypeFactory<T>,
@@ -60,7 +55,7 @@ fun <T : Any> mapType(
): T { ): T {
if (kotlinType.isSuspendFunctionType) { if (kotlinType.isSuspendFunctionType) {
return mapType( return mapType(
transformSuspendFunctionToRuntimeFunctionType(kotlinType), transformSuspendFunctionToRuntimeFunctionType(kotlinType, typeMappingConfiguration.releaseCoroutines()),
factory, mode, typeMappingConfiguration, descriptorTypeWriter, factory, mode, typeMappingConfiguration, descriptorTypeWriter,
writeGenericType writeGenericType
) )
@@ -178,12 +173,24 @@ fun hasVoidReturnType(descriptor: CallableDescriptor): Boolean {
&& descriptor !is PropertyGetterDescriptor && descriptor !is PropertyGetterDescriptor
} }
private fun <T : Any> mapBuiltInType(type: KotlinType, typeFactory: JvmTypeFactory<T>, mode: TypeMappingMode): T? { private fun continuationInternalName(releaseCoroutines: Boolean): String {
val fqName =
if (releaseCoroutines) DescriptorUtils.CONTINUATION_INTERFACE_FQ_NAME_RELEASE
else DescriptorUtils.CONTINUATION_INTERFACE_FQ_NAME_EXPERIMENTAL
return JvmClassName.byClassId(ClassId.topLevel(fqName)).internalName
}
private fun <T : Any> mapBuiltInType(
type: KotlinType,
typeFactory: JvmTypeFactory<T>,
mode: TypeMappingMode
): T? {
val descriptor = type.constructor.declarationDescriptor as? ClassDescriptor ?: return null val descriptor = type.constructor.declarationDescriptor as? ClassDescriptor ?: return null
if (descriptor === FAKE_CONTINUATION_CLASS_DESCRIPTOR) { if (descriptor === FAKE_CONTINUATION_CLASS_DESCRIPTOR_EXPERIMENTAL) {
return typeFactory.createObjectType(continuationInternalName(false))
return typeFactory.createObjectType(CONTINUATION_INTERNAL_NAME) } else if (descriptor == FAKE_CONTINUATION_CLASS_DESCRIPTOR_RELEASE) {
return typeFactory.createObjectType(continuationInternalName(true))
} }
val primitiveType = KotlinBuiltIns.getPrimitiveType(descriptor) val primitiveType = KotlinBuiltIns.getPrimitiveType(descriptor)
@@ -1,17 +1,6 @@
/* /*
* Copyright 2010-2017 JetBrains s.r.o. * 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.
* 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.
*/ */
package org.jetbrains.kotlin.builtins package org.jetbrains.kotlin.builtins
@@ -24,6 +13,7 @@ import org.jetbrains.kotlin.descriptors.annotations.Annotations
import org.jetbrains.kotlin.descriptors.impl.EmptyPackageFragmentDescriptor import org.jetbrains.kotlin.descriptors.impl.EmptyPackageFragmentDescriptor
import org.jetbrains.kotlin.descriptors.impl.MutableClassDescriptor import org.jetbrains.kotlin.descriptors.impl.MutableClassDescriptor
import org.jetbrains.kotlin.descriptors.impl.TypeParameterDescriptorImpl import org.jetbrains.kotlin.descriptors.impl.TypeParameterDescriptorImpl
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.resolve.DescriptorUtils import org.jetbrains.kotlin.resolve.DescriptorUtils
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe
@@ -31,25 +21,40 @@ import org.jetbrains.kotlin.types.*
import org.jetbrains.kotlin.types.typeUtil.asTypeProjection import org.jetbrains.kotlin.types.typeUtil.asTypeProjection
import org.jetbrains.kotlin.types.typeUtil.builtIns import org.jetbrains.kotlin.types.typeUtil.builtIns
val FAKE_CONTINUATION_CLASS_DESCRIPTOR_EXPERIMENTAL =
MutableClassDescriptor(
EmptyPackageFragmentDescriptor(ErrorUtils.getErrorModule(), DescriptorUtils.COROUTINES_PACKAGE_FQ_NAME_EXPERIMENTAL),
ClassKind.INTERFACE, /* isInner = */ false, /* isExternal = */ false,
DescriptorUtils.CONTINUATION_INTERFACE_FQ_NAME_EXPERIMENTAL.shortName(), SourceElement.NO_SOURCE
).apply {
modality = Modality.ABSTRACT
visibility = Visibilities.PUBLIC
setTypeParameterDescriptors(
TypeParameterDescriptorImpl.createWithDefaultBound(
this, Annotations.EMPTY, false, Variance.IN_VARIANCE, Name.identifier("T"), 0
).let(::listOf)
)
createTypeConstructor()
}
val FAKE_CONTINUATION_CLASS_DESCRIPTOR = val FAKE_CONTINUATION_CLASS_DESCRIPTOR_RELEASE =
MutableClassDescriptor( MutableClassDescriptor(
EmptyPackageFragmentDescriptor(ErrorUtils.getErrorModule(), DescriptorUtils.COROUTINES_PACKAGE_FQ_NAME), EmptyPackageFragmentDescriptor(ErrorUtils.getErrorModule(), DescriptorUtils.COROUTINES_PACKAGE_FQ_NAME_RELEASE),
ClassKind.INTERFACE, /* isInner = */ false, /* isExternal = */ false, ClassKind.INTERFACE, /* isInner = */ false, /* isExternal = */ false,
DescriptorUtils.CONTINUATION_INTERFACE_FQ_NAME.shortName(), SourceElement.NO_SOURCE DescriptorUtils.CONTINUATION_INTERFACE_FQ_NAME_RELEASE.shortName(), SourceElement.NO_SOURCE
).apply { ).apply {
modality = Modality.ABSTRACT modality = Modality.ABSTRACT
visibility = Visibilities.PUBLIC visibility = Visibilities.PUBLIC
setTypeParameterDescriptors( setTypeParameterDescriptors(
TypeParameterDescriptorImpl.createWithDefaultBound( TypeParameterDescriptorImpl.createWithDefaultBound(
this, Annotations.EMPTY, false, Variance.IN_VARIANCE, Name.identifier("T"), 0 this, Annotations.EMPTY, false, Variance.IN_VARIANCE, Name.identifier("T"), 0
).let(::listOf) ).let(::listOf)
) )
createTypeConstructor() createTypeConstructor()
} }
fun transformSuspendFunctionToRuntimeFunctionType(suspendFunType: KotlinType): SimpleType { fun transformSuspendFunctionToRuntimeFunctionType(suspendFunType: KotlinType, isReleaseCoroutines: Boolean): SimpleType {
assert(suspendFunType.isSuspendFunctionType) { assert(suspendFunType.isSuspendFunctionType) {
"This type should be suspend function type: $suspendFunType" "This type should be suspend function type: $suspendFunType"
} }
@@ -64,7 +69,8 @@ fun transformSuspendFunctionToRuntimeFunctionType(suspendFunType: KotlinType): S
// Continuation interface is not a part of built-ins anymore, it has been moved to stdlib. // Continuation interface is not a part of built-ins anymore, it has been moved to stdlib.
// While it must be somewhere in the dependencies, but here we don't have a reference to the module, // While it must be somewhere in the dependencies, but here we don't have a reference to the module,
// and it's rather complicated to inject it by now, so we just use a fake class descriptor. // and it's rather complicated to inject it by now, so we just use a fake class descriptor.
FAKE_CONTINUATION_CLASS_DESCRIPTOR.typeConstructor, if (isReleaseCoroutines) FAKE_CONTINUATION_CLASS_DESCRIPTOR_RELEASE.typeConstructor
else FAKE_CONTINUATION_CLASS_DESCRIPTOR_EXPERIMENTAL.typeConstructor,
listOf(suspendFunType.getReturnTypeFromFunctionType().asTypeProjection()), nullable = false listOf(suspendFunType.getReturnTypeFromFunctionType().asTypeProjection()), nullable = false
), ),
// TODO: names // TODO: names
@@ -73,14 +79,14 @@ fun transformSuspendFunctionToRuntimeFunctionType(suspendFunType: KotlinType): S
).makeNullableAsSpecified(suspendFunType.isMarkedNullable) ).makeNullableAsSpecified(suspendFunType.isMarkedNullable)
} }
fun transformRuntimeFunctionTypeToSuspendFunction(funType: KotlinType): SimpleType? { fun transformRuntimeFunctionTypeToSuspendFunction(funType: KotlinType, isReleaseCoroutines: Boolean): SimpleType? {
assert(funType.isFunctionType) { assert(funType.isFunctionType) {
"This type should be function type: $funType" "This type should be function type: $funType"
} }
val continuationArgumentType = funType.getValueParameterTypesFromFunctionType().lastOrNull()?.type ?: return null val continuationArgumentType = funType.getValueParameterTypesFromFunctionType().lastOrNull()?.type ?: return null
if (continuationArgumentType.constructor.declarationDescriptor?.fqNameSafe != DescriptorUtils.CONTINUATION_INTERFACE_FQ_NAME if (!isContinuation(continuationArgumentType.constructor.declarationDescriptor?.fqNameSafe, isReleaseCoroutines) ||
|| continuationArgumentType.arguments.size != 1 continuationArgumentType.arguments.size != 1
) { ) {
return null return null
} }
@@ -98,3 +104,8 @@ fun transformRuntimeFunctionTypeToSuspendFunction(funType: KotlinType): SimpleTy
suspendFunction = true suspendFunction = true
).makeNullableAsSpecified(funType.isMarkedNullable) ).makeNullableAsSpecified(funType.isMarkedNullable)
} }
private fun isContinuation(name: FqName?, isReleaseCoroutines: Boolean): Boolean {
return if (isReleaseCoroutines) name == DescriptorUtils.CONTINUATION_INTERFACE_FQ_NAME_RELEASE
else name == DescriptorUtils.CONTINUATION_INTERFACE_FQ_NAME_EXPERIMENTAL
}
@@ -1,17 +1,6 @@
/* /*
* Copyright 2010-2016 JetBrains s.r.o. * 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.
* 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.
*/ */
package org.jetbrains.kotlin.descriptors package org.jetbrains.kotlin.descriptors
@@ -32,8 +21,11 @@ fun ModuleDescriptor.resolveClassByFqName(fqName: FqName, lookupLocation: Lookup
?.getContributedClassifier(fqName.shortName(), lookupLocation) as? ClassDescriptor ?.getContributedClassifier(fqName.shortName(), lookupLocation) as? ClassDescriptor
} }
fun ModuleDescriptor.findContinuationClassDescriptorOrNull(lookupLocation: LookupLocation) = fun ModuleDescriptor.findContinuationClassDescriptorOrNull(lookupLocation: LookupLocation, releaseCoroutines: Boolean) =
resolveClassByFqName(DescriptorUtils.CONTINUATION_INTERFACE_FQ_NAME, lookupLocation) if (releaseCoroutines)
resolveClassByFqName(DescriptorUtils.CONTINUATION_INTERFACE_FQ_NAME_RELEASE, lookupLocation)
else
resolveClassByFqName(DescriptorUtils.CONTINUATION_INTERFACE_FQ_NAME_EXPERIMENTAL, lookupLocation)
fun ModuleDescriptor.findContinuationClassDescriptor(lookupLocation: LookupLocation) = fun ModuleDescriptor.findContinuationClassDescriptor(lookupLocation: LookupLocation, releaseCoroutines: Boolean) =
findContinuationClassDescriptorOrNull(lookupLocation).sure { "Continuation interface is not found" } findContinuationClassDescriptorOrNull(lookupLocation, releaseCoroutines).sure { "Continuation interface is not found" }
@@ -1,17 +1,6 @@
/* /*
* Copyright 2010-2017 JetBrains s.r.o. * 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.
* 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.
*/ */
package org.jetbrains.kotlin.resolve; package org.jetbrains.kotlin.resolve;
@@ -49,9 +38,15 @@ public class DescriptorUtils {
public static final FqName JVM_NAME = new FqName("kotlin.jvm.JvmName"); public static final FqName JVM_NAME = new FqName("kotlin.jvm.JvmName");
private static final FqName VOLATILE = new FqName("kotlin.jvm.Volatile"); private static final FqName VOLATILE = new FqName("kotlin.jvm.Volatile");
private static final FqName SYNCHRONIZED = new FqName("kotlin.jvm.Synchronized"); private static final FqName SYNCHRONIZED = new FqName("kotlin.jvm.Synchronized");
public static final FqName COROUTINES_PACKAGE_FQ_NAME = new FqName("kotlin.coroutines.experimental"); public static final FqName COROUTINES_PACKAGE_FQ_NAME_RELEASE = new FqName("kotlin.coroutines");
public static final FqName COROUTINES_INTRINSICS_PACKAGE_FQ_NAME = COROUTINES_PACKAGE_FQ_NAME.child(Name.identifier("intrinsics")); public static final FqName COROUTINES_PACKAGE_FQ_NAME_EXPERIMENTAL =
public static final FqName CONTINUATION_INTERFACE_FQ_NAME = COROUTINES_PACKAGE_FQ_NAME.child(Name.identifier("Continuation")); COROUTINES_PACKAGE_FQ_NAME_RELEASE.child(Name.identifier("experimental"));
public static final FqName COROUTINES_INTRINSICS_PACKAGE_FQ_NAME_EXPERIMENTAL =
COROUTINES_PACKAGE_FQ_NAME_EXPERIMENTAL.child(Name.identifier("intrinsics"));
public static final FqName CONTINUATION_INTERFACE_FQ_NAME_EXPERIMENTAL =
COROUTINES_PACKAGE_FQ_NAME_EXPERIMENTAL.child(Name.identifier("Continuation"));
public static final FqName CONTINUATION_INTERFACE_FQ_NAME_RELEASE =
COROUTINES_PACKAGE_FQ_NAME_RELEASE.child(Name.identifier("Continuation"));
private DescriptorUtils() { private DescriptorUtils() {
} }
@@ -1,30 +1,17 @@
/* /*
* Copyright 2010-2015 JetBrains s.r.o. * 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.
* 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.
*/ */
package org.jetbrains.kotlin.resolve.descriptorUtil package org.jetbrains.kotlin.resolve.descriptorUtil
import org.jetbrains.kotlin.descriptors.CallableDescriptor import org.jetbrains.kotlin.descriptors.CallableDescriptor
import org.jetbrains.kotlin.descriptors.ClassifierDescriptor
import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor
import org.jetbrains.kotlin.descriptors.annotations.AnnotationWithTarget import org.jetbrains.kotlin.descriptors.annotations.AnnotationWithTarget
import org.jetbrains.kotlin.descriptors.annotations.Annotations import org.jetbrains.kotlin.descriptors.annotations.Annotations
import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.resolve.DescriptorUtils
import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.kotlin.types.KotlinType
private val NO_INFER_ANNOTATION_FQ_NAME = FqName("kotlin.internal.NoInfer") private val NO_INFER_ANNOTATION_FQ_NAME = FqName("kotlin.internal.NoInfer")
@@ -33,7 +20,6 @@ private val LOW_PRIORITY_IN_OVERLOAD_RESOLUTION_FQ_NAME = FqName("kotlin.interna
private val HIDES_MEMBERS_ANNOTATION_FQ_NAME = FqName("kotlin.internal.HidesMembers") private val HIDES_MEMBERS_ANNOTATION_FQ_NAME = FqName("kotlin.internal.HidesMembers")
private val ONLY_INPUT_TYPES_FQ_NAME = FqName("kotlin.internal.OnlyInputTypes") private val ONLY_INPUT_TYPES_FQ_NAME = FqName("kotlin.internal.OnlyInputTypes")
private val DYNAMIC_EXTENSION_FQ_NAME = FqName("kotlin.internal.DynamicExtension") private val DYNAMIC_EXTENSION_FQ_NAME = FqName("kotlin.internal.DynamicExtension")
private val RESTRICTS_SUSPENSION_FQ_NAME = DescriptorUtils.COROUTINES_PACKAGE_FQ_NAME.child(Name.identifier("RestrictsSuspension"))
// @HidesMembers annotation only has effect for members with these names // @HidesMembers annotation only has effect for members with these names
val HIDES_MEMBERS_NAME_LIST = setOf(Name.identifier("forEach")) val HIDES_MEMBERS_NAME_LIST = setOf(Name.identifier("forEach"))
@@ -51,7 +37,6 @@ fun CallableDescriptor.hasLowPriorityInOverloadResolution(): Boolean = annotatio
fun CallableDescriptor.hasHidesMembersAnnotation(): Boolean = annotations.hasAnnotation(HIDES_MEMBERS_ANNOTATION_FQ_NAME) fun CallableDescriptor.hasHidesMembersAnnotation(): Boolean = annotations.hasAnnotation(HIDES_MEMBERS_ANNOTATION_FQ_NAME)
fun CallableDescriptor.hasDynamicExtensionAnnotation(): Boolean = annotations.hasAnnotation(DYNAMIC_EXTENSION_FQ_NAME) fun CallableDescriptor.hasDynamicExtensionAnnotation(): Boolean = annotations.hasAnnotation(DYNAMIC_EXTENSION_FQ_NAME)
fun ClassifierDescriptor.hasRestrictsSuspensionAnnotation(): Boolean = annotations.hasAnnotation(RESTRICTS_SUSPENSION_FQ_NAME)
fun TypeParameterDescriptor.hasOnlyInputTypesAnnotation(): Boolean = annotations.hasAnnotation(ONLY_INPUT_TYPES_FQ_NAME) fun TypeParameterDescriptor.hasOnlyInputTypesAnnotation(): Boolean = annotations.hasAnnotation(ONLY_INPUT_TYPES_FQ_NAME)
@@ -1,17 +1,6 @@
/* /*
* Copyright 2010-2016 JetBrains s.r.o. * 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.
* 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.
*/ */
package org.jetbrains.kotlin.serialization.deserialization package org.jetbrains.kotlin.serialization.deserialization
@@ -32,5 +21,8 @@ interface DeserializationConfiguration {
val readDeserializedContracts: Boolean val readDeserializedContracts: Boolean
get() = false get() = false
val releaseCoroutines: Boolean
get() = false
object Default : DeserializationConfiguration object Default : DeserializationConfiguration
} }
@@ -1,17 +1,6 @@
/* /*
* Copyright 2010-2016 JetBrains s.r.o. * 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.
* 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.
*/ */
package org.jetbrains.kotlin.serialization.deserialization package org.jetbrains.kotlin.serialization.deserialization
@@ -99,7 +88,7 @@ class TypeDeserializer(
}.toList() }.toList()
val simpleType = if (Flags.SUSPEND_TYPE.get(proto.flags)) { val simpleType = if (Flags.SUSPEND_TYPE.get(proto.flags)) {
createSuspendFunctionType(annotations, constructor, arguments, proto.nullable) createSuspendFunctionType(annotations, constructor, arguments, proto.nullable, c.components.configuration.releaseCoroutines)
} }
else { else {
KotlinTypeFactory.simpleType(annotations, constructor, arguments, proto.nullable) KotlinTypeFactory.simpleType(annotations, constructor, arguments, proto.nullable)
@@ -137,15 +126,17 @@ class TypeDeserializer(
} }
private fun createSuspendFunctionType( private fun createSuspendFunctionType(
annotations: Annotations, annotations: Annotations,
functionTypeConstructor: TypeConstructor, functionTypeConstructor: TypeConstructor,
arguments: List<TypeProjection>, arguments: List<TypeProjection>,
nullable: Boolean nullable: Boolean,
isReleaseCoroutines: Boolean
): SimpleType { ): SimpleType {
val result = when (functionTypeConstructor.parameters.size - arguments.size) { val result = when (functionTypeConstructor.parameters.size - arguments.size) {
0 -> { 0 -> {
val functionType = KotlinTypeFactory.simpleType(annotations, functionTypeConstructor, arguments, nullable) val functionType = KotlinTypeFactory.simpleType(annotations, functionTypeConstructor, arguments, nullable)
functionType.takeIf { it.isFunctionType }?.let(::transformRuntimeFunctionTypeToSuspendFunction) functionType.takeIf { it.isFunctionType }
?.let { funType -> transformRuntimeFunctionTypeToSuspendFunction(funType, isReleaseCoroutines) }
} }
// This case for types written by eap compiler 1.1 // This case for types written by eap compiler 1.1
1 -> { 1 -> {
@@ -1,17 +1,6 @@
/* /*
* Copyright 2010-2016 JetBrains s.r.o. * 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.
* 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.
*/ */
package org.jetbrains.kotlin.idea.decompiler.stubBuilder package org.jetbrains.kotlin.idea.decompiler.stubBuilder
@@ -197,10 +186,14 @@ class TypeClsStubBuilder(private val c: ClsStubBuilderContext) {
if (parameterType.hasClassName() && parameterType.argumentCount == 1) { if (parameterType.hasClassName() && parameterType.argumentCount == 1) {
val classId = c.nameResolver.getClassId(parameterType.className) val classId = c.nameResolver.getClassId(parameterType.className)
val fqName = classId.asSingleFqName() val fqName = classId.asSingleFqName()
if (fqName == DescriptorUtils.CONTINUATION_INTERFACE_FQ_NAME) { assert(
suspendParameterType = parameterType fqName == DescriptorUtils.CONTINUATION_INTERFACE_FQ_NAME_EXPERIMENTAL
continue || fqName == DescriptorUtils.CONTINUATION_INTERFACE_FQ_NAME_RELEASE
) {
"Last parameter type of suspend function must be Continuation, but it is $fqName"
} }
suspendParameterType = parameterType
continue
} }
} }
val parameter = KotlinParameterStubImpl( val parameter = KotlinParameterStubImpl(
@@ -1,17 +1,6 @@
/* /*
* Copyright 2010-2015 JetBrains s.r.o. * 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.
* 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.
*/ */
package org.jetbrains.kotlin.idea.debugger package org.jetbrains.kotlin.idea.debugger
@@ -25,8 +14,8 @@ import com.intellij.psi.PsiElement
import com.sun.jdi.* import com.sun.jdi.*
import com.sun.tools.jdi.LocalVariableImpl import com.sun.tools.jdi.LocalVariableImpl
import org.jetbrains.kotlin.codegen.binding.CodegenBinding import org.jetbrains.kotlin.codegen.binding.CodegenBinding
import org.jetbrains.kotlin.codegen.coroutines.CONTINUATION_ASM_TYPE
import org.jetbrains.kotlin.codegen.coroutines.DO_RESUME_METHOD_NAME import org.jetbrains.kotlin.codegen.coroutines.DO_RESUME_METHOD_NAME
import org.jetbrains.kotlin.codegen.coroutines.continuationAsmTypes
import org.jetbrains.kotlin.idea.codeInsight.CodeInsightUtils import org.jetbrains.kotlin.idea.codeInsight.CodeInsightUtils
import org.jetbrains.kotlin.idea.debugger.evaluate.KotlinDebuggerCaches import org.jetbrains.kotlin.idea.debugger.evaluate.KotlinDebuggerCaches
import org.jetbrains.kotlin.idea.refactoring.getLineEndOffset import org.jetbrains.kotlin.idea.refactoring.getLineEndOffset
@@ -160,8 +149,12 @@ fun isInSuspendMethod(location: Location): Boolean {
val method = location.method() val method = location.method()
val signature = method.signature() val signature = method.signature()
return signature.contains(CONTINUATION_ASM_TYPE.toString()) || for (continuationAsmType in continuationAsmTypes()) {
(method.name() == DO_RESUME_METHOD_NAME && signature == DO_RESUME_SIGNATURE) if (signature.contains(continuationAsmType.toString()) ||
(method.name() == DO_RESUME_METHOD_NAME && signature == DO_RESUME_SIGNATURE)
) return true
}
return false
} }
fun suspendFunctionFirstLineLocation(location: Location): Int? { fun suspendFunctionFirstLineLocation(location: Location): Int? {
@@ -1,5 +1,5 @@
/* /*
* Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 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. * that can be found in the license/LICENSE.txt file.
*/ */
@@ -24,6 +24,7 @@ import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.BindingContext.* import org.jetbrains.kotlin.resolve.BindingContext.*
import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall
import org.jetbrains.kotlin.resolve.calls.checkers.isBuiltInCoroutineContext import org.jetbrains.kotlin.resolve.calls.checkers.isBuiltInCoroutineContext
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
class KotlinSuspendCallLineMarkerProvider : LineMarkerProvider { class KotlinSuspendCallLineMarkerProvider : LineMarkerProvider {
@@ -102,8 +103,12 @@ fun KtExpression.hasSuspendCalls(bindingContext: BindingContext = analyze(BodyRe
} }
else -> { else -> {
val resolvedCall = getResolvedCall(bindingContext) val resolvedCall = getResolvedCall(bindingContext)
(resolvedCall?.resultingDescriptor as? FunctionDescriptor)?.isSuspend == true || if ((resolvedCall?.resultingDescriptor as? FunctionDescriptor)?.isSuspend == true) true
(resolvedCall?.resultingDescriptor as? PropertyDescriptor)?.isBuiltInCoroutineContext() == true else {
val propertyDescriptor = resolvedCall?.resultingDescriptor as? PropertyDescriptor
val s = propertyDescriptor?.fqNameSafe?.asString()
s?.startsWith("kotlin.coroutines.") == true && s.endsWith(".coroutineContext")
}
} }
} }
} }
@@ -35,10 +35,10 @@ abstract class AbstractUselessCallInspection : AbstractKotlinInspection() {
protected abstract val uselessNames: Set<String> protected abstract val uselessNames: Set<String>
protected abstract fun QualifiedExpressionVisitor.suggestConversionIfNeeded( protected abstract fun QualifiedExpressionVisitor.suggestConversionIfNeeded(
expression: KtQualifiedExpression, expression: KtQualifiedExpression,
calleeExpression: KtExpression, calleeExpression: KtExpression,
context: BindingContext, context: BindingContext,
conversion: Conversion conversion: Conversion
) )
inner class QualifiedExpressionVisitor internal constructor(val holder: ProblemsHolder, val isOnTheFly: Boolean) : KtVisitorVoid() { inner class QualifiedExpressionVisitor internal constructor(val holder: ProblemsHolder, val isOnTheFly: Boolean) : KtVisitorVoid() {
@@ -86,7 +86,9 @@ public class JsConfig {
@Nullable List<JsModuleDescriptor<KotlinJavaScriptLibraryParts>> metadataCache, @Nullable List<JsModuleDescriptor<KotlinJavaScriptLibraryParts>> metadataCache,
@Nullable Set<String> librariesToSkip) { @Nullable Set<String> librariesToSkip) {
this.project = project; this.project = project;
this.configuration = configuration; this.configuration = configuration.copy();
CommonConfigurationKeysKt.setLanguageVersionSettings(this.configuration, new ReleaseCoroutinesDisabledLanguageVersionSettings(
CommonConfigurationKeysKt.getLanguageVersionSettings(this.configuration)));
this.metadataCache = metadataCache; this.metadataCache = metadataCache;
this.librariesToSkip = librariesToSkip; this.librariesToSkip = librariesToSkip;
} }
@@ -0,0 +1,52 @@
/*
* 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.config;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.kotlin.config.*;
public class ReleaseCoroutinesDisabledLanguageVersionSettings implements LanguageVersionSettings {
@NotNull
private final LanguageVersionSettings delegate;
public ReleaseCoroutinesDisabledLanguageVersionSettings(@NotNull LanguageVersionSettings delegate) {
this.delegate = delegate;
}
@NotNull
@Override
public LanguageFeature.State getFeatureSupport(@NotNull LanguageFeature feature) {
if (feature.equals(LanguageFeature.ReleaseCoroutines)) {
return LanguageFeature.State.DISABLED;
}
return delegate.getFeatureSupport(feature);
}
@Override
public <T> T getFlag(@NotNull AnalysisFlag<? extends T> flag) {
return delegate.getFlag(flag);
}
@NotNull
@Override
public ApiVersion getApiVersion() {
return delegate.getApiVersion();
}
@NotNull
@Override
public LanguageVersion getLanguageVersion() {
return delegate.getLanguageVersion();
}
@Override
public boolean supportsFeature(@NotNull LanguageFeature feature) {
if (feature.equals(LanguageFeature.ReleaseCoroutines)) {
return false;
}
return delegate.supportsFeature(feature);
}
}
@@ -1,17 +1,6 @@
/* /*
* Copyright 2010-2016 JetBrains s.r.o. * 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.
* 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.
*/ */
package org.jetbrains.kotlin.js.inline; package org.jetbrains.kotlin.js.inline;
@@ -21,6 +10,7 @@ import kotlin.jvm.functions.Function1;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import org.jetbrains.kotlin.backend.common.CommonCoroutineCodegenUtilKt; import org.jetbrains.kotlin.backend.common.CommonCoroutineCodegenUtilKt;
import org.jetbrains.kotlin.config.*;
import org.jetbrains.kotlin.descriptors.CallableDescriptor; import org.jetbrains.kotlin.descriptors.CallableDescriptor;
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor; import org.jetbrains.kotlin.descriptors.DeclarationDescriptor;
import org.jetbrains.kotlin.descriptors.FunctionDescriptor; import org.jetbrains.kotlin.descriptors.FunctionDescriptor;
@@ -34,6 +24,7 @@ import org.jetbrains.kotlin.js.inline.context.FunctionContext;
import org.jetbrains.kotlin.js.inline.context.InliningContext; import org.jetbrains.kotlin.js.inline.context.InliningContext;
import org.jetbrains.kotlin.js.inline.context.NamingContext; import org.jetbrains.kotlin.js.inline.context.NamingContext;
import org.jetbrains.kotlin.js.inline.util.*; import org.jetbrains.kotlin.js.inline.util.*;
import org.jetbrains.kotlin.js.translate.context.TranslationContext;
import org.jetbrains.kotlin.js.translate.expression.InlineMetadata; import org.jetbrains.kotlin.js.translate.expression.InlineMetadata;
import org.jetbrains.kotlin.resolve.inline.InlineStrategy; import org.jetbrains.kotlin.resolve.inline.InlineStrategy;
@@ -340,7 +331,8 @@ public class JsInliner extends JsVisitorWithContextImpl {
private void inline(@NotNull JsInvocation call, @NotNull JsContext context) { private void inline(@NotNull JsInvocation call, @NotNull JsContext context) {
DeclarationDescriptor callDescriptor = MetadataProperties.getDescriptor(call); DeclarationDescriptor callDescriptor = MetadataProperties.getDescriptor(call);
if (isSuspendWithCurrentContinuation(callDescriptor)) { if (isSuspendWithCurrentContinuation(callDescriptor,
CommonConfigurationKeysKt.getLanguageVersionSettings(config.getConfiguration()))) {
inlineSuspendWithCurrentContinuation(call, context); inlineSuspendWithCurrentContinuation(call, context);
return; return;
} }
@@ -499,9 +491,14 @@ public class JsInliner extends JsVisitorWithContextImpl {
}.accept(statement); }.accept(statement);
} }
private static boolean isSuspendWithCurrentContinuation(@Nullable DeclarationDescriptor descriptor) { private static boolean isSuspendWithCurrentContinuation(
@Nullable DeclarationDescriptor descriptor,
@NotNull LanguageVersionSettings languageVersionSettings
) {
if (!(descriptor instanceof FunctionDescriptor)) return false; if (!(descriptor instanceof FunctionDescriptor)) return false;
return CommonCoroutineCodegenUtilKt.isBuiltInSuspendCoroutineOrReturn((FunctionDescriptor) descriptor.getOriginal()); return CommonCoroutineCodegenUtilKt.isBuiltInSuspendCoroutineOrReturn(
(FunctionDescriptor) descriptor.getOriginal(), languageVersionSettings
);
} }
private void inlineSuspendWithCurrentContinuation(@NotNull JsInvocation call, @NotNull JsContext context) { private void inlineSuspendWithCurrentContinuation(@NotNull JsInvocation call, @NotNull JsContext context) {
@@ -268,14 +268,14 @@ interface DelegateIntrinsic<in I : CallInfo> {
fun I.getDescriptor(): CallableDescriptor fun I.getDescriptor(): CallableDescriptor
fun I.getArgs(): List<JsExpression> fun I.getArgs(): List<JsExpression>
fun intrinsic(callInfo: I): JsExpression? = if (callInfo.canBeApply()) callInfo.getIntrinsic() else null fun intrinsic(callInfo: I, context: TranslationContext): JsExpression? = if (callInfo.canBeApply()) callInfo.getIntrinsic(context) else null
private fun I.getIntrinsic(): JsExpression? { private fun I.getIntrinsic(context: TranslationContext): JsExpression? {
val descriptor = getDescriptor() val descriptor = getDescriptor()
// Now intrinsic support only FunctionDescriptor. See DelegatePropertyAccessIntrinsic.getDescriptor() // Now intrinsic support only FunctionDescriptor. See DelegatePropertyAccessIntrinsic.getDescriptor()
if (descriptor is FunctionDescriptor) { if (descriptor is FunctionDescriptor) {
val intrinsic = context.intrinsics().getFunctionIntrinsic(descriptor) val intrinsic = context.intrinsics().getFunctionIntrinsic(descriptor, context)
if (intrinsic != null) { if (intrinsic != null) {
return intrinsic.apply(this, getArgs(), context) return intrinsic.apply(this, getArgs(), context)
} }
@@ -316,7 +316,7 @@ object DynamicOperatorCallCase : FunctionCallCase() {
} }
fun FunctionCallInfo.translateFunctionCall(): JsExpression { fun FunctionCallInfo.translateFunctionCall(): JsExpression {
val intrinsic = DelegateFunctionIntrinsic.intrinsic(this) val intrinsic = DelegateFunctionIntrinsic.intrinsic(this, context)
return when { return when {
intrinsic != null -> intrinsic != null ->
@@ -195,7 +195,7 @@ object SuperPropertyAccessCase : VariableAccessCase() {
private val VariableAccessInfo.additionalArguments: List<JsExpression> get() = value?.let { listOf(it) }.orEmpty() private val VariableAccessInfo.additionalArguments: List<JsExpression> get() = value?.let { listOf(it) }.orEmpty()
fun VariableAccessInfo.translateVariableAccess(): JsExpression { fun VariableAccessInfo.translateVariableAccess(): JsExpression {
val intrinsic = DelegatePropertyAccessIntrinsic.intrinsic(this) val intrinsic = DelegatePropertyAccessIntrinsic.intrinsic(this, context)
return when { return when {
intrinsic != null -> intrinsic != null ->
@@ -1,17 +1,6 @@
/* /*
* Copyright 2010-2017 JetBrains s.r.o. * 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.
* 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.
*/ */
package org.jetbrains.kotlin.js.translate.context; package org.jetbrains.kotlin.js.translate.context;
@@ -19,6 +8,7 @@ package org.jetbrains.kotlin.js.translate.context;
import com.intellij.psi.PsiElement; import com.intellij.psi.PsiElement;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import org.jetbrains.kotlin.config.*;
import org.jetbrains.kotlin.descriptors.*; import org.jetbrains.kotlin.descriptors.*;
import org.jetbrains.kotlin.descriptors.annotations.Annotations; import org.jetbrains.kotlin.descriptors.annotations.Annotations;
import org.jetbrains.kotlin.descriptors.impl.LocalVariableDescriptor; import org.jetbrains.kotlin.descriptors.impl.LocalVariableDescriptor;
@@ -132,7 +122,9 @@ public class TranslationContext {
FunctionDescriptor function = (FunctionDescriptor) declarationDescriptor; FunctionDescriptor function = (FunctionDescriptor) declarationDescriptor;
if (function.isSuspend()) { if (function.isSuspend()) {
ClassDescriptor continuationDescriptor = ClassDescriptor continuationDescriptor =
DescriptorUtilKt.findContinuationClassDescriptor(getCurrentModule(), NoLookupLocation.FROM_BACKEND); DescriptorUtilKt.findContinuationClassDescriptor(
getCurrentModule(), NoLookupLocation.FROM_BACKEND,
getLanguageVersionSettings().supportsFeature(LanguageFeature.ReleaseCoroutines));
return new LocalVariableDescriptor( return new LocalVariableDescriptor(
declarationDescriptor, declarationDescriptor,
@@ -934,4 +926,9 @@ public class TranslationContext {
public JsName getVariableForPropertyMetadata(@NotNull VariableDescriptorWithAccessors property) { public JsName getVariableForPropertyMetadata(@NotNull VariableDescriptorWithAccessors property) {
return staticContext.getVariableForPropertyMetadata(property); return staticContext.getVariableForPropertyMetadata(property);
} }
@NotNull
public LanguageVersionSettings getLanguageVersionSettings() {
return CommonConfigurationKeysKt.getLanguageVersionSettings(staticContext.getConfig().getConfiguration());
}
} }
@@ -39,8 +39,8 @@ class Intrinsics {
return binaryOperationIntrinsics.getIntrinsic(expression, context) return binaryOperationIntrinsics.getIntrinsic(expression, context)
} }
fun getFunctionIntrinsic(descriptor: FunctionDescriptor): FunctionIntrinsic? { fun getFunctionIntrinsic(descriptor: FunctionDescriptor, context: TranslationContext): FunctionIntrinsic? {
return functionIntrinsics.getIntrinsic(descriptor) return functionIntrinsics.getIntrinsic(descriptor, context)
} }
fun getObjectIntrinsic(classDescriptor: ClassDescriptor): ObjectIntrinsic? { fun getObjectIntrinsic(classDescriptor: ClassDescriptor): ObjectIntrinsic? {
@@ -17,6 +17,7 @@
package org.jetbrains.kotlin.js.translate.intrinsic.functions package org.jetbrains.kotlin.js.translate.intrinsic.functions
import org.jetbrains.kotlin.descriptors.FunctionDescriptor import org.jetbrains.kotlin.descriptors.FunctionDescriptor
import org.jetbrains.kotlin.js.translate.context.TranslationContext
import org.jetbrains.kotlin.js.translate.intrinsic.functions.basic.FunctionIntrinsic import org.jetbrains.kotlin.js.translate.intrinsic.functions.basic.FunctionIntrinsic
import org.jetbrains.kotlin.js.translate.intrinsic.functions.factories.* import org.jetbrains.kotlin.js.translate.intrinsic.functions.factories.*
import org.jetbrains.kotlin.utils.addToStdlib.firstNotNullResult import org.jetbrains.kotlin.utils.addToStdlib.firstNotNullResult
@@ -41,10 +42,10 @@ class FunctionIntrinsics {
InterceptedFIF InterceptedFIF
) )
fun getIntrinsic(descriptor: FunctionDescriptor): FunctionIntrinsic? { fun getIntrinsic(descriptor: FunctionDescriptor, context: TranslationContext): FunctionIntrinsic? {
if (descriptor in intrinsicCache) return intrinsicCache[descriptor] if (descriptor in intrinsicCache) return intrinsicCache[descriptor]
return factories.firstNotNullResult { it.getIntrinsic(descriptor) }.also { return factories.firstNotNullResult { it.getIntrinsic(descriptor, context) }.also {
intrinsicCache[descriptor] = it intrinsicCache[descriptor] = it
} }
} }
@@ -21,6 +21,7 @@ import com.intellij.openapi.util.Pair;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import org.jetbrains.kotlin.descriptors.FunctionDescriptor; import org.jetbrains.kotlin.descriptors.FunctionDescriptor;
import org.jetbrains.kotlin.js.translate.context.TranslationContext;
import org.jetbrains.kotlin.js.translate.intrinsic.functions.basic.FunctionIntrinsic; import org.jetbrains.kotlin.js.translate.intrinsic.functions.basic.FunctionIntrinsic;
import java.util.List; import java.util.List;
@@ -35,7 +36,7 @@ public abstract class CompositeFIF implements FunctionIntrinsicFactory {
@Nullable @Nullable
@Override @Override
public FunctionIntrinsic getIntrinsic(@NotNull FunctionDescriptor descriptor) { public FunctionIntrinsic getIntrinsic(@NotNull FunctionDescriptor descriptor, @NotNull TranslationContext context) {
for (Pair<Predicate<FunctionDescriptor>, FunctionIntrinsic> entry : patternsAndIntrinsics) { for (Pair<Predicate<FunctionDescriptor>, FunctionIntrinsic> entry : patternsAndIntrinsics) {
if (entry.first.test(descriptor)) { if (entry.first.test(descriptor)) {
return entry.second; return entry.second;
@@ -33,8 +33,8 @@ import org.jetbrains.kotlin.resolve.calls.checkers.isBuiltInCoroutineContext
import org.jetbrains.kotlin.resolve.inline.InlineStrategy import org.jetbrains.kotlin.resolve.inline.InlineStrategy
object CoroutineContextFIF : FunctionIntrinsicFactory { object CoroutineContextFIF : FunctionIntrinsicFactory {
override fun getIntrinsic(descriptor: FunctionDescriptor): FunctionIntrinsic? { override fun getIntrinsic(descriptor: FunctionDescriptor, context: TranslationContext): FunctionIntrinsic? {
if (!descriptor.isBuiltInCoroutineContext()) return null if (!descriptor.isBuiltInCoroutineContext(context.languageVersionSettings)) return null
return Intrinsic return Intrinsic
} }
@@ -31,7 +31,7 @@ import org.jetbrains.kotlin.resolve.scopes.receivers.SuperCallReceiverValue
import org.jetbrains.kotlin.types.typeUtil.isNotNullThrowable import org.jetbrains.kotlin.types.typeUtil.isNotNullThrowable
object ExceptionPropertyIntrinsicFactory : FunctionIntrinsicFactory { object ExceptionPropertyIntrinsicFactory : FunctionIntrinsicFactory {
override fun getIntrinsic(descriptor: FunctionDescriptor): FunctionIntrinsic? { override fun getIntrinsic(descriptor: FunctionDescriptor, context: TranslationContext): FunctionIntrinsic? {
if (descriptor !is PropertyGetterDescriptor) return null if (descriptor !is PropertyGetterDescriptor) return null
val classDescriptor = descriptor.correspondingProperty.containingDeclaration as? ClassDescriptor ?: return null val classDescriptor = descriptor.correspondingProperty.containingDeclaration as? ClassDescriptor ?: return null
if (!classDescriptor.defaultType.isNotNullThrowable()) return null if (!classDescriptor.defaultType.isNotNullThrowable()) return null
@@ -19,9 +19,10 @@ package org.jetbrains.kotlin.js.translate.intrinsic.functions.factories;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import org.jetbrains.kotlin.descriptors.FunctionDescriptor; import org.jetbrains.kotlin.descriptors.FunctionDescriptor;
import org.jetbrains.kotlin.js.translate.context.TranslationContext;
import org.jetbrains.kotlin.js.translate.intrinsic.functions.basic.FunctionIntrinsic; import org.jetbrains.kotlin.js.translate.intrinsic.functions.basic.FunctionIntrinsic;
public interface FunctionIntrinsicFactory { public interface FunctionIntrinsicFactory {
@Nullable @Nullable
FunctionIntrinsic getIntrinsic(@NotNull FunctionDescriptor descriptor); FunctionIntrinsic getIntrinsic(@NotNull FunctionDescriptor descriptor, @NotNull TranslationContext context);
} }
@@ -1,17 +1,6 @@
/* /*
* Copyright 2010-2017 JetBrains s.r.o. * 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.
* 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.
*/ */
package org.jetbrains.kotlin.js.translate.intrinsic.functions.factories package org.jetbrains.kotlin.js.translate.intrinsic.functions.factories
@@ -26,8 +15,8 @@ import org.jetbrains.kotlin.js.translate.utils.JsAstUtils
import org.jetbrains.kotlin.js.translate.utils.TranslationUtils import org.jetbrains.kotlin.js.translate.utils.TranslationUtils
object InterceptedFIF: FunctionIntrinsicFactory { object InterceptedFIF: FunctionIntrinsicFactory {
override fun getIntrinsic(descriptor: FunctionDescriptor): FunctionIntrinsic? { override fun getIntrinsic(descriptor: FunctionDescriptor, context: TranslationContext): FunctionIntrinsic? {
if (!descriptor.isBuiltInIntercepted()) return null if (!descriptor.isBuiltInIntercepted(context.languageVersionSettings)) return null
return Intrinsic return Intrinsic
} }
@@ -83,7 +83,7 @@ object LongOperationFIF : FunctionIntrinsicFactory {
fun wrapIntrinsicIfPresent(intrinsic: BaseBinaryIntrinsic?, toLeft: (JsExpression) -> JsExpression, toRight: (JsExpression) -> JsExpression): FunctionIntrinsic? = fun wrapIntrinsicIfPresent(intrinsic: BaseBinaryIntrinsic?, toLeft: (JsExpression) -> JsExpression, toRight: (JsExpression) -> JsExpression): FunctionIntrinsic? =
if (intrinsic != null) BaseBinaryIntrinsic() { left, right -> intrinsic.applyFun(toLeft(left), toRight(right)) } else null if (intrinsic != null) BaseBinaryIntrinsic() { left, right -> intrinsic.applyFun(toLeft(left), toRight(right)) } else null
override fun getIntrinsic(descriptor: FunctionDescriptor): FunctionIntrinsic? { override fun getIntrinsic(descriptor: FunctionDescriptor, context: TranslationContext): FunctionIntrinsic? {
val operationName = descriptor.name.asString() val operationName = descriptor.name.asString()
return when { return when {
LONG_EQUALS_ANY.test(descriptor) || LONG_BINARY_OPERATION_LONG.test(descriptor) || LONG_BIT_SHIFTS.test(descriptor) -> LONG_EQUALS_ANY.test(descriptor) || LONG_BINARY_OPERATION_LONG.test(descriptor) || LONG_BIT_SHIFTS.test(descriptor) ->
@@ -138,7 +138,7 @@ public enum PrimitiveBinaryOperationFIF implements FunctionIntrinsicFactory {
@Nullable @Nullable
@Override @Override
public FunctionIntrinsic getIntrinsic(@NotNull FunctionDescriptor descriptor) { public FunctionIntrinsic getIntrinsic(@NotNull FunctionDescriptor descriptor, @NotNull TranslationContext context) {
if (CHAR_RANGE_TO.test(descriptor)) { if (CHAR_RANGE_TO.test(descriptor)) {
return new RangeToIntrinsic(descriptor); return new RangeToIntrinsic(descriptor);
} }
@@ -230,7 +230,7 @@ public enum PrimitiveUnaryOperationFIF implements FunctionIntrinsicFactory {
@Nullable @Nullable
@Override @Override
public FunctionIntrinsic getIntrinsic(@NotNull FunctionDescriptor descriptor) { public FunctionIntrinsic getIntrinsic(@NotNull FunctionDescriptor descriptor, @NotNull TranslationContext context) {
if (!PATTERN.test(descriptor)) { if (!PATTERN.test(descriptor)) {
return null; return null;
} }
@@ -41,7 +41,7 @@ object StringPlusCharFIF : FunctionIntrinsicFactory {
} }
} }
override fun getIntrinsic(descriptor: FunctionDescriptor): FunctionIntrinsic? { override fun getIntrinsic(descriptor: FunctionDescriptor, context: TranslationContext): FunctionIntrinsic? {
val fqName = descriptor.fqNameUnsafe.asString() val fqName = descriptor.fqNameUnsafe.asString()
if (fqName != "kotlin.String.plus" && fqName != "kotlin.plus") return null if (fqName != "kotlin.String.plus" && fqName != "kotlin.plus") return null
@@ -1,17 +1,6 @@
/* /*
* Copyright 2010-2017 JetBrains s.r.o. * 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.
* 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.
*/ */
package org.jetbrains.kotlin.js.translate.intrinsic.functions.factories package org.jetbrains.kotlin.js.translate.intrinsic.functions.factories
@@ -26,8 +15,8 @@ import org.jetbrains.kotlin.js.translate.context.TranslationContext
import org.jetbrains.kotlin.js.translate.intrinsic.functions.basic.FunctionIntrinsic import org.jetbrains.kotlin.js.translate.intrinsic.functions.basic.FunctionIntrinsic
object SuspendCoroutineUninterceptedOrReturnFIF: FunctionIntrinsicFactory { object SuspendCoroutineUninterceptedOrReturnFIF: FunctionIntrinsicFactory {
override fun getIntrinsic(descriptor: FunctionDescriptor): FunctionIntrinsic? { override fun getIntrinsic(descriptor: FunctionDescriptor, context: TranslationContext): FunctionIntrinsic? {
if (!descriptor.isBuiltInSuspendCoroutineUninterceptedOrReturn()) return null if (!descriptor.isBuiltInSuspendCoroutineUninterceptedOrReturn(context.languageVersionSettings)) return null
return Intrinsic return Intrinsic
} }
object Intrinsic: FunctionIntrinsic() { object Intrinsic: FunctionIntrinsic() {
@@ -30,7 +30,7 @@ import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe
import org.jetbrains.kotlin.types.typeUtil.isNotNullThrowable import org.jetbrains.kotlin.types.typeUtil.isNotNullThrowable
object ThrowableConstructorIntrinsicFactory : FunctionIntrinsicFactory { object ThrowableConstructorIntrinsicFactory : FunctionIntrinsicFactory {
override fun getIntrinsic(descriptor: FunctionDescriptor): FunctionIntrinsic? { override fun getIntrinsic(descriptor: FunctionDescriptor, context: TranslationContext): FunctionIntrinsic? {
if (descriptor !is ConstructorDescriptor) return null if (descriptor !is ConstructorDescriptor) return null
if (!descriptor.constructedClass.defaultType.isNotNullThrowable()) return null if (!descriptor.constructedClass.defaultType.isNotNullThrowable()) return null
@@ -41,7 +41,7 @@ public final class IntrinsicIncrementTranslator extends IncrementTranslator {
@Override @Override
@NotNull @NotNull
protected JsExpression operationExpression(@NotNull TranslationContext context, @NotNull JsExpression receiver) { protected JsExpression operationExpression(@NotNull TranslationContext context, @NotNull JsExpression receiver) {
FunctionIntrinsic intrinsic = context.intrinsics().getFunctionIntrinsic(resolvedCall.getResultingDescriptor()); FunctionIntrinsic intrinsic = context.intrinsics().getFunctionIntrinsic(resolvedCall.getResultingDescriptor(), context);
assert intrinsic != null; assert intrinsic != null;
CallInfo callInfo = CallInfoKt.getCallInfo(context, resolvedCall, receiver); CallInfo callInfo = CallInfoKt.getCallInfo(context, resolvedCall, receiver);
return intrinsic.apply(callInfo, Collections.emptyList(), context); return intrinsic.apply(callInfo, Collections.emptyList(), context);
@@ -1,17 +1,6 @@
/* /*
* Copyright 2010-2017 JetBrains s.r.o. * 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.
* 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.
*/ */
package org.jetbrains.kotlin.js.translate.reference package org.jetbrains.kotlin.js.translate.reference
@@ -50,7 +39,7 @@ import java.util.*
class CallArgumentTranslator private constructor( class CallArgumentTranslator private constructor(
private val resolvedCall: ResolvedCall<*>, private val resolvedCall: ResolvedCall<*>,
private val receiver: JsExpression?, private val receiver: JsExpression?,
context: TranslationContext private val context: TranslationContext
) : AbstractTranslator(context) { ) : AbstractTranslator(context) {
data class ArgumentsInfo( data class ArgumentsInfo(
@@ -165,7 +154,7 @@ class CallArgumentTranslator private constructor(
val callableDescriptor = resolvedCall.resultingDescriptor val callableDescriptor = resolvedCall.resultingDescriptor
if (callableDescriptor is FunctionDescriptor && callableDescriptor.isSuspend) { if (callableDescriptor is FunctionDescriptor && callableDescriptor.isSuspend) {
var continuationArg: JsExpression = TranslationUtils.translateContinuationArgument(context()) var continuationArg: JsExpression = TranslationUtils.translateContinuationArgument(context())
if (callableDescriptor.original.isBuiltInSuspendCoroutineOrReturn()) { if (callableDescriptor.original.isBuiltInSuspendCoroutineOrReturn(context.languageVersionSettings)) {
val facadeName = context().getNameForDescriptor(TranslationUtils.getCoroutineProperty(context(), "facade")) val facadeName = context().getNameForDescriptor(TranslationUtils.getCoroutineProperty(context(), "facade"))
continuationArg = JsAstUtils.pureFqn(facadeName, continuationArg) continuationArg = JsAstUtils.pureFqn(facadeName, continuationArg)
} }
@@ -1,17 +1,6 @@
/* /*
* Copyright 2010-2017 JetBrains s.r.o. * 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.
* 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.
*/ */
package org.jetbrains.kotlin.js.translate.utils; package org.jetbrains.kotlin.js.translate.utils;
@@ -22,6 +11,7 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import org.jetbrains.kotlin.builtins.FunctionTypesKt; import org.jetbrains.kotlin.builtins.FunctionTypesKt;
import org.jetbrains.kotlin.builtins.KotlinBuiltIns; import org.jetbrains.kotlin.builtins.KotlinBuiltIns;
import org.jetbrains.kotlin.config.CoroutineLanguageVersionSettingsUtilKt;
import org.jetbrains.kotlin.descriptors.*; import org.jetbrains.kotlin.descriptors.*;
import org.jetbrains.kotlin.descriptors.impl.AnonymousFunctionDescriptor; import org.jetbrains.kotlin.descriptors.impl.AnonymousFunctionDescriptor;
import org.jetbrains.kotlin.descriptors.impl.LocalVariableAccessorDescriptor; import org.jetbrains.kotlin.descriptors.impl.LocalVariableAccessorDescriptor;
@@ -290,7 +280,7 @@ public final class TranslationUtils {
return false; return false;
} }
if (context.intrinsics().getFunctionIntrinsic((FunctionDescriptor) operationDescriptor) != null) return true; if (context.intrinsics().getFunctionIntrinsic((FunctionDescriptor) operationDescriptor, context) != null) return true;
return false; return false;
} }
@@ -391,7 +381,8 @@ public final class TranslationUtils {
@NotNull @NotNull
public static ClassDescriptor getCoroutineBaseClass(@NotNull TranslationContext context) { public static ClassDescriptor getCoroutineBaseClass(@NotNull TranslationContext context) {
FqName className = DescriptorUtils.COROUTINES_PACKAGE_FQ_NAME.child(Name.identifier("CoroutineImpl")); FqName className = CoroutineLanguageVersionSettingsUtilKt.coroutinesPackageFqName(context.getLanguageVersionSettings())
.child(Name.identifier("CoroutineImpl"));
ClassDescriptor descriptor = FindClassInModuleKt.findClassAcrossModuleDependencies( ClassDescriptor descriptor = FindClassInModuleKt.findClassAcrossModuleDependencies(
context.getCurrentModule(), ClassId.topLevel(className)); context.getCurrentModule(), ClassId.topLevel(className));
assert descriptor != null; assert descriptor != null;
@@ -1,17 +1,6 @@
/* /*
* Copyright 2010-2017 JetBrains s.r.o. * 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.
* 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.
*/ */
package org.jetbrains.kotlin.js.translate.utils package org.jetbrains.kotlin.js.translate.utils
@@ -21,6 +10,7 @@ import com.intellij.util.SmartList
import org.jetbrains.kotlin.backend.common.COROUTINE_SUSPENDED_NAME import org.jetbrains.kotlin.backend.common.COROUTINE_SUSPENDED_NAME
import org.jetbrains.kotlin.builtins.KotlinBuiltIns import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.config.LanguageFeature import org.jetbrains.kotlin.config.LanguageFeature
import org.jetbrains.kotlin.config.coroutinesIntrinsicsPackageFqName
import org.jetbrains.kotlin.config.languageVersionSettings import org.jetbrains.kotlin.config.languageVersionSettings
import org.jetbrains.kotlin.descriptors.ClassDescriptor import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.descriptors.FunctionDescriptor import org.jetbrains.kotlin.descriptors.FunctionDescriptor
@@ -78,7 +68,7 @@ fun generateDelegateCall(
args.add(JsNameRef(jsParamName)) args.add(JsNameRef(jsParamName))
} }
val intrinsic = context.intrinsics().getFunctionIntrinsic(toDescriptor) val intrinsic = context.intrinsics().getFunctionIntrinsic(toDescriptor, context)
val invocation = if (intrinsic is FunctionIntrinsicWithReceiverComputed) { val invocation = if (intrinsic is FunctionIntrinsicWithReceiverComputed) {
intrinsic.apply(thisObject, args, context) intrinsic.apply(thisObject, args, context)
} else { } else {
@@ -165,7 +155,7 @@ fun JsFunction.fillCoroutineMetadata(
descriptor: FunctionDescriptor, descriptor: FunctionDescriptor,
hasController: Boolean hasController: Boolean
) { ) {
val suspendPropertyDescriptor = context.currentModule.getPackage(DescriptorUtils.COROUTINES_INTRINSICS_PACKAGE_FQ_NAME) val suspendPropertyDescriptor = context.currentModule.getPackage(context.languageVersionSettings.coroutinesIntrinsicsPackageFqName())
.memberScope .memberScope
.getContributedVariables(COROUTINE_SUSPENDED_NAME, NoLookupLocation.FROM_BACKEND).first() .getContributedVariables(COROUTINE_SUSPENDED_NAME, NoLookupLocation.FROM_BACKEND).first()
@@ -1,17 +1,6 @@
/* /*
* Copyright 2010-2017 JetBrains s.r.o. * 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.
* 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.
*/ */
package org.jetbrains.kotlin.android.parcel package org.jetbrains.kotlin.android.parcel
@@ -184,7 +173,9 @@ class ParcelableDeclarationChecker : DeclarationChecker {
ClassBuilderMode.full(false), ClassBuilderMode.full(false),
IncompatibleClassTracker.DoNothing, IncompatibleClassTracker.DoNothing,
descriptor.module.name.asString(), descriptor.module.name.asString(),
/* isJvm8Target */ false) /* isJvm8Target */ false,
/* isReleaseCoroutines */ KotlinTypeMapper.RELEASE_COROUTINES_DEFAULT
)
for (parameter in primaryConstructor?.valueParameters.orEmpty()) { for (parameter in primaryConstructor?.valueParameters.orEmpty()) {
checkParcelableClassProperty(parameter, descriptor, diagnosticHolder, typeMapper) checkParcelableClassProperty(parameter, descriptor, diagnosticHolder, typeMapper)
@@ -31,6 +31,7 @@ class IdeaKotlinUastBindingContextProviderService : KotlinUastBindingContextProv
override fun getTypeMapper(element: KtElement): KotlinTypeMapper? { override fun getTypeMapper(element: KtElement): KotlinTypeMapper? {
return KotlinTypeMapper( return KotlinTypeMapper(
getBindingContext(element), ClassBuilderMode.LIGHT_CLASSES, getBindingContext(element), ClassBuilderMode.LIGHT_CLASSES,
IncompatibleClassTracker.DoNothing, JvmAbi.DEFAULT_MODULE_NAME, false) IncompatibleClassTracker.DoNothing, JvmAbi.DEFAULT_MODULE_NAME, false, KotlinTypeMapper.RELEASE_COROUTINES_DEFAULT
)
} }
} }
@@ -41,7 +41,8 @@ class UastAnalysisHandlerExtension : AnalysisHandlerExtension {
val typeMapper = KotlinTypeMapper( val typeMapper = KotlinTypeMapper(
bindingContext, ClassBuilderMode.LIGHT_CLASSES, bindingContext, ClassBuilderMode.LIGHT_CLASSES,
IncompatibleClassTracker.DoNothing, JvmAbi.DEFAULT_MODULE_NAME, false) IncompatibleClassTracker.DoNothing, JvmAbi.DEFAULT_MODULE_NAME, false, KotlinTypeMapper.RELEASE_COROUTINES_DEFAULT
)
this.typeMapper = typeMapper this.typeMapper = typeMapper
return typeMapper return typeMapper
} }