Remove redundant locals
Do not transform already transformed suspend lambdas Ignore duplicates of continuation in local variable table during redundant locals elimination.
This commit is contained in:
@@ -1103,8 +1103,11 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
if (closure.isSuspend()) {
|
||||
// resultContinuation
|
||||
if (closure.isSuspendLambda()) {
|
||||
// When inlining crossinline lambda, the ACONST_NULL is never popped.
|
||||
// Thus, do not generate it. Otherwise, it leads to VerifyError on run-time.
|
||||
boolean isCrossinlineLambda = (callGenerator instanceof InlineCodegen<?>) &&
|
||||
Objects.requireNonNull(((InlineCodegen) callGenerator).getActiveLambda()).isCrossInline;
|
||||
Objects.requireNonNull(((InlineCodegen) callGenerator).getActiveLambda(),
|
||||
"no active lambda found").isCrossInline;
|
||||
if (!isCrossinlineLambda) {
|
||||
v.aconst(null);
|
||||
}
|
||||
|
||||
+51
-44
@@ -70,6 +70,7 @@ class CodegenAnnotatingVisitor extends KtVisitorVoid {
|
||||
|
||||
private final Stack<ClassDescriptor> classStack = new Stack<>();
|
||||
private final Stack<String> nameStack = new Stack<>();
|
||||
private final Stack<FunctionDescriptor> functionsStack = new Stack<>();
|
||||
private final Set<ClassDescriptor> uninitializedClasses = new HashSet<>();
|
||||
|
||||
private final BindingTrace bindingTrace;
|
||||
@@ -317,49 +318,16 @@ class CodegenAnnotatingVisitor extends KtVisitorVoid {
|
||||
);
|
||||
closure.setSuspend(true);
|
||||
closure.setSuspendLambda();
|
||||
if (capturesCrossinlineSuspendLambda(functionLiteral)) {
|
||||
bindingTrace.record(
|
||||
CodegenBinding.CAPTURES_CROSSINLINE_SUSPEND_LAMBDA,
|
||||
functionDescriptor,
|
||||
true
|
||||
);
|
||||
}
|
||||
}
|
||||
functionsStack.push(functionDescriptor);
|
||||
|
||||
super.visitLambdaExpression(lambdaExpression);
|
||||
|
||||
functionsStack.pop();
|
||||
nameStack.pop();
|
||||
classStack.pop();
|
||||
}
|
||||
|
||||
// If inner lambda captures crossinline suspend lambda, it is unsafe to generate state machine for it.
|
||||
private boolean capturesCrossinlineSuspendLambda(@NotNull PsiElement psiNode) {
|
||||
PsiElement[] children = psiNode.getChildren();
|
||||
boolean res = false;
|
||||
for (PsiElement child : children) {
|
||||
if (child instanceof KtCallElement) {
|
||||
KtExpression callee = ((KtCallElement) child).getCalleeExpression();
|
||||
Call call = bindingContext.get(CALL, callee);
|
||||
ResolvedCall<?> resolvedCall = bindingContext.get(RESOLVED_CALL, call);
|
||||
if (resolvedCall instanceof VariableAsFunctionResolvedCall) {
|
||||
VariableAsFunctionResolvedCall variableAsFunction = (VariableAsFunctionResolvedCall) resolvedCall;
|
||||
VariableDescriptor variableDescriptor = variableAsFunction.getVariableCall().getResultingDescriptor();
|
||||
CallableDescriptor callableDescriptor = ((ResolvedCall) variableAsFunction).getResultingDescriptor();
|
||||
if (variableDescriptor instanceof ValueParameterDescriptor &&
|
||||
((ValueParameterDescriptor) variableDescriptor).isCrossinline() &&
|
||||
callableDescriptor instanceof FunctionDescriptor &&
|
||||
((FunctionDescriptor) callableDescriptor).isSuspend()) {
|
||||
FunctionDescriptor enclosingDescriptor =
|
||||
bindingContext.get(ENCLOSING_SUSPEND_FUNCTION_FOR_SUSPEND_FUNCTION_CALL, resolvedCall.getCall());
|
||||
assert(enclosingDescriptor != null);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
res = res || capturesCrossinlineSuspendLambda(child);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitCallableReferenceExpression(@NotNull KtCallableReferenceExpression expression) {
|
||||
ResolvedCall<?> referencedFunction = CallUtilKt.getResolvedCall(expression.getCallableReference(), bindingContext);
|
||||
@@ -573,17 +541,11 @@ class CodegenAnnotatingVisitor extends KtVisitorVoid {
|
||||
recordClassForFunction(function, functionDescriptor, name, functionDescriptor);
|
||||
MutableClosure closure = recordClosure(classDescriptor, name);
|
||||
closure.setSuspend(true);
|
||||
|
||||
if (capturesCrossinlineSuspendLambda(function)) {
|
||||
bindingTrace.record(
|
||||
CodegenBinding.CAPTURES_CROSSINLINE_SUSPEND_LAMBDA,
|
||||
functionDescriptor,
|
||||
true
|
||||
);
|
||||
}
|
||||
functionsStack.push(functionDescriptor);
|
||||
|
||||
super.visitNamedFunction(function);
|
||||
|
||||
functionsStack.pop();
|
||||
if (nameForClassOrPackageMember != null) {
|
||||
nameStack.pop();
|
||||
}
|
||||
@@ -593,7 +555,9 @@ class CodegenAnnotatingVisitor extends KtVisitorVoid {
|
||||
|
||||
if (nameForClassOrPackageMember != null) {
|
||||
nameStack.push(nameForClassOrPackageMember);
|
||||
functionsStack.push(functionDescriptor);
|
||||
super.visitNamedFunction(function);
|
||||
functionsStack.pop();
|
||||
nameStack.pop();
|
||||
}
|
||||
else {
|
||||
@@ -602,8 +566,10 @@ class CodegenAnnotatingVisitor extends KtVisitorVoid {
|
||||
recordClosure(classDescriptor, name);
|
||||
|
||||
classStack.push(classDescriptor);
|
||||
functionsStack.push(functionDescriptor);
|
||||
nameStack.push(name);
|
||||
super.visitNamedFunction(function);
|
||||
functionsStack.pop();
|
||||
nameStack.pop();
|
||||
classStack.pop();
|
||||
}
|
||||
@@ -631,6 +597,47 @@ class CodegenAnnotatingVisitor extends KtVisitorVoid {
|
||||
public void visitCallExpression(@NotNull KtCallExpression expression) {
|
||||
super.visitCallExpression(expression);
|
||||
checkSamCall(expression);
|
||||
checkCrossinlineSuspendCall(expression);
|
||||
}
|
||||
|
||||
private void checkCrossinlineSuspendCall(@NotNull KtCallExpression expression) {
|
||||
KtExpression callee = expression.getCalleeExpression();
|
||||
Call call = bindingContext.get(CALL, callee);
|
||||
ResolvedCall<?> resolvedCall = bindingContext.get(RESOLVED_CALL, call);
|
||||
|
||||
if (resolvedCall instanceof VariableAsFunctionResolvedCall) {
|
||||
VariableAsFunctionResolvedCall variableAsFunction = (VariableAsFunctionResolvedCall) resolvedCall;
|
||||
VariableDescriptor variableDescriptor = variableAsFunction.getVariableCall().getResultingDescriptor();
|
||||
CallableDescriptor callableDescriptor = ((ResolvedCall) variableAsFunction).getResultingDescriptor();
|
||||
|
||||
if (variableDescriptor instanceof ValueParameterDescriptor &&
|
||||
((ValueParameterDescriptor) variableDescriptor).isCrossinline() &&
|
||||
callableDescriptor instanceof FunctionDescriptor &&
|
||||
((FunctionDescriptor) callableDescriptor).isSuspend()) {
|
||||
FunctionDescriptor enclosingDescriptor =
|
||||
bindingContext.get(ENCLOSING_SUSPEND_FUNCTION_FOR_SUSPEND_FUNCTION_CALL, resolvedCall.getCall());
|
||||
if (enclosingDescriptor == null) return;
|
||||
|
||||
DeclarationDescriptor functionWithCrossinlineParameter = variableDescriptor.getContainingDeclaration();
|
||||
for (int i = functionsStack.size() - 1; i >= 0; i--) {
|
||||
if (functionsStack.get(i).isSuspend()) {
|
||||
Boolean alreadyPutValue = bindingTrace.getBindingContext()
|
||||
.get(CodegenBinding.CAPTURES_CROSSINLINE_SUSPEND_LAMBDA, functionsStack.get(i));
|
||||
if (alreadyPutValue != null && alreadyPutValue) {
|
||||
return;
|
||||
}
|
||||
bindingTrace.record(
|
||||
CodegenBinding.CAPTURES_CROSSINLINE_SUSPEND_LAMBDA,
|
||||
functionsStack.get(i),
|
||||
true
|
||||
);
|
||||
}
|
||||
if (functionsStack.get(i) == functionWithCrossinlineParameter) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void checkSamCall(@NotNull KtCallElement expression) {
|
||||
|
||||
+10
-8
@@ -67,20 +67,24 @@ class CoroutineTransformerMethodVisitor(
|
||||
override fun performTransformations(methodNode: MethodNode) {
|
||||
removeFakeContinuationConstructorCall(methodNode)
|
||||
|
||||
replaceFakeContinuationsWithRealOnes(
|
||||
methodNode,
|
||||
if (isForNamedFunction) getLastParameterIndex(methodNode.desc, methodNode.access) else 0
|
||||
)
|
||||
|
||||
FixStackMethodTransformer().transform(containingClassInternalName, methodNode)
|
||||
RedundantLocalsEliminationMethodTransformer().transform(containingClassInternalName, methodNode)
|
||||
updateMaxStack(methodNode)
|
||||
|
||||
val suspensionPoints = collectSuspensionPoints(methodNode)
|
||||
|
||||
// First instruction in the method node may change in case of named function
|
||||
val actualCoroutineStart = methodNode.instructions.first
|
||||
|
||||
FixStackMethodTransformer().transform(containingClassInternalName, methodNode)
|
||||
|
||||
if (isForNamedFunction) {
|
||||
ReturnUnitMethodTransformer.transform(containingClassInternalName, methodNode)
|
||||
|
||||
if (allSuspensionPointsAreTailCalls(containingClassInternalName, methodNode, suspensionPoints)) {
|
||||
continuationIndex = getLastParameterIndex(methodNode.desc, methodNode.access)
|
||||
replaceFakeContinuationsWithRealOnes(methodNode, continuationIndex)
|
||||
|
||||
dropSuspensionMarkers(methodNode, suspensionPoints)
|
||||
return
|
||||
}
|
||||
@@ -101,8 +105,6 @@ class CoroutineTransformerMethodVisitor(
|
||||
// Actual max stack might be increased during the previous phases
|
||||
updateMaxStack(methodNode)
|
||||
|
||||
replaceFakeContinuationsWithRealOnes(methodNode, continuationIndex)
|
||||
|
||||
// Remove unreachable suspension points
|
||||
// If we don't do this, then relevant frames will not be analyzed, that is unexpected from point of view of next steps (e.g. variable spilling)
|
||||
removeUnreachableSuspensionPointsAndExitPoints(methodNode, suspensionPoints)
|
||||
@@ -820,7 +822,7 @@ private fun AbstractInsnNode?.isInvisibleInDebugVarInsn(methodNode: MethodNode):
|
||||
private val SAFE_OPCODES =
|
||||
((Opcodes.DUP..Opcodes.DUP2_X2) + Opcodes.NOP + Opcodes.POP + Opcodes.POP2 + (Opcodes.IFEQ..Opcodes.GOTO)).toSet()
|
||||
|
||||
internal fun replaceFakeContinuationsWithRealOnes(methodNode: MethodNode, continuationIndex: Int) {
|
||||
private fun replaceFakeContinuationsWithRealOnes(methodNode: MethodNode, continuationIndex: Int) {
|
||||
val fakeContinuations = methodNode.instructions.asSequence().filter(::isFakeContinuationMarker).toList()
|
||||
for (fakeContinuation in fakeContinuations) {
|
||||
methodNode.instructions.removeAll(listOf(fakeContinuation.previous.previous, fakeContinuation.previous))
|
||||
|
||||
+218
@@ -0,0 +1,218 @@
|
||||
/*
|
||||
* Copyright 2000-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.codegen.coroutines
|
||||
|
||||
import org.jetbrains.kotlin.codegen.optimization.boxing.isUnitInstance
|
||||
import org.jetbrains.kotlin.codegen.optimization.common.ControlFlowGraph
|
||||
import org.jetbrains.kotlin.codegen.optimization.common.asSequence
|
||||
import org.jetbrains.kotlin.codegen.optimization.common.isMeaningful
|
||||
import org.jetbrains.kotlin.codegen.optimization.common.removeAll
|
||||
import org.jetbrains.kotlin.codegen.optimization.transformer.MethodTransformer
|
||||
import org.jetbrains.org.objectweb.asm.Opcodes
|
||||
import org.jetbrains.org.objectweb.asm.tree.*
|
||||
|
||||
// Inliner emits a lot of locals during inlining.
|
||||
// Remove all of them since these locals are
|
||||
// 1) going to be spilled into continuation object
|
||||
// 2) breaking tail-call elimination
|
||||
class RedundantLocalsEliminationMethodTransformer : MethodTransformer() {
|
||||
lateinit var internalClassName: String
|
||||
override fun transform(internalClassName: String, methodNode: MethodNode) {
|
||||
this.internalClassName = internalClassName
|
||||
do {
|
||||
var changed = false
|
||||
changed = simpleRemove(methodNode) || changed
|
||||
changed = removeWithReplacement(methodNode) || changed
|
||||
changed = removeAloadCheckcastContinuationAstore(methodNode) || changed
|
||||
} while (changed)
|
||||
}
|
||||
|
||||
// Replace
|
||||
// GETSTATIC kotlin/Unit.INSTANCE
|
||||
// ASTORE N
|
||||
// ...
|
||||
// ALOAD N
|
||||
// with
|
||||
// ...
|
||||
// GETSTATIC kotlin/Unit.INSTANCE
|
||||
// or
|
||||
// ACONST_NULL
|
||||
// ASTORE N
|
||||
// ...
|
||||
// ALOAD N
|
||||
// with
|
||||
// ...
|
||||
// ACONST_NULL
|
||||
// or
|
||||
// ALOAD K
|
||||
// ASTORE N
|
||||
// ...
|
||||
// ALOAD N
|
||||
// with
|
||||
// ...
|
||||
// ALOAD K
|
||||
//
|
||||
// But do not remove several at a time, since the same local (for example, ALOAD 0) might be loaded and stored multiple times in
|
||||
// sequence, like
|
||||
// ALOAD 0
|
||||
// ASTORE 1
|
||||
// ALOAD 1
|
||||
// ASTORE 2
|
||||
// ALOAD 3
|
||||
// Here, it is unsafe to replace ALOAD 3 with ALOAD 1, and then already removed ALOAD 1 with ALOAD 0.
|
||||
private fun removeWithReplacement(
|
||||
methodNode: MethodNode
|
||||
): Boolean {
|
||||
val insns = findSafeAstorePredecessors(methodNode, ignoreLocalVariableTable = false) {
|
||||
it.isUnitInstance() || it.opcode == Opcodes.ACONST_NULL || it.opcode == Opcodes.ALOAD
|
||||
}
|
||||
insns.asIterable().firstOrNull { (pred, astore) ->
|
||||
val index = astore.localIndex()
|
||||
|
||||
methodNode.instructions.removeAll(listOf(pred, astore))
|
||||
|
||||
methodNode.instructions.asSequence()
|
||||
.filter { it.opcode == Opcodes.ALOAD && it.localIndex() == index }
|
||||
.toList()
|
||||
.forEach { methodNode.instructions.set(it, pred.clone()) }
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
private fun AbstractInsnNode.clone() = when (this) {
|
||||
is FieldInsnNode -> FieldInsnNode(opcode, owner, name, desc)
|
||||
is VarInsnNode -> VarInsnNode(opcode, `var`)
|
||||
is InsnNode -> InsnNode(opcode)
|
||||
is TypeInsnNode -> TypeInsnNode(opcode, desc)
|
||||
else -> error("clone of $this is not implemented yet")
|
||||
}
|
||||
|
||||
// Remove
|
||||
// ALOAD N
|
||||
// POP
|
||||
// or
|
||||
// ACONST_NULL
|
||||
// POP
|
||||
// or
|
||||
// GETSTATIC kotlin/Unit.INSTANCE
|
||||
// POP
|
||||
private fun simpleRemove(methodNode: MethodNode): Boolean {
|
||||
val insns =
|
||||
findPopPredecessors(methodNode) { it.isUnitInstance() || it.opcode == Opcodes.ACONST_NULL || it.opcode == Opcodes.ALOAD }
|
||||
for ((pred, pop) in insns) {
|
||||
methodNode.instructions.removeAll(listOf(pred, pop))
|
||||
}
|
||||
return insns.isNotEmpty()
|
||||
}
|
||||
|
||||
private fun findPopPredecessors(
|
||||
methodNode: MethodNode,
|
||||
predicate: (AbstractInsnNode) -> Boolean
|
||||
): Map<AbstractInsnNode, AbstractInsnNode> {
|
||||
val insns = methodNode.instructions.asSequence().filter { predicate(it) }.toList()
|
||||
|
||||
val cfg = ControlFlowGraph.build(methodNode)
|
||||
|
||||
val res = hashMapOf<AbstractInsnNode, AbstractInsnNode>()
|
||||
for (insn in insns) {
|
||||
val succ = findImmediateSuccessors(insn, cfg, methodNode).singleOrNull() ?: continue
|
||||
if (succ.opcode != Opcodes.POP) continue
|
||||
if (insn.opcode == Opcodes.ALOAD && methodNode.localVariables.firstOrNull { it.index == insn.localIndex() } != null) continue
|
||||
val sources = findSourceInstructions(internalClassName, methodNode, listOf(succ)).values.flatten()
|
||||
if (sources.size != 1) continue
|
||||
res[insn] = succ
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
// Replace
|
||||
// ALOAD K
|
||||
// CHECKCAST Continuation
|
||||
// ASTORE N
|
||||
// ...
|
||||
// ALOAD N
|
||||
// with
|
||||
// ...
|
||||
// ALOAD K
|
||||
// CHECKCAST Continuation
|
||||
private fun removeAloadCheckcastContinuationAstore(methodNode: MethodNode): Boolean {
|
||||
// Here we ignore the duplicates of continuation in local variable table,
|
||||
// Since it increases performance greatly.
|
||||
val insns = findSafeAstorePredecessors(methodNode, ignoreLocalVariableTable = true) {
|
||||
it.opcode == Opcodes.CHECKCAST &&
|
||||
(it as TypeInsnNode).desc == CONTINUATION_ASM_TYPE.internalName &&
|
||||
it.previous?.opcode == Opcodes.ALOAD
|
||||
}
|
||||
|
||||
for ((checkcast, astore) in insns) {
|
||||
val aload = checkcast.previous
|
||||
val index = astore.localIndex()
|
||||
|
||||
methodNode.instructions.removeAll(listOf(aload, checkcast, astore))
|
||||
|
||||
methodNode.instructions.asSequence()
|
||||
.filter { it.opcode == Opcodes.ALOAD && it.localIndex() == index }
|
||||
.toList()
|
||||
.forEach {
|
||||
methodNode.instructions.insertBefore(it, aload.clone())
|
||||
methodNode.instructions.set(it, checkcast.clone())
|
||||
}
|
||||
}
|
||||
return insns.isNotEmpty()
|
||||
}
|
||||
|
||||
private fun findSafeAstorePredecessors(
|
||||
methodNode: MethodNode,
|
||||
ignoreLocalVariableTable: Boolean,
|
||||
predicate: (AbstractInsnNode) -> Boolean
|
||||
): Map<AbstractInsnNode, AbstractInsnNode> {
|
||||
val insns = methodNode.instructions.asSequence().filter { predicate(it) }.toList()
|
||||
|
||||
val cfg = ControlFlowGraph.build(methodNode)
|
||||
val res = hashMapOf<AbstractInsnNode, AbstractInsnNode>()
|
||||
|
||||
for (insn in insns) {
|
||||
val succ = findImmediateSuccessors(insn, cfg, methodNode).singleOrNull() ?: continue
|
||||
if (succ.opcode != Opcodes.ASTORE) continue
|
||||
if (methodNode.instructions.asSequence().count {
|
||||
it.opcode == Opcodes.ASTORE && it.localIndex() == succ.localIndex()
|
||||
} != 1) continue
|
||||
if (!ignoreLocalVariableTable && methodNode.localVariables.firstOrNull { it.index == succ.localIndex() } != null) continue
|
||||
val sources = findSourceInstructions(internalClassName, methodNode, listOf(succ)).values.flatten()
|
||||
if (sources.size > 1) continue
|
||||
res[insn] = succ
|
||||
}
|
||||
|
||||
return res
|
||||
}
|
||||
|
||||
// Find all meaningful successors of insn
|
||||
private fun findImmediateSuccessors(
|
||||
insn: AbstractInsnNode,
|
||||
cfg: ControlFlowGraph,
|
||||
methodNode: MethodNode
|
||||
): Collection<AbstractInsnNode> {
|
||||
val visited = hashSetOf<AbstractInsnNode>()
|
||||
|
||||
fun dfs(current: AbstractInsnNode): Collection<AbstractInsnNode> {
|
||||
if (!visited.add(current)) return emptySet()
|
||||
|
||||
return cfg.getSuccessorsIndices(current).flatMap {
|
||||
val succ = methodNode.instructions[it]
|
||||
if (!succ.isMeaningful || succ is JumpInsnNode || succ.opcode == Opcodes.NOP) dfs(succ)
|
||||
else setOf(succ)
|
||||
}
|
||||
}
|
||||
|
||||
return dfs(insn)
|
||||
}
|
||||
|
||||
private fun AbstractInsnNode.localIndex(): Int {
|
||||
assert(this is VarInsnNode)
|
||||
return (this as VarInsnNode).`var`
|
||||
}
|
||||
}
|
||||
+12
-13
@@ -106,19 +106,6 @@ object ReturnUnitMethodTransformer : MethodTransformer() {
|
||||
private fun isSuspendingCallReturningUnit(node: AbstractInsnNode): Boolean =
|
||||
node.safeAs<MethodInsnNode>()?.next?.next?.let(::isReturnsUnitMarker) == true
|
||||
|
||||
private fun findSourceInstructions(
|
||||
internalClassName: String,
|
||||
methodNode: MethodNode,
|
||||
pops: Collection<AbstractInsnNode>
|
||||
): Map<AbstractInsnNode, Collection<AbstractInsnNode>> {
|
||||
val frames = analyze(internalClassName, methodNode, IgnoringCopyOperationSourceInterpreter())
|
||||
return pops.keysToMap {
|
||||
val index = methodNode.instructions.indexOf(it)
|
||||
if (isUnreachable(index, frames)) return@keysToMap emptySet<AbstractInsnNode>()
|
||||
frames[index].getStack(0).insns
|
||||
}
|
||||
}
|
||||
|
||||
// Find { GETSTATIC kotlin/Unit.INSTANCE, ARETURN } sequences
|
||||
// Result is list of GETSTATIC kotlin/Unit.INSTANCE instructions
|
||||
private fun findReturnUnitSequences(methodNode: MethodNode): Collection<AbstractInsnNode> =
|
||||
@@ -132,3 +119,15 @@ object ReturnUnitMethodTransformer : MethodTransformer() {
|
||||
}
|
||||
}
|
||||
|
||||
internal fun findSourceInstructions(
|
||||
internalClassName: String,
|
||||
methodNode: MethodNode,
|
||||
insns: Collection<AbstractInsnNode>
|
||||
): Map<AbstractInsnNode, Collection<AbstractInsnNode>> {
|
||||
val frames = MethodTransformer.analyze(internalClassName, methodNode, IgnoringCopyOperationSourceInterpreter())
|
||||
return insns.keysToMap {
|
||||
val index = methodNode.instructions.indexOf(it)
|
||||
if (isUnreachable(index, frames)) return@keysToMap emptySet<AbstractInsnNode>()
|
||||
frames[index].getStack(0).insns
|
||||
}
|
||||
}
|
||||
|
||||
+8
-13
@@ -177,19 +177,14 @@ private fun NewResolvedCallImpl<VariableDescriptor>.asDummyOldResolvedCall(bindi
|
||||
}
|
||||
|
||||
fun ResolvedCall<*>.isSuspendNoInlineCall(codegen: ExpressionCodegen): Boolean {
|
||||
var isCrossinline = false
|
||||
var isInlineLambda = false
|
||||
if (this is VariableAsFunctionResolvedCall) {
|
||||
variableCall.resultingDescriptor.safeAs<ValueParameterDescriptor>()?.let {
|
||||
isCrossinline = it.isCrossinline
|
||||
isInlineLambda = !isCrossinline && !it.isNoinline && codegen.context.functionDescriptor.isInline
|
||||
}
|
||||
}
|
||||
return resultingDescriptor.safeAs<FunctionDescriptor>()
|
||||
?.let {
|
||||
val inline = it.isInline || isCrossinline || isInlineLambda
|
||||
it.isSuspend && (!inline || it.isBuiltInSuspendCoroutineOrReturnInJvm() || it.isBuiltInSuspendCoroutineUninterceptedOrReturnInJvm())
|
||||
} == true
|
||||
val isInlineLambda = this.safeAs<VariableAsFunctionResolvedCall>()
|
||||
?.variableCall?.resultingDescriptor?.safeAs<ValueParameterDescriptor>()
|
||||
?.let { it.isCrossinline || (!it.isNoinline && codegen.context.functionDescriptor.isInline) } == true
|
||||
|
||||
val functionDescriptor = resultingDescriptor as? FunctionDescriptor ?: return false
|
||||
if (!functionDescriptor.isSuspend) return false
|
||||
if (functionDescriptor.isBuiltInSuspendCoroutineOrReturnInJvm() || functionDescriptor.isBuiltInSuspendCoroutineUninterceptedOrReturnInJvm()) return true
|
||||
return !(functionDescriptor.isInline || isInlineLambda)
|
||||
}
|
||||
|
||||
fun CallableDescriptor.isSuspendFunctionNotSuspensionView(): Boolean {
|
||||
|
||||
@@ -87,7 +87,8 @@ abstract class InlineCodegen<out T: BaseExpressionCodegen>(
|
||||
|
||||
protected val expressionMap = linkedMapOf<Int, LambdaInfo>()
|
||||
|
||||
var activeLambda: LambdaInfo? = null; protected set
|
||||
var activeLambda: LambdaInfo? = null
|
||||
protected set
|
||||
|
||||
private val defaultSourceMapper = sourceCompiler.lazySourceMapper
|
||||
|
||||
|
||||
@@ -10,7 +10,6 @@ import org.jetbrains.kotlin.codegen.AsmUtil
|
||||
import org.jetbrains.kotlin.codegen.ClosureCodegen
|
||||
import org.jetbrains.kotlin.codegen.StackValue
|
||||
import org.jetbrains.kotlin.codegen.coroutines.CONTINUATION_ASM_TYPE
|
||||
import org.jetbrains.kotlin.codegen.coroutines.replaceFakeContinuationsWithRealOnes
|
||||
import org.jetbrains.kotlin.codegen.inline.FieldRemapper.Companion.foldName
|
||||
import org.jetbrains.kotlin.codegen.intrinsics.IntrinsicMethods
|
||||
import org.jetbrains.kotlin.codegen.optimization.ApiVersionCallsPreprocessingMethodTransformer
|
||||
|
||||
+1
-1
@@ -25,7 +25,7 @@ class RegeneratedLambdaFieldRemapper(
|
||||
originalLambdaInternalName: String,
|
||||
override val newLambdaInternalName: String,
|
||||
parameters: Parameters,
|
||||
private val recapturedLambdas: Map<String, LambdaInfo>,
|
||||
val recapturedLambdas: Map<String, LambdaInfo>,
|
||||
remapper: FieldRemapper,
|
||||
private val isConstructor: Boolean
|
||||
) : FieldRemapper(originalLambdaInternalName, remapper, parameters) {
|
||||
|
||||
@@ -201,7 +201,7 @@ public interface Errors {
|
||||
DiagnosticFactory2<PsiElement, KtModifierKeywordToken, String> DEPRECATED_MODIFIER_CONTAINING_DECLARATION = DiagnosticFactory2.create(WARNING);
|
||||
DiagnosticFactory1<PsiElement, KtModifierKeywordToken> ILLEGAL_INLINE_PARAMETER_MODIFIER = DiagnosticFactory1.create(ERROR);
|
||||
DiagnosticFactory0<KtParameter> INLINE_SUSPEND_FUNCTION_TYPE_UNSUPPORTED = DiagnosticFactory0.create(ERROR);
|
||||
DiagnosticFactory0<KtParameter> REDUNDANT_INLINE_SUSPEND_FUNCTION_TYPE = DiagnosticFactory0.create(WARNING);
|
||||
DiagnosticFactory0<PsiElement> REDUNDANT_INLINE_SUSPEND_FUNCTION_TYPE = DiagnosticFactory0.create(WARNING);
|
||||
DiagnosticFactory1<KtAnnotationEntry, String> WRONG_ANNOTATION_TARGET = DiagnosticFactory1.create(ERROR);
|
||||
DiagnosticFactory2<KtAnnotationEntry, String, String> WRONG_ANNOTATION_TARGET_WITH_USE_SITE_TARGET = DiagnosticFactory2.create(ERROR);
|
||||
DiagnosticFactory1<KtAnnotationEntry, String> WRONG_ANNOTATION_TARGET_WITH_USE_SITE_TARGET_ON_TYPE = DiagnosticFactory1.create(WARNING);
|
||||
|
||||
+2
-2
@@ -122,8 +122,8 @@ public class DefaultErrorMessages {
|
||||
MAP.put(WRONG_MODIFIER_CONTAINING_DECLARATION, "Modifier ''{0}'' is not applicable inside ''{1}''", TO_STRING, TO_STRING);
|
||||
MAP.put(DEPRECATED_MODIFIER_CONTAINING_DECLARATION, "Modifier ''{0}'' is deprecated inside ''{1}''", TO_STRING, TO_STRING);
|
||||
MAP.put(ILLEGAL_INLINE_PARAMETER_MODIFIER, "Modifier ''{0}'' is allowed only for function parameters of an inline function", TO_STRING);
|
||||
MAP.put(INLINE_SUSPEND_FUNCTION_TYPE_UNSUPPORTED, "Inline lambda parameters of suspend function type are not supported. Add 'noinline' or 'crossinline' modifier.");
|
||||
MAP.put(REDUNDANT_INLINE_SUSPEND_FUNCTION_TYPE, "Redundant suspend modifier of inline lambda parameters of suspend function type.");
|
||||
MAP.put(INLINE_SUSPEND_FUNCTION_TYPE_UNSUPPORTED, "Suspend inline lambda parameters of non-suspend function type are not supported. Add 'noinline' or 'crossinline' modifier.");
|
||||
MAP.put(REDUNDANT_INLINE_SUSPEND_FUNCTION_TYPE, "Redundant 'suspend' modifier: lambda parameters of suspend function type uses existing continuation.");
|
||||
MAP.put(WRONG_ANNOTATION_TARGET, "This annotation is not applicable to target ''{0}''", TO_STRING);
|
||||
MAP.put(WRONG_ANNOTATION_TARGET_WITH_USE_SITE_TARGET, "This annotation is not applicable to target ''{0}'' and use site target ''@{1}''", TO_STRING, TO_STRING);
|
||||
MAP.put(WRONG_ANNOTATION_TARGET_WITH_USE_SITE_TARGET_ON_TYPE,
|
||||
|
||||
@@ -17,13 +17,12 @@
|
||||
package org.jetbrains.kotlin.resolve.calls.checkers
|
||||
|
||||
import com.intellij.psi.PsiElement
|
||||
import org.jetbrains.kotlin.builtins.isFunctionType
|
||||
import org.jetbrains.kotlin.builtins.isSuspendFunctionType
|
||||
import org.jetbrains.kotlin.builtins.isBuiltinFunctionalType
|
||||
import org.jetbrains.kotlin.config.LanguageFeature
|
||||
import org.jetbrains.kotlin.contracts.parsing.isFromContractDsl
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.diagnostics.Errors
|
||||
import org.jetbrains.kotlin.diagnostics.Errors.*
|
||||
import org.jetbrains.kotlin.contracts.parsing.isFromContractDsl
|
||||
import org.jetbrains.kotlin.lexer.KtTokens
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.psi.psiUtil.getParentOfType
|
||||
@@ -239,8 +238,7 @@ internal class InlineChecker(private val descriptor: FunctionDescriptor) : CallC
|
||||
|
||||
val containingDeclaration = descriptor.getContainingDeclaration()
|
||||
val isInvoke = descriptor.getName() == OperatorNameConventions.INVOKE &&
|
||||
containingDeclaration is ClassDescriptor &&
|
||||
(containingDeclaration.defaultType.isFunctionType || containingDeclaration.defaultType.isSuspendFunctionType)
|
||||
containingDeclaration is ClassDescriptor && containingDeclaration.defaultType.isBuiltinFunctionalType
|
||||
|
||||
return isInvoke || InlineUtil.isInline(descriptor)
|
||||
}
|
||||
|
||||
+6
-3
@@ -22,6 +22,7 @@ import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
||||
import org.jetbrains.kotlin.diagnostics.DiagnosticSink
|
||||
import org.jetbrains.kotlin.diagnostics.Errors
|
||||
import org.jetbrains.kotlin.lexer.KtModifierKeywordToken
|
||||
import org.jetbrains.kotlin.lexer.KtToken
|
||||
import org.jetbrains.kotlin.lexer.KtTokens
|
||||
import org.jetbrains.kotlin.psi.KtDeclaration
|
||||
import org.jetbrains.kotlin.psi.KtFunction
|
||||
@@ -32,7 +33,6 @@ object InlineParameterChecker : DeclarationChecker {
|
||||
override fun check(declaration: KtDeclaration, descriptor: DeclarationDescriptor, context: DeclarationCheckerContext) {
|
||||
if (declaration is KtFunction) {
|
||||
val inline = declaration.hasModifier(KtTokens.INLINE_KEYWORD)
|
||||
val suspend = declaration.hasModifier(KtTokens.SUSPEND_KEYWORD)
|
||||
for (parameter in declaration.valueParameters) {
|
||||
val parameterDescriptor = context.trace.get(BindingContext.VALUE_PARAMETER, parameter)
|
||||
if (!inline || (parameterDescriptor != null && !parameterDescriptor.type.isBuiltinFunctionalType)) {
|
||||
@@ -43,8 +43,11 @@ object InlineParameterChecker : DeclarationChecker {
|
||||
!parameter.hasModifier(KtTokens.CROSSINLINE_KEYWORD) &&
|
||||
parameterDescriptor?.type?.isSuspendFunctionType == true
|
||||
) {
|
||||
if (suspend) {
|
||||
context.trace.report(Errors.REDUNDANT_INLINE_SUSPEND_FUNCTION_TYPE.on(parameter))
|
||||
if (declaration.hasModifier(KtTokens.SUSPEND_KEYWORD)) {
|
||||
val typeReference = parameter.typeReference!!
|
||||
val modifierList = typeReference.modifierList!!
|
||||
val modifier = modifierList.getModifier(KtTokens.SUSPEND_KEYWORD)!!
|
||||
context.trace.report(Errors.REDUNDANT_INLINE_SUSPEND_FUNCTION_TYPE.on(modifier))
|
||||
} else {
|
||||
context.trace.report(Errors.INLINE_SUSPEND_FUNCTION_TYPE_UNSUPPORTED.on(parameter))
|
||||
}
|
||||
|
||||
@@ -36,8 +36,7 @@ public class InlineUtil {
|
||||
public static boolean isInlineParameterExceptNullability(@NotNull ParameterDescriptor valueParameterOrReceiver) {
|
||||
return !(valueParameterOrReceiver instanceof ValueParameterDescriptor
|
||||
&& ((ValueParameterDescriptor) valueParameterOrReceiver).isNoinline()) &&
|
||||
(FunctionTypesKt.isFunctionType(valueParameterOrReceiver.getOriginal().getType()) ||
|
||||
FunctionTypesKt.isSuspendFunctionType(valueParameterOrReceiver.getOriginal().getType()));
|
||||
FunctionTypesKt.isBuiltinFunctionalType(valueParameterOrReceiver.getOriginal().getType());
|
||||
}
|
||||
|
||||
public static boolean isInlineParameter(@NotNull ParameterDescriptor valueParameterOrReceiver) {
|
||||
|
||||
+74
@@ -0,0 +1,74 @@
|
||||
// IGNORE_BACKEND: JS
|
||||
// WITH_RUNTIME
|
||||
// WITH_COROUTINES
|
||||
// CHECK_BYTECODE_LISTING
|
||||
import helpers.*
|
||||
import kotlin.coroutines.experimental.*
|
||||
import kotlin.coroutines.experimental.intrinsics.*
|
||||
|
||||
interface SourceCrossinline<out E> {
|
||||
suspend fun consume(sink: Sink<E>)
|
||||
companion object Factory
|
||||
}
|
||||
|
||||
interface Sink<in E> {
|
||||
suspend fun send(item: E)
|
||||
fun close(cause: Throwable?)
|
||||
}
|
||||
|
||||
inline fun <E> source(crossinline action: suspend Sink<E>.() -> Unit): SourceCrossinline<E> = object : SourceCrossinline<E> {
|
||||
override suspend fun consume(sink: Sink<E>) {
|
||||
var cause: Throwable? = null
|
||||
try {
|
||||
action(sink)
|
||||
} catch (e: Throwable) {
|
||||
cause = e
|
||||
}
|
||||
sink.close(cause)
|
||||
}
|
||||
}
|
||||
|
||||
fun SourceCrossinline.Factory.range(start: Int, count: Int): SourceCrossinline<Int> = source<Int> {
|
||||
for (i in start until (start + count)) {
|
||||
send(i)
|
||||
}
|
||||
}
|
||||
|
||||
suspend inline fun <E> SourceCrossinline<E>.consumeEach(crossinline action: suspend (E) -> Unit) {
|
||||
consume(object : Sink<E> {
|
||||
override suspend fun send(item: E) = action(item)
|
||||
override fun close(cause: Throwable?) { cause?.let { throw it } }
|
||||
})
|
||||
}
|
||||
|
||||
suspend inline fun <E, R> SourceCrossinline<E>.fold(initial: R, crossinline operation: suspend (acc: R, E) -> R): R {
|
||||
var acc = initial
|
||||
consumeEach {
|
||||
acc = operation(acc, it)
|
||||
}
|
||||
return acc
|
||||
}
|
||||
|
||||
inline fun <E> SourceCrossinline<E>.filter(crossinline predicate: (E) -> Boolean) = source<E> {
|
||||
consumeEach {
|
||||
if (predicate(it)) send(it)
|
||||
}
|
||||
}
|
||||
|
||||
fun builder(c: suspend () -> Unit) {
|
||||
c.startCoroutine(EmptyContinuation)
|
||||
}
|
||||
|
||||
fun Int.isGood() = this % 4 == 0
|
||||
|
||||
fun box(): String {
|
||||
var res = 0
|
||||
builder {
|
||||
res = SourceCrossinline
|
||||
.range(1, 11)
|
||||
.filter { it.isGood() }
|
||||
.fold(0, { a, b -> a + b })
|
||||
}
|
||||
if (res != 12) return "FAIL"
|
||||
return "OK"
|
||||
}
|
||||
+352
@@ -0,0 +1,352 @@
|
||||
@kotlin.Metadata
|
||||
public final class CrossinlineKt$box$1$doResume$$inlined$filter$1$1 {
|
||||
field L$0: java.lang.Object
|
||||
field L$1: java.lang.Object
|
||||
field L$2: java.lang.Object
|
||||
field L$3: java.lang.Object
|
||||
field L$4: java.lang.Object
|
||||
field L$5: java.lang.Object
|
||||
synthetic field data: java.lang.Object
|
||||
synthetic field exception: java.lang.Throwable
|
||||
synthetic final field this$0: CrossinlineKt$box$1$doResume$$inlined$filter$1
|
||||
inner class CrossinlineKt$box$1$doResume$$inlined$filter$1
|
||||
inner class CrossinlineKt$box$1$doResume$$inlined$filter$1$1
|
||||
public method <init>(p0: CrossinlineKt$box$1$doResume$$inlined$filter$1, p1: kotlin.coroutines.experimental.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 CrossinlineKt$box$1$doResume$$inlined$filter$1$2$1 {
|
||||
field L$0: java.lang.Object
|
||||
field L$1: java.lang.Object
|
||||
field L$2: java.lang.Object
|
||||
synthetic field data: java.lang.Object
|
||||
synthetic field exception: java.lang.Throwable
|
||||
synthetic final field this$0: CrossinlineKt$box$1$doResume$$inlined$filter$1$2
|
||||
inner class CrossinlineKt$box$1$doResume$$inlined$filter$1$2
|
||||
inner class CrossinlineKt$box$1$doResume$$inlined$filter$1$2$1
|
||||
public method <init>(p0: CrossinlineKt$box$1$doResume$$inlined$filter$1$2, p1: kotlin.coroutines.experimental.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 CrossinlineKt$box$1$doResume$$inlined$filter$1$2 {
|
||||
synthetic final field receiver$0$inlined: Sink
|
||||
synthetic final field this$0: CrossinlineKt$box$1$doResume$$inlined$filter$1
|
||||
inner class CrossinlineKt$box$1$doResume$$inlined$filter$1$2
|
||||
inner class CrossinlineKt$box$1$doResume$$inlined$filter$1$2$1
|
||||
public method <init>(p0: Sink, p1: CrossinlineKt$box$1$doResume$$inlined$filter$1): void
|
||||
public method close(@org.jetbrains.annotations.Nullable p0: java.lang.Throwable): void
|
||||
public @org.jetbrains.annotations.Nullable method send(p0: java.lang.Object, @org.jetbrains.annotations.NotNull p1: kotlin.coroutines.experimental.Continuation): java.lang.Object
|
||||
}
|
||||
|
||||
@kotlin.Metadata
|
||||
public final class CrossinlineKt$box$1$doResume$$inlined$filter$1 {
|
||||
synthetic final field receiver$0$inlined: SourceCrossinline
|
||||
inner class CrossinlineKt$box$1$doResume$$inlined$filter$1
|
||||
inner class CrossinlineKt$box$1$doResume$$inlined$filter$1$1
|
||||
public method <init>(p0: SourceCrossinline): void
|
||||
public @org.jetbrains.annotations.Nullable method consume(@org.jetbrains.annotations.NotNull p0: Sink, @org.jetbrains.annotations.NotNull p1: kotlin.coroutines.experimental.Continuation): java.lang.Object
|
||||
}
|
||||
|
||||
@kotlin.Metadata
|
||||
public final class CrossinlineKt$box$1$doResume$$inlined$fold$1 {
|
||||
synthetic final field $acc$inlined: kotlin.jvm.internal.Ref$ObjectRef
|
||||
inner class CrossinlineKt$box$1$doResume$$inlined$fold$1
|
||||
inner class CrossinlineKt$box$1$fold$$inlined$consumeEach$1$1
|
||||
public method <init>(p0: kotlin.jvm.internal.Ref$ObjectRef): void
|
||||
public method close(@org.jetbrains.annotations.Nullable p0: java.lang.Throwable): void
|
||||
public @org.jetbrains.annotations.Nullable method send(p0: java.lang.Object, @org.jetbrains.annotations.NotNull p1: kotlin.coroutines.experimental.Continuation): java.lang.Object
|
||||
}
|
||||
|
||||
@kotlin.Metadata
|
||||
public final class CrossinlineKt$box$1$filter$$inlined$source$1$1 {
|
||||
field L$0: java.lang.Object
|
||||
field L$1: java.lang.Object
|
||||
field L$2: java.lang.Object
|
||||
field L$3: java.lang.Object
|
||||
field L$4: java.lang.Object
|
||||
field L$5: java.lang.Object
|
||||
synthetic field data: java.lang.Object
|
||||
synthetic field exception: java.lang.Throwable
|
||||
synthetic final field this$0: CrossinlineKt$box$1$filter$$inlined$source$1
|
||||
inner class CrossinlineKt$box$1$filter$$inlined$source$1
|
||||
inner class CrossinlineKt$box$1$filter$$inlined$source$1$1
|
||||
public method <init>(p0: CrossinlineKt$box$1$filter$$inlined$source$1, p1: kotlin.coroutines.experimental.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 CrossinlineKt$box$1$filter$$inlined$source$1$lambda$1$1 {
|
||||
field L$0: java.lang.Object
|
||||
field L$1: java.lang.Object
|
||||
field L$2: java.lang.Object
|
||||
synthetic field data: java.lang.Object
|
||||
synthetic field exception: java.lang.Throwable
|
||||
synthetic final field this$0: CrossinlineKt$box$1$filter$$inlined$source$1$lambda$1
|
||||
inner class CrossinlineKt$box$1$filter$$inlined$source$1$lambda$1
|
||||
inner class CrossinlineKt$box$1$filter$$inlined$source$1$lambda$1$1
|
||||
public method <init>(p0: CrossinlineKt$box$1$filter$$inlined$source$1$lambda$1, p1: kotlin.coroutines.experimental.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 CrossinlineKt$box$1$filter$$inlined$source$1$lambda$1 {
|
||||
synthetic final field receiver$0$inlined: Sink
|
||||
synthetic final field this$0: CrossinlineKt$box$1$filter$$inlined$source$1
|
||||
inner class CrossinlineKt$box$1$filter$$inlined$source$1$lambda$1
|
||||
inner class CrossinlineKt$box$1$filter$$inlined$source$1$lambda$1$1
|
||||
public method <init>(p0: Sink, p1: CrossinlineKt$box$1$filter$$inlined$source$1): void
|
||||
public method close(@org.jetbrains.annotations.Nullable p0: java.lang.Throwable): void
|
||||
public @org.jetbrains.annotations.Nullable method send(p0: java.lang.Object, @org.jetbrains.annotations.NotNull p1: kotlin.coroutines.experimental.Continuation): java.lang.Object
|
||||
}
|
||||
|
||||
@kotlin.Metadata
|
||||
public final class CrossinlineKt$box$1$filter$$inlined$source$1 {
|
||||
synthetic final field $predicate$inlined: kotlin.jvm.functions.Function1
|
||||
synthetic final field receiver$0$inlined: SourceCrossinline
|
||||
inner class CrossinlineKt$box$1$filter$$inlined$source$1
|
||||
inner class CrossinlineKt$box$1$filter$$inlined$source$1$1
|
||||
public method <init>(p0: SourceCrossinline, p1: kotlin.jvm.functions.Function1): void
|
||||
public @org.jetbrains.annotations.Nullable method consume(@org.jetbrains.annotations.NotNull p0: Sink, @org.jetbrains.annotations.NotNull p1: kotlin.coroutines.experimental.Continuation): java.lang.Object
|
||||
}
|
||||
|
||||
@kotlin.Metadata
|
||||
public final class CrossinlineKt$box$1$fold$$inlined$consumeEach$1$1 {
|
||||
synthetic field data: java.lang.Object
|
||||
synthetic field exception: java.lang.Throwable
|
||||
synthetic final field this$0: CrossinlineKt$box$1$fold$$inlined$consumeEach$1
|
||||
inner class CrossinlineKt$box$1$fold$$inlined$consumeEach$1
|
||||
inner class CrossinlineKt$box$1$fold$$inlined$consumeEach$1$1
|
||||
public method <init>(p0: CrossinlineKt$box$1$fold$$inlined$consumeEach$1, p1: kotlin.coroutines.experimental.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 CrossinlineKt$box$1$fold$$inlined$consumeEach$1 {
|
||||
synthetic final field $acc$inlined: kotlin.jvm.internal.Ref$ObjectRef
|
||||
synthetic final field $operation$inlined: kotlin.jvm.functions.Function3
|
||||
inner class CrossinlineKt$box$1$fold$$inlined$consumeEach$1
|
||||
inner class CrossinlineKt$box$1$fold$$inlined$consumeEach$1$1
|
||||
public method <init>(p0: kotlin.jvm.internal.Ref$ObjectRef, p1: kotlin.jvm.functions.Function3): void
|
||||
public method close(@org.jetbrains.annotations.Nullable p0: java.lang.Throwable): void
|
||||
public @org.jetbrains.annotations.Nullable method send(p0: java.lang.Object, @org.jetbrains.annotations.NotNull p1: kotlin.coroutines.experimental.Continuation): java.lang.Object
|
||||
}
|
||||
|
||||
@kotlin.Metadata
|
||||
final class CrossinlineKt$box$1 {
|
||||
synthetic final field $res: kotlin.jvm.internal.Ref$IntRef
|
||||
field L$0: java.lang.Object
|
||||
field L$1: java.lang.Object
|
||||
field L$2: java.lang.Object
|
||||
field L$3: java.lang.Object
|
||||
field L$4: java.lang.Object
|
||||
inner class CrossinlineKt$box$1
|
||||
method <init>(p0: kotlin.jvm.internal.Ref$IntRef, p1: kotlin.coroutines.experimental.Continuation): void
|
||||
public final @org.jetbrains.annotations.NotNull method create(@org.jetbrains.annotations.NotNull p0: kotlin.coroutines.experimental.Continuation): kotlin.coroutines.experimental.Continuation
|
||||
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.NotNull p0: kotlin.coroutines.experimental.Continuation): java.lang.Object
|
||||
public synthetic method invoke(p0: java.lang.Object): java.lang.Object
|
||||
}
|
||||
|
||||
@kotlin.Metadata
|
||||
public final class CrossinlineKt$consumeEach$2$send$1 {
|
||||
synthetic field data: java.lang.Object
|
||||
synthetic field exception: java.lang.Throwable
|
||||
synthetic final field this$0: CrossinlineKt$consumeEach$2
|
||||
inner class CrossinlineKt$consumeEach$2
|
||||
inner class CrossinlineKt$consumeEach$2$send$1
|
||||
public method <init>(p0: CrossinlineKt$consumeEach$2, p1: kotlin.coroutines.experimental.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 CrossinlineKt$consumeEach$2 {
|
||||
synthetic final field $action: kotlin.jvm.functions.Function2
|
||||
inner class CrossinlineKt$consumeEach$2
|
||||
inner class CrossinlineKt$consumeEach$2$send$1
|
||||
public method <init>(p0: kotlin.jvm.functions.Function2): void
|
||||
public method close(@org.jetbrains.annotations.Nullable p0: java.lang.Throwable): void
|
||||
public @org.jetbrains.annotations.Nullable method send(p0: java.lang.Object, @org.jetbrains.annotations.NotNull p1: kotlin.coroutines.experimental.Continuation): java.lang.Object
|
||||
}
|
||||
|
||||
@kotlin.Metadata
|
||||
public final class CrossinlineKt$filter$$inlined$source$1$1 {
|
||||
field L$0: java.lang.Object
|
||||
field L$1: java.lang.Object
|
||||
field L$2: java.lang.Object
|
||||
field L$3: java.lang.Object
|
||||
field L$4: java.lang.Object
|
||||
field L$5: java.lang.Object
|
||||
synthetic field data: java.lang.Object
|
||||
synthetic field exception: java.lang.Throwable
|
||||
synthetic final field this$0: CrossinlineKt$filter$$inlined$source$1
|
||||
inner class CrossinlineKt$filter$$inlined$source$1
|
||||
inner class CrossinlineKt$filter$$inlined$source$1$1
|
||||
public method <init>(p0: CrossinlineKt$filter$$inlined$source$1, p1: kotlin.coroutines.experimental.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 CrossinlineKt$filter$$inlined$source$1$lambda$1$1 {
|
||||
field L$0: java.lang.Object
|
||||
field L$1: java.lang.Object
|
||||
field L$2: java.lang.Object
|
||||
synthetic field data: java.lang.Object
|
||||
synthetic field exception: java.lang.Throwable
|
||||
synthetic final field this$0: CrossinlineKt$filter$$inlined$source$1$lambda$1
|
||||
inner class CrossinlineKt$filter$$inlined$source$1$lambda$1
|
||||
inner class CrossinlineKt$filter$$inlined$source$1$lambda$1$1
|
||||
public method <init>(p0: CrossinlineKt$filter$$inlined$source$1$lambda$1, p1: kotlin.coroutines.experimental.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 CrossinlineKt$filter$$inlined$source$1$lambda$1 {
|
||||
synthetic final field receiver$0$inlined: Sink
|
||||
synthetic final field this$0: CrossinlineKt$filter$$inlined$source$1
|
||||
inner class CrossinlineKt$filter$$inlined$source$1$lambda$1
|
||||
inner class CrossinlineKt$filter$$inlined$source$1$lambda$1$1
|
||||
public method <init>(p0: Sink, p1: CrossinlineKt$filter$$inlined$source$1): void
|
||||
public method close(@org.jetbrains.annotations.Nullable p0: java.lang.Throwable): void
|
||||
public @org.jetbrains.annotations.Nullable method send(p0: java.lang.Object, @org.jetbrains.annotations.NotNull p1: kotlin.coroutines.experimental.Continuation): java.lang.Object
|
||||
}
|
||||
|
||||
@kotlin.Metadata
|
||||
public final class CrossinlineKt$filter$$inlined$source$1 {
|
||||
synthetic final field $predicate$inlined: kotlin.jvm.functions.Function1
|
||||
synthetic final field receiver$0$inlined: SourceCrossinline
|
||||
inner class CrossinlineKt$filter$$inlined$source$1
|
||||
inner class CrossinlineKt$filter$$inlined$source$1$1
|
||||
public method <init>(p0: SourceCrossinline, p1: kotlin.jvm.functions.Function1): void
|
||||
public @org.jetbrains.annotations.Nullable method consume(@org.jetbrains.annotations.NotNull p0: Sink, @org.jetbrains.annotations.NotNull p1: kotlin.coroutines.experimental.Continuation): java.lang.Object
|
||||
}
|
||||
|
||||
@kotlin.Metadata
|
||||
public final class CrossinlineKt$fold$$inlined$consumeEach$1$1 {
|
||||
synthetic field data: java.lang.Object
|
||||
synthetic field exception: java.lang.Throwable
|
||||
synthetic final field this$0: CrossinlineKt$fold$$inlined$consumeEach$1
|
||||
inner class CrossinlineKt$fold$$inlined$consumeEach$1
|
||||
inner class CrossinlineKt$fold$$inlined$consumeEach$1$1
|
||||
public method <init>(p0: CrossinlineKt$fold$$inlined$consumeEach$1, p1: kotlin.coroutines.experimental.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 CrossinlineKt$fold$$inlined$consumeEach$1 {
|
||||
synthetic final field $acc$inlined: kotlin.jvm.internal.Ref$ObjectRef
|
||||
synthetic final field $operation$inlined: kotlin.jvm.functions.Function3
|
||||
inner class CrossinlineKt$fold$$inlined$consumeEach$1
|
||||
inner class CrossinlineKt$fold$$inlined$consumeEach$1$1
|
||||
public method <init>(p0: kotlin.jvm.internal.Ref$ObjectRef, p1: kotlin.jvm.functions.Function3): void
|
||||
public method close(@org.jetbrains.annotations.Nullable p0: java.lang.Throwable): void
|
||||
public @org.jetbrains.annotations.Nullable method send(p0: java.lang.Object, @org.jetbrains.annotations.NotNull p1: kotlin.coroutines.experimental.Continuation): java.lang.Object
|
||||
}
|
||||
|
||||
@kotlin.Metadata
|
||||
public final class CrossinlineKt$range$$inlined$source$1$1 {
|
||||
field I$0: int
|
||||
field I$1: int
|
||||
field L$0: java.lang.Object
|
||||
field L$1: java.lang.Object
|
||||
field L$2: java.lang.Object
|
||||
field L$3: java.lang.Object
|
||||
field L$4: java.lang.Object
|
||||
synthetic field data: java.lang.Object
|
||||
synthetic field exception: java.lang.Throwable
|
||||
synthetic final field this$0: CrossinlineKt$range$$inlined$source$1
|
||||
inner class CrossinlineKt$range$$inlined$source$1
|
||||
inner class CrossinlineKt$range$$inlined$source$1$1
|
||||
public method <init>(p0: CrossinlineKt$range$$inlined$source$1, p1: kotlin.coroutines.experimental.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 CrossinlineKt$range$$inlined$source$1 {
|
||||
synthetic final field $count$inlined: int
|
||||
synthetic final field $start$inlined: int
|
||||
inner class CrossinlineKt$range$$inlined$source$1
|
||||
inner class CrossinlineKt$range$$inlined$source$1$1
|
||||
public method <init>(p0: int, p1: int): void
|
||||
public @org.jetbrains.annotations.Nullable method consume(@org.jetbrains.annotations.NotNull p0: Sink, @org.jetbrains.annotations.NotNull p1: kotlin.coroutines.experimental.Continuation): java.lang.Object
|
||||
}
|
||||
|
||||
@kotlin.Metadata
|
||||
public final class CrossinlineKt$source$1$consume$1 {
|
||||
synthetic field data: java.lang.Object
|
||||
synthetic field exception: java.lang.Throwable
|
||||
synthetic final field this$0: CrossinlineKt$source$1
|
||||
inner class CrossinlineKt$source$1
|
||||
inner class CrossinlineKt$source$1$consume$1
|
||||
public method <init>(p0: CrossinlineKt$source$1, p1: kotlin.coroutines.experimental.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 CrossinlineKt$source$1 {
|
||||
synthetic final field $action: kotlin.jvm.functions.Function2
|
||||
inner class CrossinlineKt$source$1
|
||||
inner class CrossinlineKt$source$1$consume$1
|
||||
public method <init>(p0: kotlin.jvm.functions.Function2): void
|
||||
public @org.jetbrains.annotations.Nullable method consume(@org.jetbrains.annotations.NotNull p0: Sink, @org.jetbrains.annotations.NotNull p1: kotlin.coroutines.experimental.Continuation): java.lang.Object
|
||||
}
|
||||
|
||||
@kotlin.Metadata
|
||||
public final class CrossinlineKt {
|
||||
inner class CrossinlineKt$box$1
|
||||
inner class CrossinlineKt$consumeEach$2
|
||||
inner class CrossinlineKt$source$1
|
||||
public final static @org.jetbrains.annotations.NotNull method box(): java.lang.String
|
||||
public final static method builder(@org.jetbrains.annotations.NotNull p0: kotlin.jvm.functions.Function1): void
|
||||
private final static method consumeEach(@org.jetbrains.annotations.NotNull p0: SourceCrossinline, p1: kotlin.jvm.functions.Function2, p2: kotlin.coroutines.experimental.Continuation): java.lang.Object
|
||||
public final static @org.jetbrains.annotations.NotNull method filter(@org.jetbrains.annotations.NotNull p0: SourceCrossinline, @org.jetbrains.annotations.NotNull p1: kotlin.jvm.functions.Function1): SourceCrossinline
|
||||
private final static method fold(@org.jetbrains.annotations.NotNull p0: SourceCrossinline, p1: java.lang.Object, p2: kotlin.jvm.functions.Function3, p3: kotlin.coroutines.experimental.Continuation): java.lang.Object
|
||||
public final static method isGood(p0: int): boolean
|
||||
public final static @org.jetbrains.annotations.NotNull method range(@org.jetbrains.annotations.NotNull p0: SourceCrossinline$Factory, p1: int, p2: int): SourceCrossinline
|
||||
public final static @org.jetbrains.annotations.NotNull method source(@org.jetbrains.annotations.NotNull p0: kotlin.jvm.functions.Function2): SourceCrossinline
|
||||
}
|
||||
|
||||
@kotlin.Metadata
|
||||
public interface Sink {
|
||||
public abstract method close(@org.jetbrains.annotations.Nullable p0: java.lang.Throwable): void
|
||||
public abstract @org.jetbrains.annotations.Nullable method send(p0: java.lang.Object, @org.jetbrains.annotations.NotNull p1: kotlin.coroutines.experimental.Continuation): java.lang.Object
|
||||
}
|
||||
|
||||
@kotlin.Metadata
|
||||
public final class SourceCrossinline$Factory {
|
||||
synthetic final static field $$INSTANCE: SourceCrossinline$Factory
|
||||
inner class SourceCrossinline$Factory
|
||||
static method <clinit>(): void
|
||||
private method <init>(): void
|
||||
}
|
||||
|
||||
@kotlin.Metadata
|
||||
public interface SourceCrossinline {
|
||||
public final static field Factory: SourceCrossinline$Factory
|
||||
inner class SourceCrossinline$Factory
|
||||
static method <clinit>(): void
|
||||
public abstract @org.jetbrains.annotations.Nullable method consume(@org.jetbrains.annotations.NotNull p0: Sink, @org.jetbrains.annotations.NotNull p1: kotlin.coroutines.experimental.Continuation): java.lang.Object
|
||||
}
|
||||
Vendored
-1
@@ -14,7 +14,6 @@ final class InlineWithoutStateMachineKt$box$1 {
|
||||
@kotlin.Metadata
|
||||
final class InlineWithoutStateMachineKt$complexSuspend$1 {
|
||||
field L$0: java.lang.Object
|
||||
field L$1: java.lang.Object
|
||||
synthetic field data: java.lang.Object
|
||||
synthetic field exception: java.lang.Throwable
|
||||
inner class InlineWithoutStateMachineKt$complexSuspend$1
|
||||
|
||||
@@ -15,6 +15,7 @@ suspend inline fun test2(crossinline c: suspend () -> Unit) {
|
||||
// FILE: box.kt
|
||||
|
||||
import kotlin.coroutines.experimental.*
|
||||
import kotlin.coroutines.experimental.intrinsics.*
|
||||
|
||||
fun builder(c: suspend () -> Unit) {
|
||||
c.startCoroutine(object: Continuation<Unit> {
|
||||
@@ -30,7 +31,10 @@ fun builder(c: suspend () -> Unit) {
|
||||
})
|
||||
}
|
||||
|
||||
suspend fun calculate() = "OK"
|
||||
suspend fun calculate() = suspendCoroutineOrReturn<String> {
|
||||
it.resume("OK")
|
||||
COROUTINE_SUSPENDED
|
||||
}
|
||||
|
||||
fun box() : String {
|
||||
var res = "FAIL 1"
|
||||
|
||||
@@ -25,5 +25,8 @@ fun box() : String {
|
||||
return res
|
||||
}
|
||||
|
||||
// When we generate code of suspend function returning unit call
|
||||
// we surround it with return unit markers.
|
||||
// While denerating state machine, we remove them.
|
||||
// 0 ICONST_2
|
||||
// 0 ICONST_3
|
||||
-2
@@ -1,2 +0,0 @@
|
||||
// SKIP_TXT
|
||||
inline fun foo(crossinline <!WRONG_MODIFIER_TARGET!>suspend<!> <!UNUSED_PARAMETER!>c<!>: () -> Unit) {}
|
||||
compiler/testData/diagnostics/testsWithStdLib/coroutines/inlineCrossinline/inlineSuspendOfSuspend.kt
Vendored
+1
-1
@@ -20,7 +20,7 @@ interface SuspendRunnable {
|
||||
// Block is NOT allowed to be called from nested classes/lambdas (as common crossinlines)
|
||||
// It is NOT possible to call startCoroutine on the parameter
|
||||
// suspend calls possible inside lambda matching to the parameter
|
||||
suspend inline fun test(<!REDUNDANT_INLINE_SUSPEND_FUNCTION_TYPE!>c: suspend () -> Unit<!>) {
|
||||
suspend inline fun test(c: <!REDUNDANT_INLINE_SUSPEND_FUNCTION_TYPE!>suspend<!> () -> Unit) {
|
||||
c()
|
||||
val o = object: SuspendRunnable {
|
||||
override suspend fun run() {
|
||||
|
||||
+1
-1
@@ -5,7 +5,7 @@ inline fun foo2(crossinline x: suspend () -> Unit) {}
|
||||
<!NOTHING_TO_INLINE!>inline<!> fun foo3(noinline x: suspend () -> Unit) {}
|
||||
<!NOTHING_TO_INLINE!>inline<!> fun foo4(<!INCOMPATIBLE_MODIFIERS!>noinline<!> <!INCOMPATIBLE_MODIFIERS!>crossinline<!> x: suspend () -> Unit) {}
|
||||
|
||||
suspend inline fun bar1(<!REDUNDANT_INLINE_SUSPEND_FUNCTION_TYPE!>x: suspend () -> Unit<!>) {}
|
||||
suspend inline fun bar1(x: <!REDUNDANT_INLINE_SUSPEND_FUNCTION_TYPE!>suspend<!> () -> Unit) {}
|
||||
suspend inline fun bar2(crossinline x: suspend () -> Unit) {}
|
||||
suspend inline fun bar3(noinline x: suspend () -> Unit) {}
|
||||
suspend inline fun bar4(<!INCOMPATIBLE_MODIFIERS!>noinline<!> <!INCOMPATIBLE_MODIFIERS!>crossinline<!> x: suspend () -> Unit) {}
|
||||
|
||||
Generated
+6
@@ -6683,6 +6683,12 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
|
||||
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/coroutines/tailCallOptimizations"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JVM, true);
|
||||
}
|
||||
|
||||
@TestMetadata("crossinline.kt")
|
||||
public void testCrossinline() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/tailCallOptimizations/crossinline.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("inlineWithStateMachine.kt")
|
||||
public void testInlineWithStateMachine() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/tailCallOptimizations/inlineWithStateMachine.kt");
|
||||
|
||||
-6
@@ -1559,12 +1559,6 @@ public class DiagnosticsTestWithStdLibGenerated extends AbstractDiagnosticsTestW
|
||||
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/diagnostics/testsWithStdLib/coroutines/inlineCrossinline"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true);
|
||||
}
|
||||
|
||||
@TestMetadata("crossinlineSuspendValueParameter.kt")
|
||||
public void testCrossinlineSuspendValueParameter() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithStdLib/coroutines/inlineCrossinline/crossinlineSuspendValueParameter.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("inlineOrdinaryOfCrossinlineOrdinary.kt")
|
||||
public void testInlineOrdinaryOfCrossinlineOrdinary() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithStdLib/coroutines/inlineCrossinline/inlineOrdinaryOfCrossinlineOrdinary.kt");
|
||||
|
||||
compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsTestWithStdLibUsingJavacGenerated.java
Generated
-6
@@ -1559,12 +1559,6 @@ public class DiagnosticsTestWithStdLibUsingJavacGenerated extends AbstractDiagno
|
||||
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/diagnostics/testsWithStdLib/coroutines/inlineCrossinline"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true);
|
||||
}
|
||||
|
||||
@TestMetadata("crossinlineSuspendValueParameter.kt")
|
||||
public void testCrossinlineSuspendValueParameter() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithStdLib/coroutines/inlineCrossinline/crossinlineSuspendValueParameter.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("inlineOrdinaryOfCrossinlineOrdinary.kt")
|
||||
public void testInlineOrdinaryOfCrossinlineOrdinary() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithStdLib/coroutines/inlineCrossinline/inlineOrdinaryOfCrossinlineOrdinary.kt");
|
||||
|
||||
+6
@@ -6683,6 +6683,12 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
|
||||
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/coroutines/tailCallOptimizations"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JVM, true);
|
||||
}
|
||||
|
||||
@TestMetadata("crossinline.kt")
|
||||
public void testCrossinline() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/tailCallOptimizations/crossinline.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("inlineWithStateMachine.kt")
|
||||
public void testInlineWithStateMachine() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/tailCallOptimizations/inlineWithStateMachine.kt");
|
||||
|
||||
+6
@@ -6683,6 +6683,12 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
|
||||
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/coroutines/tailCallOptimizations"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JVM, true);
|
||||
}
|
||||
|
||||
@TestMetadata("crossinline.kt")
|
||||
public void testCrossinline() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/tailCallOptimizations/crossinline.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("inlineWithStateMachine.kt")
|
||||
public void testInlineWithStateMachine() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/tailCallOptimizations/inlineWithStateMachine.kt");
|
||||
|
||||
+12
@@ -7253,6 +7253,18 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest {
|
||||
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/coroutines/tailCallOptimizations"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JS, true);
|
||||
}
|
||||
|
||||
@TestMetadata("crossinline.kt")
|
||||
public void testCrossinline() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/tailCallOptimizations/crossinline.kt");
|
||||
try {
|
||||
doTest(fileName);
|
||||
}
|
||||
catch (Throwable ignore) {
|
||||
return;
|
||||
}
|
||||
throw new AssertionError("Looks like this test can be unmuted. Remove IGNORE_BACKEND directive for that.");
|
||||
}
|
||||
|
||||
@TestMetadata("inlineWithStateMachine.kt")
|
||||
public void testInlineWithStateMachine() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/tailCallOptimizations/inlineWithStateMachine.kt");
|
||||
|
||||
Reference in New Issue
Block a user