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
@@ -268,14 +268,14 @@ interface DelegateIntrinsic<in I : CallInfo> {
fun I.getDescriptor(): CallableDescriptor
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()
// Now intrinsic support only FunctionDescriptor. See DelegatePropertyAccessIntrinsic.getDescriptor()
if (descriptor is FunctionDescriptor) {
val intrinsic = context.intrinsics().getFunctionIntrinsic(descriptor)
val intrinsic = context.intrinsics().getFunctionIntrinsic(descriptor, context)
if (intrinsic != null) {
return intrinsic.apply(this, getArgs(), context)
}
@@ -316,7 +316,7 @@ object DynamicOperatorCallCase : FunctionCallCase() {
}
fun FunctionCallInfo.translateFunctionCall(): JsExpression {
val intrinsic = DelegateFunctionIntrinsic.intrinsic(this)
val intrinsic = DelegateFunctionIntrinsic.intrinsic(this, context)
return when {
intrinsic != null ->
@@ -195,7 +195,7 @@ object SuperPropertyAccessCase : VariableAccessCase() {
private val VariableAccessInfo.additionalArguments: List<JsExpression> get() = value?.let { listOf(it) }.orEmpty()
fun VariableAccessInfo.translateVariableAccess(): JsExpression {
val intrinsic = DelegatePropertyAccessIntrinsic.intrinsic(this)
val intrinsic = DelegatePropertyAccessIntrinsic.intrinsic(this, context)
return when {
intrinsic != null ->
@@ -1,17 +1,6 @@
/*
* Copyright 2010-2017 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
* that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.js.translate.context;
@@ -19,6 +8,7 @@ package org.jetbrains.kotlin.js.translate.context;
import com.intellij.psi.PsiElement;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.kotlin.config.*;
import org.jetbrains.kotlin.descriptors.*;
import org.jetbrains.kotlin.descriptors.annotations.Annotations;
import org.jetbrains.kotlin.descriptors.impl.LocalVariableDescriptor;
@@ -132,7 +122,9 @@ public class TranslationContext {
FunctionDescriptor function = (FunctionDescriptor) declarationDescriptor;
if (function.isSuspend()) {
ClassDescriptor continuationDescriptor =
DescriptorUtilKt.findContinuationClassDescriptor(getCurrentModule(), NoLookupLocation.FROM_BACKEND);
DescriptorUtilKt.findContinuationClassDescriptor(
getCurrentModule(), NoLookupLocation.FROM_BACKEND,
getLanguageVersionSettings().supportsFeature(LanguageFeature.ReleaseCoroutines));
return new LocalVariableDescriptor(
declarationDescriptor,
@@ -934,4 +926,9 @@ public class TranslationContext {
public JsName getVariableForPropertyMetadata(@NotNull VariableDescriptorWithAccessors 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)
}
fun getFunctionIntrinsic(descriptor: FunctionDescriptor): FunctionIntrinsic? {
return functionIntrinsics.getIntrinsic(descriptor)
fun getFunctionIntrinsic(descriptor: FunctionDescriptor, context: TranslationContext): FunctionIntrinsic? {
return functionIntrinsics.getIntrinsic(descriptor, context)
}
fun getObjectIntrinsic(classDescriptor: ClassDescriptor): ObjectIntrinsic? {
@@ -17,6 +17,7 @@
package org.jetbrains.kotlin.js.translate.intrinsic.functions
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.factories.*
import org.jetbrains.kotlin.utils.addToStdlib.firstNotNullResult
@@ -41,10 +42,10 @@ class FunctionIntrinsics {
InterceptedFIF
)
fun getIntrinsic(descriptor: FunctionDescriptor): FunctionIntrinsic? {
fun getIntrinsic(descriptor: FunctionDescriptor, context: TranslationContext): FunctionIntrinsic? {
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
}
}
@@ -21,6 +21,7 @@ import com.intellij.openapi.util.Pair;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
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 java.util.List;
@@ -35,7 +36,7 @@ public abstract class CompositeFIF implements FunctionIntrinsicFactory {
@Nullable
@Override
public FunctionIntrinsic getIntrinsic(@NotNull FunctionDescriptor descriptor) {
public FunctionIntrinsic getIntrinsic(@NotNull FunctionDescriptor descriptor, @NotNull TranslationContext context) {
for (Pair<Predicate<FunctionDescriptor>, FunctionIntrinsic> entry : patternsAndIntrinsics) {
if (entry.first.test(descriptor)) {
return entry.second;
@@ -33,8 +33,8 @@ import org.jetbrains.kotlin.resolve.calls.checkers.isBuiltInCoroutineContext
import org.jetbrains.kotlin.resolve.inline.InlineStrategy
object CoroutineContextFIF : FunctionIntrinsicFactory {
override fun getIntrinsic(descriptor: FunctionDescriptor): FunctionIntrinsic? {
if (!descriptor.isBuiltInCoroutineContext()) return null
override fun getIntrinsic(descriptor: FunctionDescriptor, context: TranslationContext): FunctionIntrinsic? {
if (!descriptor.isBuiltInCoroutineContext(context.languageVersionSettings)) return null
return Intrinsic
}
@@ -31,7 +31,7 @@ import org.jetbrains.kotlin.resolve.scopes.receivers.SuperCallReceiverValue
import org.jetbrains.kotlin.types.typeUtil.isNotNullThrowable
object ExceptionPropertyIntrinsicFactory : FunctionIntrinsicFactory {
override fun getIntrinsic(descriptor: FunctionDescriptor): FunctionIntrinsic? {
override fun getIntrinsic(descriptor: FunctionDescriptor, context: TranslationContext): FunctionIntrinsic? {
if (descriptor !is PropertyGetterDescriptor) return null
val classDescriptor = descriptor.correspondingProperty.containingDeclaration as? ClassDescriptor ?: 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.Nullable;
import org.jetbrains.kotlin.descriptors.FunctionDescriptor;
import org.jetbrains.kotlin.js.translate.context.TranslationContext;
import org.jetbrains.kotlin.js.translate.intrinsic.functions.basic.FunctionIntrinsic;
public interface FunctionIntrinsicFactory {
@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.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
* that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.js.translate.intrinsic.functions.factories
@@ -26,8 +15,8 @@ import org.jetbrains.kotlin.js.translate.utils.JsAstUtils
import org.jetbrains.kotlin.js.translate.utils.TranslationUtils
object InterceptedFIF: FunctionIntrinsicFactory {
override fun getIntrinsic(descriptor: FunctionDescriptor): FunctionIntrinsic? {
if (!descriptor.isBuiltInIntercepted()) return null
override fun getIntrinsic(descriptor: FunctionDescriptor, context: TranslationContext): FunctionIntrinsic? {
if (!descriptor.isBuiltInIntercepted(context.languageVersionSettings)) return null
return Intrinsic
}
@@ -83,7 +83,7 @@ object LongOperationFIF : FunctionIntrinsicFactory {
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
override fun getIntrinsic(descriptor: FunctionDescriptor): FunctionIntrinsic? {
override fun getIntrinsic(descriptor: FunctionDescriptor, context: TranslationContext): FunctionIntrinsic? {
val operationName = descriptor.name.asString()
return when {
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
@Override
public FunctionIntrinsic getIntrinsic(@NotNull FunctionDescriptor descriptor) {
public FunctionIntrinsic getIntrinsic(@NotNull FunctionDescriptor descriptor, @NotNull TranslationContext context) {
if (CHAR_RANGE_TO.test(descriptor)) {
return new RangeToIntrinsic(descriptor);
}
@@ -230,7 +230,7 @@ public enum PrimitiveUnaryOperationFIF implements FunctionIntrinsicFactory {
@Nullable
@Override
public FunctionIntrinsic getIntrinsic(@NotNull FunctionDescriptor descriptor) {
public FunctionIntrinsic getIntrinsic(@NotNull FunctionDescriptor descriptor, @NotNull TranslationContext context) {
if (!PATTERN.test(descriptor)) {
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()
if (fqName != "kotlin.String.plus" && fqName != "kotlin.plus") return null
@@ -1,17 +1,6 @@
/*
* Copyright 2010-2017 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
* that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.js.translate.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
object SuspendCoroutineUninterceptedOrReturnFIF: FunctionIntrinsicFactory {
override fun getIntrinsic(descriptor: FunctionDescriptor): FunctionIntrinsic? {
if (!descriptor.isBuiltInSuspendCoroutineUninterceptedOrReturn()) return null
override fun getIntrinsic(descriptor: FunctionDescriptor, context: TranslationContext): FunctionIntrinsic? {
if (!descriptor.isBuiltInSuspendCoroutineUninterceptedOrReturn(context.languageVersionSettings)) return null
return Intrinsic
}
object Intrinsic: FunctionIntrinsic() {
@@ -30,7 +30,7 @@ import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe
import org.jetbrains.kotlin.types.typeUtil.isNotNullThrowable
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.constructedClass.defaultType.isNotNullThrowable()) return null
@@ -41,7 +41,7 @@ public final class IntrinsicIncrementTranslator extends IncrementTranslator {
@Override
@NotNull
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;
CallInfo callInfo = CallInfoKt.getCallInfo(context, resolvedCall, receiver);
return intrinsic.apply(callInfo, Collections.emptyList(), context);
@@ -1,17 +1,6 @@
/*
* Copyright 2010-2017 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
* that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.js.translate.reference
@@ -50,7 +39,7 @@ import java.util.*
class CallArgumentTranslator private constructor(
private val resolvedCall: ResolvedCall<*>,
private val receiver: JsExpression?,
context: TranslationContext
private val context: TranslationContext
) : AbstractTranslator(context) {
data class ArgumentsInfo(
@@ -165,7 +154,7 @@ class CallArgumentTranslator private constructor(
val callableDescriptor = resolvedCall.resultingDescriptor
if (callableDescriptor is FunctionDescriptor && callableDescriptor.isSuspend) {
var continuationArg: JsExpression = TranslationUtils.translateContinuationArgument(context())
if (callableDescriptor.original.isBuiltInSuspendCoroutineOrReturn()) {
if (callableDescriptor.original.isBuiltInSuspendCoroutineOrReturn(context.languageVersionSettings)) {
val facadeName = context().getNameForDescriptor(TranslationUtils.getCoroutineProperty(context(), "facade"))
continuationArg = JsAstUtils.pureFqn(facadeName, continuationArg)
}
@@ -1,17 +1,6 @@
/*
* Copyright 2010-2017 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
* that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.js.translate.utils;
@@ -22,6 +11,7 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.kotlin.builtins.FunctionTypesKt;
import org.jetbrains.kotlin.builtins.KotlinBuiltIns;
import org.jetbrains.kotlin.config.CoroutineLanguageVersionSettingsUtilKt;
import org.jetbrains.kotlin.descriptors.*;
import org.jetbrains.kotlin.descriptors.impl.AnonymousFunctionDescriptor;
import org.jetbrains.kotlin.descriptors.impl.LocalVariableAccessorDescriptor;
@@ -290,7 +280,7 @@ public final class TranslationUtils {
return false;
}
if (context.intrinsics().getFunctionIntrinsic((FunctionDescriptor) operationDescriptor) != null) return true;
if (context.intrinsics().getFunctionIntrinsic((FunctionDescriptor) operationDescriptor, context) != null) return true;
return false;
}
@@ -391,7 +381,8 @@ public final class TranslationUtils {
@NotNull
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(
context.getCurrentModule(), ClassId.topLevel(className));
assert descriptor != null;
@@ -1,17 +1,6 @@
/*
* Copyright 2010-2017 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
* that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.js.translate.utils
@@ -21,6 +10,7 @@ import com.intellij.util.SmartList
import org.jetbrains.kotlin.backend.common.COROUTINE_SUSPENDED_NAME
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.config.LanguageFeature
import org.jetbrains.kotlin.config.coroutinesIntrinsicsPackageFqName
import org.jetbrains.kotlin.config.languageVersionSettings
import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
@@ -78,7 +68,7 @@ fun generateDelegateCall(
args.add(JsNameRef(jsParamName))
}
val intrinsic = context.intrinsics().getFunctionIntrinsic(toDescriptor)
val intrinsic = context.intrinsics().getFunctionIntrinsic(toDescriptor, context)
val invocation = if (intrinsic is FunctionIntrinsicWithReceiverComputed) {
intrinsic.apply(thisObject, args, context)
} else {
@@ -165,7 +155,7 @@ fun JsFunction.fillCoroutineMetadata(
descriptor: FunctionDescriptor,
hasController: Boolean
) {
val suspendPropertyDescriptor = context.currentModule.getPackage(DescriptorUtils.COROUTINES_INTRINSICS_PACKAGE_FQ_NAME)
val suspendPropertyDescriptor = context.currentModule.getPackage(context.languageVersionSettings.coroutinesIntrinsicsPackageFqName())
.memberScope
.getContributedVariables(COROUTINE_SUSPENDED_NAME, NoLookupLocation.FROM_BACKEND).first()